1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 3410字,需瀏覽 7分鐘

         ·

        2020-12-13 09:57

        前言

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

        超時(shí)模式

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

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

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

        示例程序

        架構(gòu)說明

        • 如上圖所示,簡(jiǎn)單模擬電商支付下單邏輯


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

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

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

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

        代碼實(shí)現(xiàn)

        ├──?timeout-demo
        ???├──?order-service????????#訂單服務(wù)??(8070)
        ???├──?pay-service??????????#支付服務(wù)??(8060)
        ???└──?product-service??????#商品庫存服務(wù)??(8050)
        • 依賴說明。由于 hystrix 年久失修,這里使用 resilience4j 斷路保護(hù)器做演示
        <dependency>
        ????<groupId>io.github.resilience4jgroupId>
        ????<artifactId>resilience4j-spring-boot2artifactId>
        ????<version>1.6.1version>
        dependency>
        • 消費(fèi)方定義超時(shí)策略
        #?超時(shí)參數(shù)配置
        resilience4j:
        ??timelimiter:
        ????instances:
        ??????createOrder:?#?接口名稱
        ????????timeoutDuration:?5s?#超時(shí)時(shí)間
        ??????pay:?#?接口名稱
        ????????timeoutDuration:?3s?#超時(shí)時(shí)間
        • 消費(fèi)方接口。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:?指定接口超時(shí)配置名稱
        ?*?fallbackMethod:?超時(shí)后降級(jí)方法
        ?*/

        @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());
        }

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

        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)用支付渠道耗時(shí)?10s
        ????????Thread.sleep(10000);
        ????????return?"支付成功";
        ????}
        }

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

        使用示例

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

        測(cè)試如下

        curl?http://localhost:8050/buy

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

        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 包裝接口,實(shí)現(xiàn)對(duì)指定調(diào)用超時(shí)設(shè)置,保證線程不會(huì)被阻塞

        • 核心服務(wù)不會(huì)因?yàn)橄掠畏?wù)超時(shí)而被影響造成性能問題

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

        問題分析:

        • 下游服務(wù)不可用的狀態(tài)下,線程仍需要阻塞,當(dāng)并發(fā)請(qǐng)求很多時(shí),也會(huì)造成性能瓶頸
        • 如上問題可以通過隔離模式來實(shí)現(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è)計(jì)之禪」重試模式

        「SpringBoot 新特性」啟動(dòng)耗時(shí)詳細(xì)監(jiān)控

        Spring Boot Xss 攻擊過濾插件

        「Spring Boot 新特性」 jar 大小自動(dòng)瘦身

        Spring Cloud Hoxton SR9 發(fā)布

        Spring Boot ?接口冪等插件使用


        瀏覽 105
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            大尺度做爰呻吟舌吻网站 | 大香蕉欧美 | 韩国精品在线观看 | 8050午夜一级A片免费视频 | 久久久久免费网站 | 九九在线| 国产真实交换夫妇视频 | 我和二个女人做爰 | 精品国产乱码久久久兰 | 码精品一区二区三区四区 |