Dubbo线程模型与Sentinel运用

案例回放

  • 用户登录全部流量接入极验校验后,导致请求到第三方极验公司那边个别请求很慢
    在这里插入图片描述
  • 与第三方公司定位后,还是存在问题(有所好转,但不明显)
  • 考虑到不能完全依靠第三方处理,可以通过Dubbo线程池处理
  • 个别服务慢,导致占用线程池瞬间上升,其他服务调用也越来越慢,影响整体可用性

增加线程池大小,设置为可伸缩线程池

  • 线程模型参考官网介绍
  • 配置示例如下
    在这里插入图片描述
  • dubbo默认将所有消息都派发到线程池,并且是固定200个线程
  • 考虑到当前应用流量大 这里配置500,并且是可伸缩的
# 这里可以用配置name 是为了后续配置多个线程池组使用的
<dubbo:protocol id="dubbo" name="dubbo" port="21888" threadpool="limited" threads="500" queues="0"/>
  • 上线后,还是存在问题,只是出现问题的时间离应用部署时间更久一点而已
  • 接下来尝试配置多个线程池处理

配置多个Dubbo线程池

  • 配置多个线程池(dubbo-common.xml)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:protocol id="dubbo" name="dubbo" port="21888" threadpool="limited" threads="500" queues="0"/>
    <!-- http调用极验服务存在超时情况 则将请求延迟服务单独出来 单独配置线程池规则 -->
    <dubbo:protocol id="captcha" name="dubbo" port="21889" dispatcher="message" threadpool="fixed"
                    threads="${captcha.threads:100}"/>
</beans>
  • 考虑到线上可能存在线程不够用,此处设置为配动态配置的(但是需要重启应用才能生效)
  • 在启动类中引入dubbo-comm.xml即可
@SpringBootApplication
@ImportResource(locations = {"classpath:/dubbo-common.xml"})
public class UserApplication {

    /**
     * 程序入口
     *
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(UserApplication.class);
        springApplication.run(args);
    }
}
  • 需要在类上引入新定义的线程池组
@com.alibaba.dubbo.config.annotation.Service(protocol = {"captcha"}, timeout = 2000)
public class CaptchaServiceImple {}
  • 上线后问题还是存在,只是没这么频繁
  • 之前看SpringCloud书籍,看可以通过Hystrix解决
  • 然后网上一搜,阿里也出了一个,而且控制的更细
  • Hystrix与Sentinel区别

使用Sentinel

/**
 * SentinelConfig
 *
 * @author weigang
 * @create 2019-04-02
 **/
@Configuration
public class SentinelConfig {
	
	/**
     * 接入配置中心,可以动态配置count、times和window等
     */
    @Autowired
    private AutoLimitService autoLimitService;

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

    /**
     * 初始化降级策略规则
     */
    @PostConstruct
    public void initDegradeRule() {
        List<DegradeRule> rules = Lists.newArrayList();
        List<String> resList = Lists.newArrayList("captcha");

        DegradeRule rule;
        for (String resource : resList) {
            rule = new DegradeRule();
            rule.setResource(resource);
            /**
             * RuleConstant.DEGRADE_GRADE_RT
             * 当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,资源进入准降级状态。
             * 接下来如果持续进入 5 个请求,它们的 RT 都持续超过这个阈值,那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,
             * 对这个方法的调用都会自动地返回(抛出 DegradeException)
             *
             * RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO
             * 当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,
             * 即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。
             * 异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%
             *
             * RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT
             * 当资源近1分钟的异常数目超过阈值之后会进行熔断
             *
             * 注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。
             * 为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常
             * 参考文档: https://github.com/alibaba/Sentinel/wiki/熔断降级
             */
            //rule.setCount(autoLimitService.getSentinelServiceInvokeTimeout());

            /**
             * 平均响应时间 (DEGRADE_GRADE_RT)
             * 异常比例(DEGRADE_GRADE_EXCEPTION_RATIO)
             * 异常数(DEGRADE_GRADE_EXCEPTION_COUNT)
             */
            rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);

            /**
             * 那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,
             * 对这个方法的调用都会自动地返回(抛出 DegradeException) 默认调用 @SentinelResource 注解的 fallback 属性对应的方法
             */
            //rule.setTimeWindow(autoLimitService.getSentinelTimeWindow());

            rule.setCount(autoLimitService.getSentinelServiceInvokeTimeoutCaptcha());
            rule.setTimeWindow(autoLimitService.getSentinelTimeWindowCaptcha());
            rules.add(rule);
        }

        DegradeRuleManager.loadRules(rules);
    }
}
  • 在实现类上,增加注释
@SentinelResource(value = "captcha", fallback = "needCaptchaFallback")
@Override
public Result<***Out> needCaptcha(Request<***In> request) {
}
  • 并且同时定义一个方法(方法名为上面fallback定义名称,入参和出参相同,是不是和Hystrix很像呀)
public Result<***Out> needCaptchaFallback(Request<***In> request) {
	return ResultUtils.commonServiceTimeOut("captcha needCaptchaFallback", request);
}
  • 这样就完全满足我们的需求了。各个业务都调用正常,个别服务调用调用超时也不影响其他服务调用

参考文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章