<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>

          「微服務設計之禪」重試模式

          共 3152字,需瀏覽 7分鐘

           ·

          2020-12-13 09:57

          前言

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

          重試模式

          在微服務技術(shù)架構(gòu)中,當有多個服務(A,B,C ,D)時,一個服務(A)可能依賴于另一服務(B),而另一服務(B)又可能依賴于 C,依此類推。有時由于某些問題,服務 D 可能無法按預期響應。服務 D 可能引發(fā)了某些異常,例如 OutOfMemory Error 或 Internal Server Error。此類異常會影響下游服務,這可能導致用戶體驗較差,如下所示。

          1607306376

          類似于網(wǎng)絡通信異常等,大部分情況通過刷新再次請求服務接口即可解決。在微服務架構(gòu)中,生產(chǎn)環(huán)境針對服務 D 部署了多個實例,并通過負載均衡等實現(xiàn)服務 D 高可用。如果其中一個實例網(wǎng)絡請求有問題,無法響應期望結(jié)果,我們可以通過重試該請求,通過負載均衡器將請求發(fā)送至運行狀態(tài)良好的實例獲取正確結(jié)果。因此通過“重試”模式,可以使得應用可用性得到保證。

          1607306392

          示例程序

          架構(gòu)圖

          1607306406

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

          • 用戶登錄瀏覽商品 (商品庫存模塊)
          • 扣減商品庫存 (商品庫存模塊)
          • 創(chuàng)建商品訂單 (訂單模塊)

          product-service 通過調(diào)用 order-service 服務下單

          代碼實現(xiàn)

          ├──?retry-demo
          ???├──?order-service????????#訂單服務??(8070)
          ???└──?product-service??????#商品庫存服務??(8050)
          • 依賴說明。由于 hystrix 年久失修,這里使用 resilience4j 斷路保護器做演示
          <dependency>
          ????<groupId>io.github.resilience4jgroupId>
          ????<artifactId>resilience4j-spring-boot2artifactId>
          ????<version>1.6.1version>
          dependency>
          • 針對接口定義重試策略
          resilience4j.retry:
          ??instances:
          ????ratingService:
          ??????maxRetryAttempts:?1?#重試策略
          ??????retryExceptions:???#針對哪些異常進行重試
          ????????-?org.springframework.web.client.HttpServerErrorException

          • 消費方接口。product-service 8050
          /**
          ?*?用戶點擊購買
          ?*/

          @SneakyThrows
          @GetMapping("/order")
          public?String?buy()?{
          ????//?模擬調(diào)用?訂單服務下單
          ????orderService.createOrder().get();
          ????return?"success";
          }
          • 定義遠程調(diào)用類使用 Retry 包裝
          /**
          ?*?創(chuàng)建訂單
          ?*?name:?指定接口重試配置名稱
          ?*?fallbackMethod:?重試后降級方法
          ?*/

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

          public?CompletableFuture?getError(Throwable?error)?{
          ????log.warn("創(chuàng)建訂單失敗了?{}",?error.getMessage());
          ????return?CompletableFuture.completedFuture("");
          }

            • 服務提供方。order-service 8070
          @RestController
          public?class?PayController?{
          ????private?static?int?num?=?0;
          ????@SneakyThrows
          ????@GetMapping("/createOrder")
          ????public?String?createOrder()?{
          ????????log.info("開始請求創(chuàng)建訂單接口?{}",?++num);
          ????????//?請求次數(shù)奇數(shù)模擬創(chuàng)建訂單異常
          ????????if?(num?%?2?!=?0)?{
          ????????????throw?new?RuntimeException();
          ????????}
          ????????return?"創(chuàng)建訂單服務";
          ????}
          }

          開始測試

          • 請求商品服務,返回成功
          curl?http://localhost:8050/order
          success?
          • 訂單服務日志,由于是第一次請求觸發(fā)異常,然后服務調(diào)用方自動重試產(chǎn)生第二次調(diào)用。
          2020-12-06?15:50:07.664??INFO?25846?---?[nio-8070-exec-1]?c.e.o.controller.OrderController?????????:?開始請求創(chuàng)建訂單接口?1
          2020-12-06?15:50:07.686?ERROR?25846?---?[nio-8070-exec-1]?o.a.c.c.C.[.[.[/].[dispatcherServlet]????:?Servlet.service()?for?servlet?[dispatcherServlet]?in?context?with?path?[]?threw?exception?[Request?processing?failed;?nested?exception?is?java.lang.RuntimeException]?with?root?cause

          ...?異常日志?...

          2020-12-06?15:50:08.271??INFO?25846?---?[nio-8070-exec-2]?c.e.o.controller.OrderController?????????:?開始請求創(chuàng)建訂單接口?2

          總結(jié)

          重試模式可以通過編碼的形式自動發(fā)起重試,避免終端用戶手動刷新體驗問題。但重試模式的缺點是會造成整體的響應時間,部分業(yè)務邏輯不能適用(比如冪等接口[1]等)

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

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

          參考資料

          [1]

          冪等接口: https://juejin.cn/post/6892966720017793037

          [2]

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

          [3]

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


          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  怡红院院AV | 精品福利在线免费观看 | 色艹艹| 久久精品成人电影 | 色黄超碰|