JavaEE:Sentinel使用

本文详细介绍了如何在JavaEE环境中使用Sentinel作为控制组件,涵盖Sentinel控制台Dashboard的启动、Sentinel与Apollo的集成、流量控制、熔断降级、系统保护规则的设定,以及在Dubbo、RocketMQ中的应用,还包括集群流控和Web应用从Apollo拉取Sentinel规则的配置方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:

Sentinel是控制组件,可实现流量控制、熔断降级、系统自适应保护等多个维度保护微服务的稳定性。

一、启动Sentinel控制台Dashboard(192.168.233.129):

1.使用官方默认sentinel-dashboard(退出后在管理页创建的规则会丢失):

(1)下载sentinel-dashboard-1.8.3.jar到D盘根目录:

https://github.com/alibaba/Sentinel/releases

(2)打开cmd启动控制台(设置用户和密码都为root):

D:\>java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=192.168.233.129:8080 -Dsentinel.dashboard.auth.username=root -Dsentinel.dashboard.auth.password=root -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.3.jar

2.搭建sentinel-dashboard(Push模式,能将管理页增加的规则持久化到Apollo):

Apollo安装(一、二章):

https://blog.youkuaiyun.com/a526001650a/article/details/123188040

(1)下载Sentinel-1.8.3.zip,解压后用IntelliJ IDEA打开:

https://github.com/alibaba/Sentinel/releases/tag/1.8.3

(2)删除apollo-openapi中<scope>test</scope>,在sentinel-dashboard模块pom.xml中(后面所有操作均在sentinel-dashboard模块中进行):

<!-- for Apollo rule publisher sample -->
<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-openapi</artifactId>
    <version>1.2.0</version>
</dependency>

(3)配置加载类,修改ApolloConfig(从test目录移到main目录):

package com.alibaba.csp.sentinel.dashboard.rule.apollo;
...
@Configuration
@ComponentScan("com.alibaba.csp.sentinel.dashboard.rule.apollo.*")//扫描自定义包下所有规则类
public class ApolloConfig implements InitializingBean {
    public static String url = "http://192.168.233.128:8070"; //apollo地址
    public static String appId = "apollo";                    //应用id
    public static String token = "76e317c68505c32a4d4adab1e8abf84ff5bf1f1a"; //token
    public static String env = "DEV";     //环境
    public static String nameSpace = "application"; //名称空间
    public static String account = "apollo";         //管理员账号
    public static String clusterName = "default";
    @Override
    public void afterPropertiesSet() throws Exception {
    }
    @Bean
    public ApolloOpenApiClient apolloOpenApiClient() { //供外部使用
        return ApolloOpenApiClient.newBuilder()
                .withPortalUrl(url)   //apollo服务器地址
                .withToken(token)     //token
                .build();
    }
    @Bean
    public Converter<List<FlowRuleEntity>, String> flowRuleEncoder() { //限流规则列表转json
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<FlowRuleEntity>> flowRuleDecoder() {//限流规则json转列表
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }
    @Bean
    public Converter<List<DegradeRuleEntity>, String> degradeRuleEncoder() { //熔断规则列表转json
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<DegradeRuleEntity>> degradeRuleDecoder() { //熔断规则json转列表
        return s -> JSON.parseArray(s, DegradeRuleEntity.class);
    }
    @Bean
    public Converter<List<SystemRuleEntity>, String> systemRuleEncoder() { //系统保护规则列表转json
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<SystemRuleEntity>> systemRuleDecoder() { //系统保护规则json转列表
        return s -> JSON.parseArray(s, SystemRuleEntity.class);
    }
    @Bean
    public Converter<List<AuthorityRuleEntity>, String> authorityRuleEncoder() { //访问控制规则列表转json
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<AuthorityRuleEntity>> authorityRuleDecoder() { //访问控制规则json转列表
        return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
    }
    @Bean
    public Converter<List<ParamFlowRuleEntity>, String> paramFlowRuleEncoder() { //热点限流规则列表转json
        return JSON::toJSONString;
    }
    @Bean
    public Converter<String, List<ParamFlowRuleEntity>> paramFlowRuleDecoder() { //热点参数限流规则json转列表
        return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
    }
}

(4)flowDataId工具类,修改ApolloConfigUtil(从test目录移到main目录):

public final class ApolloConfigUtil { //flowDataId工具类
    public static final String POSTFIX = "rules";
    private ApolloConfigUtil() {
    }
    public static String getFlowDataId(String appName) {  //限流DataId
        return String.format("%s-%s-%s", appName, "flow", POSTFIX);
    }
    public static String getDegradeDataId(String appName) { //熔断DataId
        return String.format("%s-%s-%s", appName, "degrade", POSTFIX);
    }
    public static String getSystemDataId(String appName) {  //系统保护DataId
        return String.format("%s-%s-%s", appName, "system", POSTFIX);
    }
    public static String getAuthorityDataId(String appName) { //访问控制DataId
        return String.format("%s-%s-%s", appName, "authority", POSTFIX);
    }
    public static String getParamFlowDataId(String appName) { //热点参数限流DataId
        return String.format("%s-%s-%s", appName, "paramFlow", POSTFIX);
    }
}

(5)配置限流规则发布,修改FlowRuleApolloPublisher(从test目录移到main目录,熔断等规则需要创建新的DynamicRulePublisher实现类):

package com.alibaba.csp.sentinel.dashboard.rule.apollo;
...
@Component("flowRuleApolloPublisher")
public class FlowRuleApolloPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> { //限流规则发布
    @Autowired
    private ApolloOpenApiClient apolloOpenApiClient;
    @Autowired
    private Converter<List<FlowRuleEntity>, String> converter;
    private FastDateFormat dateFormat = FastDateFormat.getInstance("yyyyMMdd HH:mm:ss");
    @Override
    public void publish(String appName, List<FlowRuleEntity> rules) {
        if (rules == null) {
            return;
        }
        String flowDataId = ApolloConfigUtil.getFlowDataId(appName);
        //(1)修改
        OpenItemDTO itemDTO = new OpenItemDTO();
        itemDTO.setKey(flowDataId);
        itemDTO.setValue(converter.convert(rules));
        itemDTO.setComment("修改时间: " + dateFormat.format(new Date()));  //描述
        itemDTO.setDataChangeCreatedBy(ApolloConfig.userId);    //修改人
        apolloOpenApiClient.createOrUpdateItem(ApolloConfig.appId,   //应用id
                ApolloConfig.env,         //环境
                ApolloConfig.clusterName,
                ApolloConfig.nameSpace,   //名称空间
                itemDTO);
        //(2)发布
        NamespaceReleaseDTO releaseDTO = new NamespaceReleaseDTO();
        releaseDTO.setEmergencyPublish(true);
        releaseDTO.setReleaseComment("发布时间: " + dateFormat.format(new Date()));  //描述
        releaseDTO.setReleasedBy(ApolloConfig.userId);    //发布人
        releaseDTO.setReleaseTitle("发布Key-Value");  //标题
        apolloOpenApiClient.publishNamespace(ApolloConfig.appId,  //应用id
                ApolloConfig.env,        //环境
                ApolloConfig.clusterName,
                ApolloConfig.nameSpace,  //名称空间
                releaseDTO);
    }
}

(6)配置限流规则获取,修改FlowRuleApolloProvider(从test目录移到main目录,熔断等规则需要创建新DynamicRuleProvider实现类):

package com.alibaba.csp.sentinel.dashboard.rule.apollo;
...
@Component("flowRuleApolloProvider")
public class FlowRuleApolloProvider implements DynamicRuleProvider<List<FlowRuleEntity>> { //限流规则获取
    @Autowired
    private ApolloOpenApiClient apolloOpenApiClient;
    @Autowired
    private Converter<String, List<FlowRuleEntity>> converter;
    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
        String flowDataId = ApolloConfigUtil.getFlowDataId(appName);
        OpenNamespaceDTO namespaceDTO = apolloOpenApiClient.getNamespace(ApolloConfig.appId, //Apollo网页上创建的应用appId
                ApolloConfig.env,        //环境
                ApolloConfig.clusterName,
                ApolloConfig.nameSpace); //名称空间
        String rules = namespaceDTO
                .getItems()
                .stream()
                .filter(p -> p.getKey().equals(flowDataId))  //过滤
                .map(OpenItemDTO::getValue)
                .findFirst()
                .orElse("");
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }
}

(7)配置限流Controller类,修改FlowControllerV1中使用Provider与Publisher实现类(其他规则修改其他Controller):

package com.alibaba.csp.sentinel.dashboard.controller;
...    //保持原有代码
@RestController
@RequestMapping(value = "/v1/flow")
public class FlowControllerV1 {
    ...    //保持原有代码
    @Autowired
    private FlowRuleApolloProvider flowRuleApolloProvider;
    @Autowired
    private FlowRuleApolloPublisher flowRuleApolloPublisher;
    @GetMapping("/rules")
    @AuthAction(PrivilegeType.READ_RULE)
    public Result<List<FlowRuleEntity>> apiQueryMachineRules(...) {
        ...    //保持原有代码
        try {
            List<FlowRuleEntity> rules = flowRuleApolloProvider.getRules(app); //修改获取规则的代码为自已的
            rules = repository.saveAll(rules);
            return Result.ofSuccess(rules);
        } catch (Throwable throwable) {
            logger.error("Error when querying flow rules", throwable);
            return Result.ofThrowable(-1, throwable);
        }
    }
    ...    //保持原有代码
    @PostMapping("/rule")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<FlowRuleEntity> apiAddFlowRule(...) {
        ...    //保持原有代码
        try {
            entity = repository.save(entity);
            publishRules(entity.getApp());   //替换成自已的publishRules方法
            return Result.ofSuccess(entity);
        } catch (Throwable t) {
            Throwable e = t instanceof ExecutionException ? t.getCause() : t;
            logger.error("Failed to add new flow rule, app={}, ip={}", entity.getApp(), entity.getIp(), e);
            return Result.ofFail(-1, e.getMessage());
        }
    }
    @PutMapping("/save.json")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<FlowRuleEntity> apiUpdateFlowRule(...) {
        ...    //保持原有代码
        try {
            entity = repository.save(entity);
            if (entity == null) {
                return Result.ofFail(-1, "save entity fail: null");
            }
            publishRules(entity.getApp());   //替换成自已的publishRules方法
            return Result.ofSuccess(entity);
        } catch (Throwable t) {
            Throwable e = t instanceof ExecutionException ? t.getCause() : t;
            logger.error("Error when updating flow rules, app={}, ip={}, ruleId={}", entity.getApp(),
                    entity.getIp(), id, e);
            return Result.ofFail(-1, e.getMessage());
        }
    }
    @DeleteMapping("/delete.json")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<Long> apiDeleteFlowRule(Long id) {
        ...    //保持原有代码
        try {
            publishRules(oldEntity.getApp());  //替换成自已的publishRules方法
            return Result.ofSuccess(id);
        } catch (Throwable t) {
            Throwable e = t instanceof ExecutionException ? t.getCause() : t;
            logger.error("Error when deleting flow rules, app={}, ip={}, id={}", oldEntity.getApp(),
                    oldEntity.getIp(), id, e);
            return Result.ofFail(-1, e.getMessage());
        }
    }
    private void publishRules(String app) {//自定义发布规则方法
        List<FlowRuleEntity> rules = repository.findAllByApp(app);
        flowRuleApolloPublisher.publish(app, rules);
    }
}

修改其他规则Controller同样代码:

熔断规则Controller:
com.alibaba.csp.sentinel.dashboard.controller.DegradeController
系统保护规则Controller:
com.alibaba.csp.sentinel.dashboard.controller.SystemController
访问控制规则Controller:
com.alibaba.csp.sentinel.dashboard.controller.AuthController
热点参数限流规则Controller:
com.alibaba.csp.sentinel.dashboard.controller.ParamFlowRuleController

(8)jar包方式运行,展开IntelliJ IDEA右侧Maven -> 找到sentinel-dashboard模块Lifecycle菜单,分别双击clean、install,将target目录下生成的sentinel-dashboard.jar上传到centos7,并使用java命令启动:

[root@localhost ~]# java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=192.168.233.129:8080 -Dsentinel.dashboard.auth.username=root -Dsentinel.dashboard.auth.password=root -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

3.访问首页看效果:

http://192.168.233.129:8080/#/dashboard/home

二、使用Sentinel:

1.添加sentinel依赖:

<dependencies>
    <!-- sentinel依赖 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-core</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!-- 接入控制台实时监控 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-transport-simple-http</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!-- 注解埋点支持 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-annotation-aspectj</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!-- 热点参数限流 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-parameter-flow-control</artifactId>
        <version>1.8.3</version>
    </dependency>
</dependencies>

2.定义规则,在Application中加载:

@EnableAsync  //开启异步调用
@SpringBootApplication
public class SentinelApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelApplication.class);
        loadFlowRule();             //(1)加载流量控制规则
        //loadDegradeRule();          //(2)加载熔断降级规则
        //loadSystemProtectRule();    //(3)系统保护规则
        //loadAuthorityRule();        //(4)访问控制规则
        //loadParamFlowRule();        //(5)热点参数限流规则
    }
}

(1)流量控制规则:

private static void loadFlowRule() {  //(1)流量控制规则
    List<FlowRule> rules = new ArrayList<>();
    FlowRule fr = new FlowRule();
    fr.setResource("资源名1");                     //指定资源名
    fr.setGrade(RuleConstant.FLOW_GRADE_QPS);     //限流阈值类型,QPS模式(默认) / 线程数模式FLOW_GRADE_THREAD(统计线程数,超过拒绝)
    fr.setCount(20);                              //限流阈值,此处QPS最大为20
    fr.setLimitApp("default");                    //调用来源,default为不区分调用来源
    fr.setStrategy(RuleConstant.STRATEGY_DIRECT); //调用关系限流策略:直接(默认)、关联STRATEGY_RELATE、链路STRATEGY_CHAIN
    //fr.setRefResource("来源名称");                //setStrategy为关联或链路时需要设置
    fr.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); //QPS超过阈值时的流控效果(0直接拒绝(默认) / 1冷启动缓慢增加 / 2匀速通过)
    rules.add(fr);
    FlowRuleManager.loadRules(rules);
}

(2)熔断降级规则:

private static void loadDegradeRule() { //(2)熔断降级规则
    List<DegradeRule> rules = new ArrayList<>();
    DegradeRule dr = new DegradeRule("资源名1");     //指定资源名
    dr.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType()); //熔断策略:慢调用比例SLOW_REQUEST_RATIO(默认) /异常比例ERROR_RATIO / 异常数ERROR_COUNT
    dr.setCount(0.7);                                          //阈值为70%错误率,超出时熔断。必须MinRequestAmount同时满足才会熔断
    dr.setMinRequestAmount(100);                               //熔断触发的最小请求数,数小于该值时Count超出阈值也不会熔断
    dr.setStatIntervalMs(30000);                               //统计时长,单位毫秒
    dr.setTimeWindow(10);                                      //熔断时长,单位为秒
    //dr.setSlowRatioThreshold(1.0D);                          //慢调用比例阈值
    rules.add(dr);
    DegradeRuleManager.loadRules(rules);
    //监听熔断开关事件
    EventObserverRegistry.getInstance().addStateChangeObserver("logging",
            (prevState, newState, rule, snapshotValue) -> {
                if (newState == CircuitBreaker.State.OPEN) { //开启时
                } else { //半开或关闭时
                }
            });
}

(3)系统保护规则:

private static void loadSystemProtectRule() { //(3)系统保护规则
    List<SystemRule> rules = new ArrayList<>();
    SystemRule sr = new SystemRule();
    sr.setHighestSystemLoad(10);        //系统load1超过阈值(推荐值=CPU核心数*2.5),且并发数超过容量时才会触发保护,仅对Linux/Unix-like机器生效
    sr.setAvgRt(2000);                  //入口流量平均响应时间,单位毫秒
    sr.setMaxThread(100);               //入口流量最大并发数
    sr.setQps(20);                      //入口请求最大QPS数量
    sr.setHighestCpuUsage(0.9);         //CPU使用率,值范围:0.0-1.0
    rules.add(sr);
    SystemRuleManager.loadRules(rules);
}

(4)访问控制规则:

private static void loadAuthorityRule() { //(4)访问控制规则
    List<AuthorityRule> rules = new ArrayList<>();
    AuthorityRule ar = new AuthorityRule();
    ar.setResource("资源名1");                       //指定资源名
    ar.setLimitApp("appA,appB");                     //配置请求来源名单,多个时用逗号分隔
    ar.setStrategy(RuleConstant.AUTHORITY_WHITE);    //限制模式:白名单AUTHORITY_WHITE(默认) / 黑名单AUTHORITY_BLACK
    AuthorityRuleManager.loadRules(rules);
}

(5)热点参数限流规则:

private static void loadParamFlowRule() { //(5)热点参数限流规则
    List<ParamFlowRule> rules = new ArrayList<>();
    ParamFlowRule pfr = new ParamFlowRule("资源名1")   //指定资源名(必填)
            .setGrade(RuleConstant.FLOW_GRADE_QPS)               //限流阈值类型,默认QPS模式
            .setParamIdx(0)                                      //热点参数的索引(必填),对应SphU.entry(xxx, 参数0, 参数1)的参数索引
            .setCount(5)                                         //限流阈值(必填)
            .setDurationInSec(1)                                 //统计窗口时间长度(单位秒),默认1秒
            .setControlBehavior(1)                               //流控效果:快速失败(默认) / 匀速排队
            .setMaxQueueingTimeMs(0)                             //最大排队等待时长(单位毫秒)(仅在匀速排队模式生效),默认0毫秒
            .setClusterMode(false);                              //是否是集群参数流控规则,默认false
          //.setClusterConfig(...)                               //集群流控相关配置
    //对指定类型的参数,设置独立的限流(覆盖全局)
    ParamFlowItem item = new ParamFlowItem().setObject("参数0")  //使用SphU.entry("资源名1", EntryType.IN, 1, "参数0")传入热点参数
            .setClassType(int.class.getName())
            .setCount(10);
    pfr.setParamFlowItemList(Collections.singletonList(item));   //例外项,对指定参数值单独设置限流阈值
    rules.add(pfr);
    ParamFlowRuleManager.loadRules(rules);
}

3.使用规则(定义资源),保护业务逻辑:

(1)方式1,try-catch方式:

@RequestMapping("/user1")
public String user1(String userNo) {
    try (Entry entry = SphU.entry("资源名1")) { //热点参数限流时使用SphU.entry("资源名1", EntryType.IN, 1, "参数1")传入热点参数
        //此处为被保护的逻辑
    } catch (BlockException ex) {
        Tracer.trace(ex);  //记录业务异常
        //此处处理被限流/降级的逻辑
    } //传入热点参数后,结束时需要手动调用entry.exit()
    return "...";
}

(2)方式2,if-else方式:

@RequestMapping("/user2")
public String user2(String userNo) {
    if (SphO.entry("资源名1")) {
        try {
            //此处为被保护的逻辑
        } finally {
            SphO.exit();
        }
    } else {
        //此处处理被限流/降级的逻辑
    }
    return "user2";
}

(3)方式3,注解方式:

@RequestMapping("/user3")
@SentinelResource(blockHandler = "blockHandler") //需要传热点参数时,放在形参上,同SphU.entry("资源名1", EntryType.IN, 1, "userNo")
public String user3(String userNo) {
    //此处为被保护的逻辑
    return "...";
}
public String blockHandler(String id, BlockException ex) { //此函数会因user3函数被限流/降级/系统保护时触发
    Tracer.trace(ex);  //记录业务异常
    //此处处理被限流/降级的逻辑
    return "...";
}

(4)方式4,异步调用方式:

@RequestMapping("/user4")
public String user4(String userNo) {
    try {
        AsyncEntry entry = SphU.asyncEntry("资源名1");
        doAsync(userNo, entry);  //执行异步方法
    } catch (BlockException ex) {
        //此处处理被限流/降级的逻辑
    }
    return "...";
}
@Async
private void doAsync(String userNo, AsyncEntry entry) {
    try {
        //此处为被保护的逻辑
    } finally {
        entry.exit();  //异步结束时调用exit方法
    }
}

4.IntelliJ IDEA方式启动,Edit Configurations -> 左侧Application中选中ApolloApplication,右侧Configuration选项卡中,在VM options中填入:

-Dproject.name=sentinel -Dcsp.sentinel.dashboard.server=192.168.233.129:8080 -Dcsp.sentinel.api.port=8719

三、开源框架集成Sentinel,详细见如下官方文档:

https://sentinelguard.io/zh-cn/docs/open-source-framework-integrations.html

1.Dubbo集成Sentinel:

(1)添加sentinel+dubbo组合依赖(控),在pom文件中:

<!-- ...省略控制台依赖+注解埋点依赖 -->
<!-- sentinel+dubbo依赖 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-apache-dubbo-adapter</artifactId>
    <version>1.8.3</version>
</dependency>

(2)配置限流粒度(可配置为接口或方法级别),在Application.main中加载:

private static void loadFlowRule() {  //流量控制规则
    List<FlowRule> rules = new ArrayList<>();
    FlowRule fr = new FlowRule();
    fr.setResource("com.yyh.dubbosentinel.UserService:getUser(java.lang.String)"); //方法级,资源名规则:接口全名.方法名(形参类型)
    //fr.setResource("com.yyh.dubbosentinel.UserService");                         //类级,资源名规则:接口全名
    ...  //省略其他配置
    FlowRuleManager.loadRules(rules);
}

(3)注册dubbo限流/降级回调,在Application.main中加载:

private static void registerDubboFallback() { //注册dubbo全局回调
    DubboAdapterGlobalConfig.setConsumerFallback(new DubboFallback(){
        @Override
        public Result handle(Invoker<?> invoker, Invocation invocation, BlockException e) {
            //此处处理被限流/降级的逻辑
            return null;
        }
    });
}

(4)关闭某个Filter,在Application中:

@Bean
public ConsumerConfig consumerConfig() {
    ConsumerConfig consumerConfig = new ConsumerConfig();
    consumerConfig.setFilter("-sentinel.dubbo.consumer.filter");
    return consumerConfig;
}

2.RocketMQ集成Sentinel:

(1)添加sentinel依赖(见第二章),添加rocketmq-client依赖:

<!-- 导入rocketmq依赖包 -->
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.2.0</version>
</dependency>

(2)配置限流规则,在Application.main中加载:

private static void loadFlowRule() {  //(1)流量控制规则
    FlowRule rule = new FlowRule();
    rule.setResource("组名:topic名称");                                   //资源名规则:组名:topic名称
    rule.setCount(5);                                                     //限流阈值,此处QPS最大为每秒允许通过5个
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);                           //限流模式为QPS模式
    rule.setLimitApp("default");                                          //调用来源,default为不区分调用来源
    rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);  //QPS超过阈值时的流控效果为匀速通过
    rule.setMaxQueueingTimeMs(5 * 1000);                                  //最大排队等待时长为5秒
    FlowRuleManager.loadRules(Collections.singletonList(rule));
}

(3)处理消息的时候手动埋点,在Application.main中加载(官方例子):

private static Map<MessageQueue, Long> mMap = new HashMap<>();
private static void pullMessage() throws MQClientException {
    DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("组名");
    consumer.setNamesrvAddr("192.168.233.128:9876");  //RocketMQ服务器地址
    consumer.start();
    Set<MessageQueue> mqs = new HashSet<>();
    try {
        mqs = consumer.fetchSubscribeMessageQueues("Topic名");
    } catch (Exception e) {
        e.printStackTrace();
    }
    for (MessageQueue mq : mqs) {
        SINGLE_MQ:
        while (true) {
            try {
                PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                if (pullResult.getMsgFoundList() != null) {
                    for (MessageExt msg : pullResult.getMsgFoundList()) {
                        doMessage(msg);
                    }
                }
                long nextOffset = pullResult.getNextBeginOffset();
                putMessageQueueOffset(mq, nextOffset);
                consumer.updateConsumeOffset(mq, nextOffset);
                switch (pullResult.getPullStatus()) {
                    case NO_NEW_MSG:
                        break SINGLE_MQ;
                    case FOUND:
                    case NO_MATCHED_MSG:
                    case OFFSET_ILLEGAL:
                    default:
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    consumer.shutdown();
}
private static void doMessage(MessageExt message) {
    Entry entry = null;
    try {
        ContextUtil.enter("组名:topic名");
        entry = SphU.entry("组名:topic名", EntryType.OUT);
        //此处为被保护的逻辑,如处理消息
    } catch (BlockException ex) {
        //此处处理被限流/降级的逻辑
    } finally {
        if (entry != null) {
            entry.exit();
        }
        ContextUtil.exit();
    }
}
private static long getMessageQueueOffset(MessageQueue mq) {
    Long offset = mMap.get(mq);
    if (offset != null) {
        return offset;
    }
    return 0;
}
private static void putMessageQueueOffset(MessageQueue mq, long offset) {
    mMap.put(mq, offset);
}

四、集群流控:

1.Server端(独立部署):

(1)添加Servert端依赖:

<!-- 添加Servert端依赖 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-cluster-server-default</artifactId>
    <version>1.8.3</version>
</dependency>

(2)启动服务端,在Application.main中加载:

private static void startClusterServer() { //启动集群流控服务端
    try {
        ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();
        ClusterServerConfigManager.loadGlobalTransportConfig(new ServerTransportConfig()
                .setIdleSeconds(600)  //闲置时间
                .setPort(9999));  //服务端口
        ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton("sentinel-cluster-server"));  //服务名称
        tokenServer.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.Client端:

(1)添加Client端依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-cluster-client-default</artifactId>
    <version>1.8.3</version>
</dependency>

(2)可以通过API将当前模式置为客户端模式:

http://192.168.233.128:9999/setClusterMode?mode=0

五、Web应用从Apollo拉取Sentinel规则:

1.添加Apollo+Sentinel依赖:

<dependencies>
    <!-- 从Apollo拉取Sentinel规则的依赖 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-apollo</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!-- 接入控制台实时监控 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-transport-simple-http</artifactId>
        <version>1.8.3</version>
    </dependency>
</dependencies>

2.配置连接Apollo:

...
app:
  id: apollo     #apollo应用ID(必须与Apollo网页上创建项目时定义的应用Id一致)
apollo:
  meta: http://192.168.233.128:8080  #apollo服务器地址
  bootstrap:
    enabled: true   #注入默认application命名空间
    namespaces: application  #可以注入多个命名空间,以逗号分隔

3.Application中注册Apollo创建规则的回调事件,接收并加载规则:

@SpringBootApplication
public class SentinelApolloApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelApolloApplication.class);
        String namespaceName = "application";  //application为Apollo命名空间
        String ruleKey = "sentinelapollo-flow-rules";             //sentinelapollo-flow-rules为Apollo页面Key/Value列表的Key名(value为规则json,格式见defaultRuleValue)
        String defaultRuleValue = "\"[{\\\"grade\\\":1,\\\"count\\\":1,\\\"resource\\\":\\\"资源名1\\\",\\\"limitApp\\\":\\\"default\\\",\\\"strategy\\\":\\\"0\\\"}]\""; //Apollo连接失败时使用的默认规则
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName, ruleKey, defaultRuleValue, new Converter() {
            @Override
            public List<FlowRule> convert(Object ruleJson) { //Apollo页面上创建规则时,此方法会收到回调
                System.out.println("ruleJson: " + ruleJson);
                return JSON.parseObject((String) ruleJson, new TypeReference<List<FlowRule>>() {});  //将规则json解析为列表
            }
        });
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }
}

4.使用拉取的规则,保护业务逻辑:

@RestController
public class UserController {
    @RequestMapping("/user1")
    public String user1(String userNo) { //(1)方式1,try-catch方式
        try (Entry entry = SphU.entry("资源名1")) {
            //此处为被保护的逻辑
        } catch (BlockException ex) {
            Tracer.trace(ex);  //记录业务异常
            //此处处理被限流/降级的逻辑
        }
        return "测试完成";
    }
}

5.也可以手动添加规则,在Apollo应用Key/Value中:

(1)进入创建的应用,点击Key/Value列表的右上角"新增配置",添加Key和Value后,点发布生效:

 (2)在Key中输入创建ApolloDataSource时ruleKey名(此处为myRule),在Value中输入规则json(json所有key必须与所属规则对象的属性名一致):

 6.IntelliJ IDEA方式启动Web应用,Edit Configurations -> 左侧Application中选中ApolloApplication,右侧Configuration选项卡中,在VM options中填入:

-Dapollo.meta=http://192.168.233.128:8080 -Denv=dev -Dproject.name=sentinelapollo -Dcsp.sentinel.dashboard.server=192.168.233.129:8080 -Dcsp.sentinel.api.port=8719

<think>嗯,用户想了解Java EE的学习路线,我得先理清楚Java EE现在的体系。首先,Java EE已经改名为Jakarta EE了,不过大家可能还是习惯叫Java EE,所以需要提到这一点,避免混淆。然后,用户可能是刚开始学习Java,或者已经有一定基础,想转企业级开发,得从基础开始讲起。 首先,Java基础肯定是必须的,比如面向对象、集合、IO这些。然后是数据库,MySQL和JDBC,这部分是后端的基础。接着是Web基础,HTML、CSS、JavaScript,虽然前端不是重点,但至少要懂基础。Servlet和JSP是Java EE的核心,必须详细讲,包括生命周期、Filter、Listener这些。 接下来框架部分,Spring家族现在是主流,Spring Boot简化了配置,可能比传统的Spring MVC更推荐先学。还有ORM框架,比如Hibernate和MyBatis,用户需要了解两者的区别和应用场景。微服务现在很火,Spring Cloud相关组件也得介绍,但可能需要放在后面,作为进阶内容。 工具方面,Maven和Git是必备的,构建和版本控制。服务器如Tomcat、Jetty也需要熟悉。测试部分,JUnit和Postman对保证代码质量很重要,不能漏掉。 学习资源方面,官方文档、书籍、在线课程都需要推荐,比如《Head First Servlet & JSP》和Spring的官方指南。项目实战是关键,通过实际项目巩固知识,可以列举一些常见的项目类型,比如电商、管理系统。 注意事项里要强调动手实践,理解原理,关注社区变化,比如Jakarta EE的更新。最后,路线分阶段,从基础到进阶,再到深入,逐步推进。可能用户的实际水平和目标不同,需要灵活调整路线。 要确保内容结构清晰,分点列出,重点突出,同时语言口语化,避免太技术化的术语,让初学者容易理解。还要检查有没有遗漏的重要知识点,比如容器技术Docker,或者安全方面的知识,是否需要加入?不过可能放在进阶部分更合适,避免信息过载。 总之,整理出一个循序渐进的学习路径,覆盖从基础到框架再到部署和微服务的整个流程,帮助用户建立完整的知识体系,并提供学习资源建议和实战项目推荐,最后提醒注意事项,鼓励持续学习。</think>Java EE(现更名为 **Jakarta EE**)是 Java 企业级应用开发的核心技术栈,适合构建复杂、高并发的分布式系统。以下是一份系统的学习路线建议,涵盖从基础到进阶的关键知识点,结合当前主流技术趋势(如微服务、云原生等): --- ### **一、基础阶段** #### 1. **Java 核心基础** - 语法基础:数据类型、流程控制、面向对象(封装、继承、多态)、异常处理。 - 核心类库:集合框架(List/Set/Map)、IO/NIO、多线程(Thread、锁机制)、反射、泛型。 - 开发工具:IDEA/Eclipse、Maven/Gradle(依赖管理)、Git(版本控制)。 #### 2. **数据库与 SQL** - **关系型数据库**:MySQL/Oracle,掌握 SQL 语法(CRUD、事务、索引、连接查询)。 - **JDBC**:数据库连接、PreparedStatement、连接池(HikariCP、Druid)。 #### 3. **Web 基础** - 前端基础:HTML/CSS/JavaScript(了解即可,非前端重点)。 - HTTP 协议:请求/响应结构、状态码、Cookie/Session 原理。 - 后端入门:Servlet(生命周期、Request/Response)、JSP(已逐渐被模板引擎取代,了解即可)。 --- ### **二、核心框架与技术** #### 1. **Spring 生态** - **Spring Framework**:IoC(控制反转)、AOP(面向切面)、Spring MVC(Web 开发)。 - **Spring Boot**:自动化配置、Starter 依赖、Restful API 开发、集成 MyBatis/JPA。 - **Spring Security**:认证与授权、OAuth2/JWT(分布式安全方案)。 #### 2. **ORM 框架** - **MyBatis**:XML/注解配置、动态 SQL、关联映射。 - **JPA/Hibernate**:对象关系映射(ORM)、JPQL、Hibernate 缓存机制。 #### 3. **中间件与工具** - **Redis**:缓存、分布式锁、数据结构(String/Hash/List)。 - **消息队列**:RabbitMQ/Kafka,实现异步解耦与削峰填谷。 - **Elasticsearch**:全文检索、日志分析(可选,根据需求学习)。 --- ### **三、进阶与微服务** #### 1. **分布式与微服务** - **Spring Cloud** 全家桶: - 服务注册与发现:Eureka/Nacos。 - 负载均衡:Ribbon/OpenFeign。 - 配置中心:Spring Cloud Config/Nacos。 - 服务熔断:Hystrix/Sentinel- 网关:Spring Cloud Gateway/Zuul。 - **Dubbo**:RPC 框架(可选,传统分布式架构常用)。 #### 2. **容器化与 DevOps** - **Docker**:镜像与容器管理、Dockerfile 编写。 - **Kubernetes**:Pod/Deployment/Service 概念(企业级容器编排)。 - **CI/CD**:Jenkins/GitLab CI,实现自动化部署。 #### 3. **云原生技术** - 服务网格:Istio(微服务治理)。 - 无服务器架构:Serverless(如 AWS Lambda)。 --- ### **四、项目实战与经验积累** 1. **实战项目推荐**: - 电商系统:商品管理、订单流程、支付对接。 - 权限管理系统:RBAC 模型、动态菜单。 - 秒杀系统:高并发设计(限流、缓存、队列)。 - 微服务项目:拆分业务模块,集成 Spring Cloud。 2. **学习资源**: - 书籍:《Spring 实战》《深入理解 Java 虚拟机》《凤凰架构》。 - 文档:[Spring 官方文档](https://spring.io/)、[阿里巴巴 Java 开发手册](https://github.com/alibaba/p3c)。 - 视频:B 站慕课网、极客时间专栏。 --- ### **五、注意事项** 1. **避免“过度学框架”**:先理解底层原理(如 Servlet 生命周期、Spring AOP 实现机制)。 2. **关注社区动态**:Jakarta EE 更新、Spring 6 新特性(如响应式编程)。 3. **参与开源项目**:GitHub 上学习优秀代码,积累工程经验。 --- ### **学习路线总结** ``` Java 基础 → 数据库 → Web 基础 → Spring → 中间件 → 微服务 → 云原生 → 项目实战 ``` 根据个人目标调整方向(如传统企业应用侧重 Jakarta EE,互联网企业侧重 Spring Cloud + 云原生)。保持持续学习,结合实际项目深化理解!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值