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);
}
  • 這樣就完全滿足我們的需求了。各個業務都調用正常,個別服務調用調用超時也不影響其他服務調用

參考文章

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