<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ***** # 1. 雪崩效應 ``` 服務雪崩效應是一種因“服務提供者的不可用”(原因)導致“服務調用者不可用”(結果),并將不可用逐漸放大的現象 ``` ``` 形成原因 服務雪崩的過程可以分為三個階段: 服務提供者不可用; 重試加大請求流量; 服務調用者不可用; 服務雪崩的每個階段都可能由不同的原因造成,總結如下: ``` ![](https://img.kancloud.cn/e4/e8/e4e8fd226368a0a3d9e2b08d4738b385_1048x424.png) **應對策略** ![](https://img.kancloud.cn/0c/ba/0cbaa264138e77b150d4be1277ac9e71_739x560.png) # 2. 常見容錯方案 ``` 1. 超時: 釋放夠快就不會掛掉 2. 限流: 只有一碗的飯量,給我三碗我吃不下 3. 倉壁模式: 如每個controller都有自己比較小的線程池,當線程池滿了就會拒絕請求(線程池本身有拒絕機制),不把雞蛋放在一個籃子里 4. 斷路器模式: 監控+開關, 如對API進行監控,5s以內錯誤率/錯誤次數達到一定的閾值,就跳閘,不去調用其他服務,并且有半開機制 ``` **斷路器模式:** ![](https://img.kancloud.cn/a3/a1/a3a16d612ed87c387e8ef0af999dc47c_742x432.png) # 3. 使用Sentinel實現容錯 ``` 1. Sentinel是什么? 參考 [http://blog.didispace.com/spring-cloud-alibaba-sentinel-1/] ``` ``` 2. 應用整合Sentinel (熔斷/ 降級) 加依賴 compile("org.springframework.cloud:spring-cloud-starter-alibaba-sentinel") ``` # 4. Sentinel控制臺 ``` 下載sentinel, 1.6.0版本之后才有登錄頁面 啟動 java -jar sentinel-dashboard-1.6.0.jar 登錄 http://localhost:8080 用戶名/密碼=[sentinel/sentinel] ``` ![](https://img.kancloud.cn/3c/0a/3c0a129c01b42c0f4e0d4109b091bfb1_1083x521.png) ``` 添加配置: spring: cloud: sentinel: transport: #指定sentinel 控制臺地址 dashboard: localhost:8080 ``` ![](https://img.kancloud.cn/3a/b5/3ab54d6c7a4abebe0e6afbfeae97ab66_828x482.png) ## 4.1 流控規則 ``` 資源名: 控制臺自動填寫我們請求的路徑(唯一的名稱) 針對來源: 比如有倆個服務(A / B)調用用戶中心,可以為A設置200QPS, B設置300QPS,針對來源設置不同值,(default默認表示不區分來源) 閾值類型: QPS表示當達到QPS閾值時就是限流; 線程數表示當達到線程數的閾值時就是限流 是否集群: 表示是否支持集群模式 流控模式: 直接模式: 如把QPS設置成1, 當請求達到1次就限流,會報Blocked by sentinel (flow limiting)的異常 關聯模式: [關聯資源:當關聯資源達到一定值時就限流自己],比如關聯資源設置為/users/getUerInfo,請求路徑達到閾值就限流當前資源 使用場景: 有倆個API(查詢/修改),衡量優先讀還是優先修改,如優先修改,關聯資源處設置成[修改的API],資源名處設置成[查詢的API] 鏈路模式: [只記錄指定鏈路上的流量]API級別 流控效果: 快速失敗: 直接拋異常 WarmUp: 預熱, 根據codefactor(冷加載因子|默認3)的值,從閾值/codeFactor,經過預熱時長,才達到設置的QPS閾值 如 閾值設置為100,預熱時長設置為10s, 那么就會 100/3 作為最初閾值,經過10s后才達到100限流 場景: 如秒殺服務平時流量不會很高,但有活動的某一瞬間流量激增,不處理服務會掛掉,預熱可以讓流量緩慢的增加 排隊等待: 勻速排隊,讓請求以均勻的速度通過,閾值類型必須設置成QPS,否則無效 原理: 如閾值類型設置QPS,單機閾值設置1,超時時間設置為200s;相當于1s請求1次,當時間超過200s后才會被丟棄 場景: (應對突發流量)一會流量很大,一會很空閑,希望應用能夠在空閑時處理請求而不是直接拒絕請求 ``` ![](https://img.kancloud.cn/44/d7/44d741e756d3f28eea592f7ea02b5c74_829x440.png) ## 4.2 降級規則詳解 (斷路器) ``` 資源名: 當前資源路徑 降級策略: RT: 若持續進入 5 個請求,它們資源的平均響應時間都超過閾值(秒級平均 RT,以 ms 為單位),資源調用會被熔斷。 在接下的降級時間窗口(在降級規則中配置,以s為單位)之內,對這個方法的調用都會自動地返回(拋出 DegradeException) 注意點: RT默認最大4900ms -- 通過 -Dcsp.sentinel.statistic.max.rt=xxx 修改 異常比例模式: 當資源的每秒異常數占通過量的比值超過閾值之后,資源進入降級狀態,即在接下的降級時間窗口(在降級規則中配置,以s為單位)之內, 對這個方法的調用都會自動地返回.異常比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%. 異常數模式: 當資源最近 1 分鐘的異常數目超過閾值之后會進行熔斷. 注意: 時間窗口<60s可能會出現問題 注意: 斷路器有三種狀態: 打開 | 關閉 | 半開, 但目前sentinel沒有設置半開狀態. ``` ![](https://img.kancloud.cn/ab/0b/ab0b364e8e80d2aa9eeed0eccf8f3601_866x414.png) ## 4.3 熱點規則詳解 ``` ** 熱點規則就是對指定的參數或者參數值限流; sentinel默認顯示的端點是不支持熱點規則的,需要自定義代碼實現 @GetMapping("test-hot") @SentinelResource("hot") //使用該注解,請求刷新Sentinel控制臺,才會出現熱點規則配置 public String testHost(@RequestParam(required = false) String a, @RequestParam(required = false) String b) { return a + ":" + b; } ``` ``` 資源名: @SentinelResource中定義的值即hot 參數索引: 參數a的索引就是0, 參數b的索引就是1, 若設置為0代表限流API帶參數a的請求,若不帶a,則不會被限流. 在時間窗口以內指定參數的QPS達到一定的閾值就會觸發限流 高級選項: 如參數類型設置String, 參數值設置5, 限流閾值設置1000ms, 代表參數值是不是5時閾值就是1ms; 參數值是5時閾值就是1000ms 場景: API的某參數的QPS很高時, 可以使用熱點規則,提高API的可用性;即對傳遞該參數或參數值的API限流,不影響調用該API傳遞其他參數或參數值 注意: 參數索引中配置的參數必須是[基本類型或者String,否則不會生效] ``` ![](https://img.kancloud.cn/f9/7b/f97b79c6a0dc3938e45c63b09b911042_905x443.png) ## 4.4 系統規則詳解 ``` 閾值類型: LOAD(負載): 當系統load1(1分鐘的負載)超過閾值,且并發線程數超過系統容量時觸發,建議設置為CPU核心數*2.5(僅對linux/unix-like機器生效) 命令查看load: uptime RT: 所有入口流量的平均RT達到閾值觸發 線程數: 所有入口流量的并發線程數達到閾值觸發 入口QPS: 所有入口流量的QPS達到閾值觸發 ``` ![](https://img.kancloud.cn/9d/8c/9d8cbce837d42c75c30f2079f7d8e7fe_766x106.png) ![](https://img.kancloud.cn/76/78/7678254ce0a71b1b80fbfd6d33e57419_913x394.png) ## 4.5 授權規則詳解 ![](https://img.kancloud.cn/62/2e/622e08250ffc0ad85a7d5e71c081b7d2_912x443.png) # 5. 代碼配置規則 ``` 參考: https://www.imooc.com/article/289345 ``` # 6. Sentinel與控制臺通信原理剖析 ``` 控制臺是如何獲取到微服務的監控信息的? 用控制臺配置規則時,控制臺是如何將規則發送到各個微服務的呢? http://ip:sentinel端口/api 源碼: 注冊/心跳發送的API: com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeartbeatSender 通信的API: com.alibaba.csp.sentinel.command.CommandHandler的實現類, 如: ApiCommandHandler ``` ![](https://img.kancloud.cn/18/f2/18f2364a9a70cb774865ea2a912afdee_816x461.png) # 7. 控制臺相關配置項 **7-1. 應用端連接控制臺配置項** ![](https://img.kancloud.cn/6f/ac/6facc05fb8295f2375a38101701814f4_571x305.png) **7-2. 控制臺的配置項** ![](https://img.kancloud.cn/97/cb/97cb8528af0abc102384a2047bfea138_855x367.png) **7-3. 修改控制臺的配置項操作 ** ``` 如:修改控制臺的用戶名和密碼,如下圖 ``` ![](https://img.kancloud.cn/4a/42/4a4245b645df02aecb28cc1426acb4fa_925x73.png) # 8. SentinelAPI詳解 ``` 核心API: 1. SphU: 定義資源,讓資源受到監控并且可以保護資源 2. Tracer: 對我們想要的異常進行統計 3. ContextUtil: 可以實現調用來源,標記調用 ``` ``` spring: cloud: sentinel: transport: #指定sentinel 控制臺地址 dashboard: localhost:8080 filter: #關閉掉spring MVC端點的保護,測試為了防止干擾,正常要為true(或者默認) enabled: false ``` ``` //代碼實現降級及限流及來源功能 String resourceName = "test-sentinel-api"; ContextUtil.enter(resourceName, "test-wfw"); //定義一個Sentinel保護的資源,名稱可以任意,唯一即可 Entry entry = null; try { entry = SphU.entry(resourceName); if(StringUtils.isEmpty(a)) { throw new IllegalArgumentException("參數不合法"); } // 被保護的業務邏輯 //TODO: return a; } catch (BlockException e) { //如果被保護的資源被限流或者降級會拋出BlockException } catch (IllegalArgumentException e) { //統計IllegalArgumentException[發生的次數,發生占比...] Tracer.trace(e); return "參數不合法"; } finally { if(entry != null) { entry.exit(); } ContextUtil.exit(); } ``` # 9. @SentinelResource注解詳解 ``` 參考: https://www.imooc.com/article/289384 ``` ``` 重寫上面代碼: @GetMapping("test-sentinel-api") @SentinelResource(value = "test-sentinel-api", blockHandler = "block", fallback = "fallback") public String testSentinelAPI(@RequestParam(required = false) String a) { if(StringUtils.isEmpty(a)) { throw new IllegalArgumentException("參數不合法"); } return a; } //處理限流或者降級 public String block(String a, BlockException e) { return "限流或者降級了 block"; } //1.5處理降級 sentinel 1.6可以處理Throwable public String fallback(String a) { return "限流或者降級了 fallback"; } ``` ``` 源碼: com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect com.alibaba.csp.sentinel.annotation.aspectj.AbstractSentinelAspectSupport ``` # 10. RestTemplate整合Sentinel ``` 源碼: org.springframework.cloud.alibaba.sentinel.custom.SentinelBeanPostProcessor ``` ``` @Bean @LoadBalanced @SentinelRestTemplate public RestTemplate restTemplate() { return new RestTemplate(); } 配置開關: resttemplate: sentinel: # 關閉@SentinelRestTemplate注解 enabled: false ``` # 11. Feign整合Sentinel ``` 源碼: org.springframework.cloud.alibaba.sentinel.feign.SentinelFeign ``` ``` 1. 只需要添加下面的配置: feign: sentinel: #為feign整合sentinel enabled: true ``` ``` 2. 限流降級發生時,如何定制自己的處理邏輯? @FeignClient(name = "ali-pay-service", configuration = UserCenterFeignConfiguration.class, fallback = UserCenterFeginClientFallback.class) public interface UserCenterFeginClient { /** * http://ali-pay-service/users/{id} * @param id * @return */ @GetMapping("/users/{id}") String findById(@PathVariable Integer id); } @Component public class UserCenterFeginClientFallback implements UserCenterFeginClient { @Override public String findById(Integer id) { return null; } } ``` ``` 3. 進入到Fallback中是異常情況,如何獲取到異常? /** * name: 請求服務的名稱 * fallback與fallbackFactory不可同時用 * fallbackFactory可以獲取到異常 */ @FeignClient(name = "ali-pay-service", configuration = UserCenterFeignConfiguration.class, // fallback = UserCenterFeginClientFallback.class, fallbackFactory = UserCenterFeginClientFallbackFactory.class ) public interface UserCenterFeginClient { /** * http://ali-pay-service/users/{id} * @param id * @return */ @GetMapping("/users/{id}") String findById(@PathVariable Integer id); } @Component public class UserCenterFeginClientFallbackFactory implements FallbackFactory<UserCenterFeginClient> { @Override public UserCenterFeginClient create(Throwable cause) { return new UserCenterFeginClient() { @Override public String findById(Integer id) { return null; } }; } } ``` # 12. 規則持久化 ``` 1. 規則持久化-拉模式 參考: https://www.imooc.com/article/289402 2. 規則持久化-推模式 參考: https://www.imooc.com/article/289464 3. 阿里云上提供免費的Sentinel的使用(AHAS) 開通地址: https://ahas.console.aliyun.com/ 開通說明: https://help.aliyun.com/document_detail/90323.html ``` # 13. 集群流控 ``` 配置規則時設置集群模式,如控制臺配置: ``` ![](https://img.kancloud.cn/f1/92/f19254c0bcfd40729d111f9effc57339_887x469.png) ``` 要想集群模式需要引入Token Client組件去和Token Server通信, 如何部署Token Server? 微服務如何繼承Token Client? 參考官方https://github.com/alibaba/Sentinel/wiki 注: 目前Token Server還不能用在生產環境,很多功能需要自己實現,集群流控搭建參考:https://www.jianshu.com/p/bb198c08b418 但目前[實現集群的流控方案可以在網關處進行設置]更加簡單,實用. 下圖為集群流控模式的架構圖: ``` ![](https://img.kancloud.cn/ea/cc/eacc11adc16a14b52b975304e14c4b5b_732x359.png) # 14. 擴展Sentinel ``` UrlBlockHandler : 提供Sentinel異常處理 RequestOriginParser : 區分來源 UrlCleaner : 重新定義資源名稱 本質都是通過CommonFilter過濾器調用的,源碼參照: com.alibaba.csp.sentinel.adapter.servlet.CommonFilter ``` ``` 1. 擴展Sentinel-錯誤頁優化 @Component public class MyUrlBlockHandler implements UrlBlockHandler { @Override public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException { ErrorMsg message = null; //限流異常 if(ex instanceof FlowException) { message = ErrorMsg.builder().code(100).msg("限流異常").build(); } //降級異常 else if(ex instanceof DegradeException) { message = ErrorMsg.builder().code(101).msg("降級異常").build(); } //系統規則異常 else if(ex instanceof SystemBlockException) { message = ErrorMsg.builder().code(102).msg("系統規則異常").build(); } //參數熱點規則異常 else if(ex instanceof ParamFlowException) { message = ErrorMsg.builder().code(103).msg("參數熱點規則異常").build(); } //授權規則異常 else if(ex instanceof AuthorityException) { message = ErrorMsg.builder().code(104).msg("授權規則異常").build(); } //TODO: 通過response將異常信息寫出去 } } @Data @Builder @AllArgsConstructor @NoArgsConstructor class ErrorMsg { private Integer code; private String msg; } ``` ``` 2. 擴展Sentinel-實現區分來源 @Component public class MyRequestOriginParser implements RequestOriginParser { @Override public String parseOrigin(HttpServletRequest request) { //來源的參數在實際應用中可以放在Header中 //從請求參數中過去名為 origin 的參數并返回 //如果獲取不到 origin 參數,那么就拋出異常 String origin = request.getParameter("origin"); //String origin = request.getHeader("origin"); if (StringUtils.isEmpty(origin)) { throw new IllegalArgumentException("origin must be set"); } return origin; } } ``` ``` 3. 擴展Sentinel-RESTfulURL支持(針對所有資源設置相同的流控規則) @Component public class MyUrlCleaner implements UrlCleaner { @Override public String clean(String originUrl) { //目標:path/1和path/2的返回值相同,返回/path/{number} String[] split = originUrl.split("/"); return Arrays.stream(split).map(string -> { if (NumberUtils.isNumber(string)) { return "{number}"; } return string; }).reduce((a,b) -> a+"/"+b).orElse(""); } } ``` # 15. Sentinel全部配置項 ``` 參照: https://www.imooc.com/article/289562 ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看