<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「微服務(wù)設(shè)計之禪」超時模式

          共 3410字,需瀏覽 7分鐘

           ·

          2020-12-13 09:57

          前言

          微服務(wù)本質(zhì)上分布式架構(gòu),當(dāng)我們使用分布式系統(tǒng)時任何不可預(yù)知的問題都會發(fā)生(例如網(wǎng)絡(luò)可用性問題、服務(wù)可用性問題、中間件可用性問題)。一個系統(tǒng)的問題可能會直接影響另外一個系統(tǒng)的使用或性能。所以在系統(tǒng)設(shè)計過程既要保證自身運行的彈性需求,也要避免對下游服務(wù)級聯(lián)故障。

          超時模式

          如下圖在微服務(wù)架構(gòu)中,當(dāng)存在多個服務(wù)(A,B,C,D),服務(wù) A 依賴于服務(wù) B,而服務(wù) B 依賴于服務(wù) C,依次類推。由于網(wǎng)絡(luò)可用性問題,導(dǎo)致終點服務(wù)(服務(wù) D)不能即使返回,最終導(dǎo)致服務(wù) A 作為調(diào)用方 線程一直處于阻塞狀態(tài)。

          所以為了避免上圖所述的線程阻塞的問題,我們建議在依賴服務(wù)之間通過設(shè)置調(diào)用超時來避免服務(wù)緩慢或者不可用的問題。

          超時設(shè)置的好處
          即使被調(diào)用方服務(wù)不可用,也能保證消費方服務(wù)始終正在運行
          避免消費方服務(wù)無限期等待
          避免阻塞當(dāng)前線程

          示例程序

          架構(gòu)說明

          • 如上圖所示,簡單模擬電商支付下單邏輯


            1. 用戶登錄瀏覽商品 (商品庫存模塊)

            2. 扣減商品庫存 (商品庫存模塊)

            3. 創(chuàng)建商品訂單 (訂單模塊)

            4. 調(diào)用支付模塊支付 (支付模塊)

          代碼實現(xiàn)

          ├──?timeout-demo
          ???├──?order-service????????#訂單服務(wù)??(8070)
          ???├──?pay-service??????????#支付服務(wù)??(8060)
          ???└──?product-service??????#商品庫存服務(wù)??(8050)
          • 依賴說明。由于 hystrix 年久失修,這里使用 resilience4j 斷路保護器做演示
          <dependency>
          ????<groupId>io.github.resilience4jgroupId>
          ????<artifactId>resilience4j-spring-boot2artifactId>
          ????<version>1.6.1version>
          dependency>
          • 消費方定義超時策略
          #?超時參數(shù)配置
          resilience4j:
          ??timelimiter:
          ????instances:
          ??????createOrder:?#?接口名稱
          ????????timeoutDuration:?5s?#超時時間
          ??????pay:?#?接口名稱
          ????????timeoutDuration:?3s?#超時時間
          • 消費方接口。product-service 8050
          @GetMapping("/buy")
          public?String?buy()?{
          ??log.info("-->?開始調(diào)用?");
          ??//?模擬調(diào)用?訂單服務(wù)下單
          ??orderService.createOrder()
          ??????????//?模擬調(diào)用?支付服務(wù)支付
          ??????????.thenApply(orderNo?->?payService.pay()).get()
          ??????????.get();
          ??log.info("-->?結(jié)束調(diào)用?");
          ??return?"success";
          }
          /**
          ?*?創(chuàng)建訂單
          ?*?name:?指定接口超時配置名稱
          ?*?fallbackMethod:?超時后降級方法
          ?*/

          @TimeLimiter(name?=?"createOrder",?fallbackMethod?=?"getError")
          public?CompletableFuture?createOrder()?{
          ????return?CompletableFuture.supplyAsync(()?->?restTemplate.getForEntity("http://localhost:8070/createOrder"
          ????????????,?String.class).getBody());
          }

          /**
          ?*?支付
          ?*/

          @TimeLimiter(name?=?"pay",?fallbackMethod?=?"getError")
          public?CompletableFuture?pay()?{
          ????return?CompletableFuture.supplyAsync(()?->?restTemplate.getForEntity("http://localhost:8060/pay"
          ????????????,?String.class).getBody());
          }

          /**
          ?*?超時后執(zhí)行降級方法
          ?*/

          public?CompletableFuture?getError(Throwable?error)?{
          ????log.warn("失敗?{}",?error.getMessage());
          ????return?CompletableFuture.completedFuture("");
          }
          • 服務(wù)提供方。order-service 8070 /pay-service 8060
          @RestController
          public?class?PayController?{
          ????@SneakyThrows
          ????@GetMapping("/pay")
          ????public?String?pay(){
          ????????//?模擬調(diào)用支付渠道耗時?10s
          ????????Thread.sleep(10000);
          ????????return?"支付成功";
          ????}
          }

          @RestController
          public?class?OrderController?{
          ????@SneakyThrows
          ????@GetMapping("/createOrder")
          ????public?String?createOrder(){
          ????????//?模擬創(chuàng)建訂單耗時
          ????????Thread.sleep(10000);
          ????????return?"創(chuàng)建訂單服務(wù)";
          ????}
          }

          使用示例

          通過以上代碼,我們實現(xiàn)了一個簡單的下單邏輯,通過調(diào)用商品服務(wù)接口,會自動調(diào)用支付、訂單服務(wù)接口。訂單、支付服務(wù)提供方 處理的耗時分別為 10S ,但服務(wù)消費方(商品服務(wù)) 針對 createOrder、pay 接口的最大超時時間為 5S、3S。所以當(dāng)用戶調(diào)用商品服務(wù)的 BUY 會在 8S 內(nèi)獲得返回。

          測試如下

          curl?http://localhost:8050/buy

          日志輸出如下:8 秒超時按照降級方法返回。

          2020-12-05?14:09:34.605??ProductController???????:?-->?開始調(diào)用
          2020-12-05?14:09:39.626??OrderService???:?創(chuàng)建訂單失敗了?TimeLimiter?'createOrder'?recorded?a?timeout?exception.
          2020-12-05?14:09:42.644??PayService???:?支付訂單失敗?TimeLimiter?'pay'?recorded?a?timeout?exception.
          2020-12-05?14:09:42.645ProductController???????:?-->?結(jié)束調(diào)用

          總結(jié)

          • 通過引入 resilience4j 包裝接口,實現(xiàn)對指定調(diào)用超時設(shè)置,保證線程不會被阻塞

          • 核心服務(wù)不會因為下游服務(wù)超時而被影響造成性能問題

          • 保證應(yīng)用返回時間在固定時間窗內(nèi)

          問題分析:

          • 下游服務(wù)不可用的狀態(tài)下,線程仍需要阻塞,當(dāng)并發(fā)請求很多時,也會造成性能瓶頸
          • 如上問題可以通過隔離模式來實現(xiàn)影響最小化,下篇再來講解。

          源碼:https://github.com/lltx/microservices-pattern[1]

          參考資料和部分圖片來源 https://www.vinsguru.com[2]

          參考資料

          [1]

          源碼:: https://github.com/lltx/microservices-pattern

          [2]

          參考資料和部分圖片來源: https://www.vinsguru.com


          往期推薦

          「微服務(wù)設(shè)計之禪」重試模式

          「SpringBoot 新特性」啟動耗時詳細監(jiān)控

          Spring Boot Xss 攻擊過濾插件

          「Spring Boot 新特性」 jar 大小自動瘦身

          Spring Cloud Hoxton SR9 發(fā)布

          Spring Boot ?接口冪等插件使用


          瀏覽 105
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91狠狠色丁香婷婷综合久久精品 | 欧美黄色一级视频 | 日韩 中文字幕 无码 | 黑人大香蕉 | 爱爱网站无码 |