SpringCloud OpenFeign超時(shí)控制示例詳解
前言:
在上一章節(jié)中我們簡單的介紹了如何使用OprnFeign去調(diào)用微服務(wù),因?yàn)橄M(fèi)側(cè)和服務(wù)側(cè)是兩個(gè)不同的微服務(wù),這樣可能會(huì)出現(xiàn)超時(shí)的現(xiàn)象,例如服務(wù)側(cè)需要3秒處理任何才能返回結(jié)果,但消費(fèi)側(cè)可能2秒就斷開連接了,這時(shí)就會(huì)因?yàn)闀r(shí)間差而出現(xiàn)連接超時(shí)的問題,而本節(jié)內(nèi)容則是關(guān)于如果去對OpenFeign進(jìn)行超時(shí)控制。
1、編寫代碼模擬連接超時(shí)
(1)編寫providder-payment8001項(xiàng)目PaymentController類的代碼
package com.ken.springcloud.controller; import com.ken.springcloud.entities.CommonResult; import com.ken.springcloud.entities.Payment; import com.ken.springcloud.service.PaymentService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; import java.util.concurrent.TimeUnit; @RestController @Slf4j public class PaymentController { @Resource private PaymentService paymentService; @Value("${server.port}") private String serverPort; @Resource private DiscoveryClient discoveryClient; @PostMapping("/payment/insert") public CommonResult insert(@RequestBody Payment payment) { int result = paymentService.insert(payment); log.info("插入結(jié)果{}",result); if(result > 0) { return new CommonResult(200,"插入數(shù)據(jù)庫成功,提供服務(wù)的端口號為" + serverPort,result); }else { return new CommonResult(500,"插入數(shù)據(jù)庫失敗",result); } } @GetMapping("/payment/get/{id}") public CommonResult insert(@PathVariable("id") Long id) { Payment payment = paymentService.getPaymentById(id); log.info("查詢結(jié)果{}",payment); if(payment != null) { return new CommonResult(200,"查詢成功,提供服務(wù)的端口號為" + serverPort,payment); }else { return new CommonResult(500,"沒有對應(yīng)的數(shù)據(jù),查詢失敗,查詢id" + id,payment); } } @GetMapping("/payment/discovery") public Object discovery() { //獲取eureka內(nèi)的服務(wù) List<String> services = discoveryClient.getServices(); for (String service : services) { log.info("***service:" + service); } //獲取服務(wù)名為CLOUD-PAYMENT-SERVICE下的實(shí)例 List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); for (ServiceInstance instance : instances) { log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri()); } return this.discoveryClient; } @GetMapping("/payment/lb") public String getPaymentLB() { //返回當(dāng)前服務(wù)的端口號 return serverPort; } @GetMapping("/payment/feign/timeout") public String paymentFeigntimeout() { try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } //返回當(dāng)前服務(wù)的端口號 return serverPort; } }
(2)編寫cloud-consumer-feign-order80項(xiàng)目PaymentFeignService類的代碼
package com.ken.springcloud.service; import com.ken.springcloud.entities.CommonResult; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @Component //這里@FeignClient里寫的是指定要訪問的微服務(wù)的名稱,表示通過FeignClient去Eureka上面找名稱為CLOUD-PAYMENT-SERVICE的微服務(wù)的接口 @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService { //指明要調(diào)用的CLOUD-PAYMENT-SERVICE的微服務(wù)的接口,這里調(diào)用的是PaymentController類里的/payment/get/{id}接口 @GetMapping("/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id); @GetMapping("/payment/feign/timeout") public String paymentFeigntimeout(); }
(3)編寫cloud-consumer-feign-order80項(xiàng)目OrderFeignController的代碼
package com.ken.springcloud.controller; import com.ken.springcloud.entities.CommonResult; import com.ken.springcloud.entities.Payment; import com.ken.springcloud.service.PaymentFeignService; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @Slf4j @RestController public class OrderFeignController { @Resource private PaymentFeignService paymentFeignService; @GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) { return paymentFeignService.getPaymentById(id); } @GetMapping("/payment/feign/timeout") public String paymentFeigntimeout() { //客戶端一般默認(rèn)等待1秒鐘 return paymentFeignService.paymentFeigntimeout(); } }
2、測試payment接口是否正常工作
分別啟動(dòng)eureka-server7001、eureka-server7002,然后再啟動(dòng)provider-payment8001,最后再啟動(dòng)cloud-consumer-feign-order80,全部啟動(dòng)完畢后在瀏覽器的地址欄里輸入http://localhost:8001/payment/feign/timeout 并且回車調(diào)用接口,最后可以看到接口調(diào)用成功并返回8001,這證明provider-payment8001服務(wù)工作正常
3、測試通過consumer服務(wù)遠(yuǎn)程調(diào)用payment服務(wù)
在瀏覽器地址欄里輸入http://localhost/consumer/payment/feign/timeout 并且回車調(diào)用接口,這時(shí)會(huì)顯示Read timed out executing GET http://CLOUD-PAYMENT-SERVICE/payment/feign/timeout的錯(cuò)誤信息,這是因?yàn)镕eign客戶端默認(rèn)只等待一秒鐘,但是服務(wù)端處理需要超過1秒鐘,導(dǎo)致Feign客戶端不想等待了,直接返回報(bào)錯(cuò),為了避免這樣的情況,有時(shí)候我們需要設(shè)置Feign客戶端的超時(shí)控制。
效果圖:
4、設(shè)置Feign客戶端的超時(shí)時(shí)間
修改cloud-consumer-feign-order80項(xiàng)目的application.yml文件(因?yàn)镺penFeign集成了Ribbon,所以O(shè)penFeign的超時(shí)控制也由最底層的Ribbon來進(jìn)行限制,所以這里是對Ribbon進(jìn)行配置)
集成示意圖:
application.yml文件
server: port: 80 eureka: client: #表示是否將自己注冊進(jìn)Eureka Server里,默認(rèn)為true register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #設(shè)置feign客戶端超時(shí)時(shí)間(OpenFeign默認(rèn)支持ribbon) ribbon: #指的是建立連接所用的時(shí)間,適用于網(wǎng)絡(luò)狀況正常的情況下,兩端連接所用的時(shí)間 ReadTimeout: 5000 #指的是建立連接后從服務(wù)器讀取到可用資源所用的時(shí)間 ConnectTimeout: 5000
5、重新測試通過consumer服務(wù)遠(yuǎn)程調(diào)用payment服務(wù)
重新啟動(dòng)consumer服務(wù),然后重新用瀏覽器調(diào)用http://localhost/consumer/payment/feign/timeout 接口,發(fā)現(xiàn)現(xiàn)在并不會(huì)再次發(fā)生微服務(wù)間調(diào)用出現(xiàn)連接超時(shí)的情況
到此這篇關(guān)于SpringCloud OpenFeign超時(shí)控制的文章就介紹到這了,更多相關(guān)SpringCloud OpenFeign超時(shí)控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot動(dòng)態(tài)定時(shí)任務(wù)實(shí)現(xiàn)與應(yīng)用詳解
定時(shí)任務(wù)在許多應(yīng)用場景中是必不可少的,特別是在自動(dòng)化任務(wù)執(zhí)行、定期數(shù)據(jù)處理等方面,定時(shí)任務(wù)能極大地提高系統(tǒng)的效率,然而,隨著業(yè)務(wù)需求的變化,定時(shí)任務(wù)的執(zhí)行頻率或時(shí)間點(diǎn)可能需要?jiǎng)討B(tài)調(diào)整,所以本文給大家介紹了SpringBoot動(dòng)態(tài)定時(shí)任務(wù)實(shí)現(xiàn)與應(yīng)用2024-08-08Java volatile如何實(shí)現(xiàn)禁止指令重排
這篇文章主要介紹了Java volatile如何實(shí)現(xiàn)禁止指令重排,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11Spring Boot Mail QQ企業(yè)郵箱無法連接解決方案
這篇文章主要介紹了Spring Boot Mail QQ企業(yè)郵箱無法連接解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09解決Spring事務(wù)@Transactional多層嵌套失效問題
在使用Spring進(jìn)行事務(wù)管理時(shí),可能會(huì)遇到事務(wù)失效的問題,主要原因包括數(shù)據(jù)庫不支持事務(wù)、方法訪問級別不是public、未被Spring管理的Bean、當(dāng)前類的方法內(nèi)部調(diào)用以及配置的事務(wù)傳播性不當(dāng)?shù)?解決事務(wù)失效的方法有使用聲明式事務(wù)處理采用合適的事務(wù)傳播行為2024-11-11Springboot FeignClient調(diào)用Method has too m
本文主要介紹了Springboot FeignClient微服務(wù)間調(diào)用Method has too many Body parameters 解決,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Eclipse導(dǎo)入項(xiàng)目報(bào)錯(cuò)問題解決方案
這篇文章主要介紹了Eclipse導(dǎo)入項(xiàng)目報(bào)錯(cuò)問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07