最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Cloud OpenFeign實(shí)現(xiàn)動態(tài)服務(wù)名調(diào)用的示例代碼

 更新時(shí)間:2025年06月06日 10:24:38   作者:要阿爾卑斯嗎  
在微服務(wù)架構(gòu)中,我們經(jīng)常需要根據(jù)動態(tài)傳入的服務(wù)名來遠(yuǎn)程調(diào)用其他服務(wù),例如,你的業(yè)務(wù)中可能有多個(gè)子服務(wù):service-1、service-2……需要動態(tài)決定調(diào)用哪個(gè),所以本文給大家介紹了Spring Cloud OpenFeign 實(shí)現(xiàn)動態(tài)服務(wù)名調(diào)用指南,需要的朋友可以參考下

場景背景

在微服務(wù)架構(gòu)中,我們經(jīng)常需要根據(jù)動態(tài)傳入的服務(wù)名來遠(yuǎn)程調(diào)用其他服務(wù)。例如,你的業(yè)務(wù)中可能有多個(gè)子服務(wù):service-1、service-2……需要動態(tài)決定調(diào)用哪個(gè)。

通常我們使用如下方式注入 Feign 客戶端:

 @FeignClient(name = "service")
 public interface FeignClient {
     @PostMapping("/api/push")
     void pushMessage(@RequestBody PushMessageRequest request);
 }

但這種寫法服務(wù)名是靜態(tài)寫死的,不能根據(jù)運(yùn)行時(shí)的參數(shù)進(jìn)行動態(tài)選擇。

錯(cuò)誤用法:FeignClientFactory

很多開發(fā)者會嘗試用 Spring 內(nèi)部的 FeignClientFactory

 @Resource
 private FeignClientFactory feignClientFactory;
 ?
 FeignClient FeignClient = feignClientFactory.getInstance(serviceName, FeignClient.class);

這種方式只能獲取 @FeignClient(name="xxx") 注冊的靜態(tài)實(shí)例,而不能真正實(shí)現(xiàn)動態(tài)服務(wù)調(diào)用。

  • 適用場景:獲取已經(jīng) @FeignClient 聲明過的 bean。
  • 不適用:動態(tài)服務(wù)名(如從數(shù)據(jù)庫或配置中傳入)+ 動態(tài)構(gòu)建 Feign 實(shí)例。

正確方式:自定義動態(tài) Feign 客戶端工廠

要想實(shí)現(xiàn)真正的動態(tài)服務(wù)名 + 負(fù)載均衡 + 支持配置和攔截器的 Feign 客戶端,我們需要手動構(gòu)造并注入 Feign 客戶端。

核心思路:

  • 使用 Spring Cloud 提供的 Feign.Builder(必須是 Spring 注入的)
  • 配合 LoadBalancerClient 實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)與負(fù)載均衡
  • 手動構(gòu)建 Feign 接口實(shí)例

一、配置 Feign.Builder

 @Configuration
 public class FeignBuilderConfig {
 ?
     @Bean
     @Scope("prototype")
     public Feign.Builder feignBuilder(ObjectFactory<HttpMessageConverters> messageConverters) {
         return Feign.builder()
                 .contract(new SpringMvcContract())
                 .encoder(new SpringEncoder(messageConverters))
                 .decoder(new SpringDecoder(messageConverters))
                 .retryer(new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1), 3))
                 .options(new Request.Options(3000, 5000))
                 .logger(new Logger.ErrorLogger())
                 .logLevel(Logger.Level.BASIC);
     }
 }

二、自定義動態(tài)客戶端工廠

 @Component
 @Slf4j
 public class DynamicFeignClientFactory {
 ?
     private final Feign.Builder feignBuilder;
     private final LoadBalancerClient loadBalancerClient;
 ?
     public DynamicFeignClientFactory(Feign.Builder feignBuilder,
                                      LoadBalancerClient loadBalancerClient) {
         this.feignBuilder = feignBuilder;
         this.loadBalancerClient = loadBalancerClient;
     }
 ?
     public <T> T getClient(String serviceName, Class<T> clazz) {
         int maxRetry = 3;
         int retryCount = 0;
         Exception lastException = null;
 ?
         while (retryCount < maxRetry) {
             try {
                 ServiceInstance instance = loadBalancerClient.choose(serviceName);
                 if (instance == null) {
                     throw new RuntimeException("未找到可用的服務(wù)實(shí)例:" + serviceName);
                 }
 ?
                 String url = instance.getUri().toString();
                 log.info("選擇的 Feign 客戶端目標(biāo)地址為:{}", url);
                 return feignBuilder.target(clazz, url);
 ?
             } catch (Exception e) {
                 lastException = e;
                 log.warn("第 {} 次嘗試獲取 Feign 客戶端失敗,服務(wù)名:{},錯(cuò)誤信息:{}", retryCount + 1, serviceName, e.getMessage());
                 retryCount++;
                 try {
                     Thread.sleep(500L);
                 } catch (InterruptedException ignored) {}
             }
         }
 ?
         throw new RuntimeException("創(chuàng)建 Feign 客戶端失敗,服務(wù)名:" + serviceName, lastException);
     }
 }

三、使用方式

原始寫法(錯(cuò)誤):

 @Resource
 private FeignClientFactory feignClientFactory;
 ?
 FeignClient FeignClient = feignClientFactory.getInstance(serviceName, FeignClient.class); 

正確寫法:

@Resource
private DynamicFeignClientFactory feignClientFactory;

FeignClient FeignClient = feignClientFactory.getClient(ServerName, FeignClient.class);
FeignClient.pushMessage(new PushMessageRequest(Ids, senderEventMessage));

補(bǔ)充說明

  • Spring 注入的 Feign.Builder 會自動繼承全局配置(超時(shí)、日志、攔截器等)。
  • 支持服務(wù)名動態(tài)路由,自動走 Spring Cloud LoadBalancer。
  • 每次調(diào)用可綁定到不同的服務(wù)實(shí)例(支持輪詢/自定義負(fù)載策略)。
  • 避免直接 new Feign.Builder(),否則會失去 Spring 集成能力。

1. DynamicFeignClientFactory 類

 @Component
 @Slf4j
 public class DynamicFeignClientFactory {
 ?
     private final Feign.Builder feignBuilder;
     private final LoadBalancerClient loadBalancerClient;
 ?
     public DynamicFeignClientFactory(Feign.Builder feignBuilder,
                                      LoadBalancerClient loadBalancerClient) {
         this.feignBuilder = feignBuilder;
         this.loadBalancerClient = loadBalancerClient;
     }
 ?
     public <T> T getClient(String serviceName, Class<T> clazz) {
         ...
     }
 }

功能說明:

這是 動態(tài)創(chuàng)建 Feign 客戶端 的核心工廠類,解決了 Spring Cloud @FeignClient 無法支持運(yùn)行時(shí)動態(tài)服務(wù)名的問題。

核心邏輯:

  • 使用 Spring 提供的 LoadBalancerClient 動態(tài)選擇某個(gè)服務(wù)的實(shí)例(支持 Eureka/Nacos 等注冊中心)。
  • 使用 Spring 注入的 Feign.Builder 構(gòu)建 Feign 客戶端實(shí)例,綁定目標(biāo)實(shí)例地址
  • 加了簡單的重試邏輯(最多3次),提升服務(wù)不穩(wěn)定時(shí)的容錯(cuò)性。

為什么不能直接用 FeignClientFactory?

  • FeignClientFactory#getInstance 是靜態(tài)注冊的,依賴啟動時(shí)的 @FeignClient(name="xxx"),不能做到動態(tài)服務(wù)名運(yùn)行時(shí)創(chuàng)建實(shí)例。
  • 而本類是自己構(gòu)造目標(biāo)地址,可通過服務(wù)名運(yùn)行時(shí)切換服務(wù)。

2. FeignBuilderConfig 類

 @Configuration
 public class FeignBuilderConfig {
 ?
     @Bean
     @Scope("prototype")
     public Feign.Builder feignBuilder(ObjectFactory<HttpMessageConverters> messageConverters) {
         return Feign.builder()
                 .contract(new SpringMvcContract())
                 .encoder(new SpringEncoder(messageConverters))
                 .decoder(new SpringDecoder(messageConverters))
                 .retryer(new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1), 3))
                 .options(new Request.Options(3000, 5000))
                 .logger(new Logger.ErrorLogger())
                 .logLevel(Logger.Level.BASIC);
     }
 }

功能說明:

這是自定義的 Feign 構(gòu)造器配置,確保動態(tài)創(chuàng)建的 Feign 實(shí)例擁有 Spring 的 HTTP 編解碼器、契約協(xié)議、超時(shí)、重試等設(shè)置。

關(guān)鍵配置解讀:

配置項(xiàng)作用說明
SpringMvcContract讓 Feign 支持 @RequestMapping、@GetMapping 等 Spring MVC 風(fēng)格注解
SpringEncoder/Decoder使用 Spring Boot 的 HttpMessageConverter 做 JSON 編解碼(默認(rèn)支持 Jackson、Gson 等)
Retryer.Default(...)設(shè)置重試機(jī)制:初始延遲100ms,最大延遲1s,最多重試3次
Request.Options(...)設(shè)置連接超時(shí)為3秒,請求響應(yīng)超時(shí)為5秒
Logger.ErrorLogger + BASIC開啟日志,僅記錄錯(cuò)誤請求的基本信息(節(jié)省性能)
@Scope("prototype")每次注入都創(chuàng)建一個(gè)新的 Feign.Builder(防止多實(shí)例干擾)

為什么不能直接用 Feign.builder()?

如果你直接用 Feign.builder()

  • 不具備 Spring 編解碼器能力;
  • 沒有 Spring 的日志、重試、超時(shí)等配置支持;
  • 無法識別 @RequestMapping 等注解;
  • 無法使用負(fù)載均衡(因?yàn)闆]注入 LoadBalancerClient);

你必須用 Spring 注入的 Feign.Builder,并設(shè)置好契約與編解碼器,才能讓它具備 @FeignClient 的能力。

總結(jié)

配置類作用是否必須
DynamicFeignClientFactory實(shí)現(xiàn)動態(tài)服務(wù)名綁定并構(gòu)建 Feign 客戶端
FeignBuilderConfig注入支持 Spring 編解碼、契約協(xié)議、重試、超時(shí)等功能的構(gòu)造器

這兩個(gè)配置類結(jié)合起來,實(shí)現(xiàn)了 “動態(tài)服務(wù)發(fā)現(xiàn) + 動態(tài)客戶端構(gòu)建 + Spring 完整能力支持” ,是 Spring Cloud Feign 動態(tài)服務(wù)名調(diào)用的標(biāo)準(zhǔn)做法之一。

以上就是Spring Cloud OpenFeign實(shí)現(xiàn)動態(tài)服務(wù)名調(diào)用的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Spring Cloud OpenFeign服務(wù)名調(diào)用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實(shí)現(xiàn)對中文字符串的排序功能實(shí)例代碼

    Java實(shí)現(xiàn)對中文字符串的排序功能實(shí)例代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)中文字符串的排序功能實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • java實(shí)現(xiàn)切圖并且判斷圖片是不是純色/彩色圖片

    java實(shí)現(xiàn)切圖并且判斷圖片是不是純色/彩色圖片

    本篇文章主要介紹了java實(shí)現(xiàn)切圖并且判斷圖片是否是純色/彩色圖片,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • springBoot整合jwt實(shí)現(xiàn)token令牌認(rèn)證的示例代碼

    springBoot整合jwt實(shí)現(xiàn)token令牌認(rèn)證的示例代碼

    實(shí)施Token驗(yàn)證的方法挺多的,還有一些標(biāo)準(zhǔn)方法,比如JWT,本文主要介紹了springBoot整合jwt實(shí)現(xiàn)token令牌認(rèn)證的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • JFormDesigner(IDEA)下載方法

    JFormDesigner(IDEA)下載方法

    JFormDesigner是一種Java Swing GUI設(shè)計(jì)工具,可快速創(chuàng)建用戶界面,支持多種布局管理器,如GridBagLayout、SpringLayout等,本文給大家介紹JFormDesigner(IDEA)下載方法,感興趣的朋友跟隨小編一起看看吧
    2023-12-12
  • 詳解Spring Boot下使用logback 記錄多個(gè)文件日志

    詳解Spring Boot下使用logback 記錄多個(gè)文件日志

    這篇文章主要介紹了詳解Spring Boot下使用logback 記錄多個(gè)文件日志,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • Java漏桶算法的簡單代碼實(shí)例

    Java漏桶算法的簡單代碼實(shí)例

    這篇文章主要介紹了Java漏桶算法的簡單代碼實(shí)例,漏桶算法的意義在于能夠平滑請求,不給下游服務(wù)造成過大壓力,特別適用于突發(fā)流量或者定時(shí)任務(wù)拉取大量數(shù)據(jù)時(shí),需要處理大量數(shù)據(jù)或者請求的場景,需要的朋友可以參考下
    2024-01-01
  • SpringBoot中將@Bean方法解析為BeanDefinition詳解

    SpringBoot中將@Bean方法解析為BeanDefinition詳解

    這篇文章主要介紹了SpringBoot中將@Bean方法解析為BeanDefinition詳解,得到的BeanDefinition是ConfigurationClassBeanDefinition類型,會為BeanDefinition設(shè)置factoryMethodName,這意味著當(dāng)實(shí)例化這個(gè)bean的時(shí)候?qū)⒉捎霉S方法,需要的朋友可以參考下
    2023-12-12
  • Java項(xiàng)目防止SQL注入的幾種方法總結(jié)

    Java項(xiàng)目防止SQL注入的幾種方法總結(jié)

    SQL注入是比較常見的網(wǎng)絡(luò)攻擊方式之一,在客戶端在向服務(wù)器發(fā)送請求的時(shí)候,sql命令通過表單提交或者url字符串拼接傳遞到后臺持久層,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令,下面這篇文章主要給大家總結(jié)介紹了關(guān)于Java項(xiàng)目防止SQL注入的幾種方法,需要的朋友可以參考下
    2023-04-04
  • 在spring boot中使用java線程池ExecutorService的講解

    在spring boot中使用java線程池ExecutorService的講解

    今天小編就為大家分享一篇關(guān)于在spring boot中使用java線程池ExecutorService的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Java算法實(shí)現(xiàn)楊輝三角的講解

    Java算法實(shí)現(xiàn)楊輝三角的講解

    今天小編就為大家分享一篇關(guān)于Java算法實(shí)現(xiàn)楊輝三角的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01

最新評論

太白县| 苗栗市| 清水县| 上栗县| 泸水县| 林甸县| 龙山县| 建始县| 收藏| 伊春市| 濮阳市| 辰溪县| 淳安县| 临泉县| 江达县| 门源| 阜宁县| 合川市| 栾川县| 西畴县| 岑溪市| 泗水县| 佛冈县| 砀山县| 彩票| 永靖县| 木里| 仁寿县| 凤台县| 饶阳县| 若尔盖县| 永川市| 长沙县| 杨浦区| 福州市| 两当县| 龙门县| 栾城县| 永州市| 临漳县| 台南县|