微服務外聯Feign調用:第三方API調用的負載均衡與容災實戰

在這里插入圖片描述

01Feign 簡介

Feign 是 Spring Cloud Netflix 中的 聲明式 HTTP 客戶端,它如同一位貼心的信使,幫我們化繁為簡,讓服務間的調用變得輕松又高效。

Feign 的核心優勢在于:。

? 聲明式調用:開發者只需定義接口和注解,無需編寫繁瑣的 HTTP 請求代碼,Feign 會自動幫我們處理底層細節。
? 集成 Ribbon:Feign 內置了 Ribbon 負載均衡器,在微服務架構中能智能地分配請求到不同實例,確保系統高可用。
? 集成 Hystrix:與熔斷器 Hystrix 深度融合,為服務調用提供容錯保障,就像給系統系上了安全帶。
? 注解驅動開發:通過 @FeignClient 定義客戶端,@RequestMapping 映射請求,搭配 @PathVariable 等注解靈活處理各種參數。
? 高度可定制:支持自定義編碼器、解碼器、錯誤處理邏輯,滿足個性化開發需求。

02使用 Feign 調用第三方接口

Feign 不僅能在微服務家族內部穿梭調用,還能跨越邊界與第三方接口對話。

只需在 @FeignClient 注解中設定 url 屬性,Feign 就能精準地找到目標接口。

@FeignClient(name = "third-party-api", url = "https://api.example.com")
public interface ThirdPartyApi {@GetMapping("/data")String fetchData();
}

注解:

  1. @FeignClient 的 name 屬性為 Feign 客戶端命名,便于識別。
  2. url 屬性直接指定第三方接口的基地址,Feign 會基于此構建完整請求路徑。
  3. 接口方法通過 @GetMapping 注解定義具體請求路徑和方法,清晰直觀。

03Feign 調用第三方接口的負載均衡實現

雖然 Feign 與 Ribbon 的天然適配讓其在微服務內負載均衡游刃有余,但面對第三方接口時,我們需要另辟蹊徑。

借助 Feign 的攔截器功能,我們能巧妙地植入自定義負載均衡邏輯。

@Component
public class FeignLoadBalancerInterceptor implements RequestInterceptor {private final LoadBalancer loadBalancer;public FeignLoadBalancerInterceptor(LoadBalancer loadBalancer) {this.loadBalancer = loadBalancer;}@Overridepublic void apply(RequestTemplate template) {// 獲取當前請求的目標服務String serviceName = template.feignTarget().name();// 從負載均衡器獲取最佳服務實例地址String selectedUrl = loadBalancer.selectServiceInstance(serviceName);// 反射更新請求模板的 URL(因 Feign 的 URL 字段被 final 修飾)updateRequestUrl(template, selectedUrl);}private void updateRequestUrl(RequestTemplate template, String newUrl) {try {FieldurlField= template.feignTarget().getClass().getDeclaredField("url");urlField.setAccessible(true);urlField.set(template.feignTarget(), newUrl);} catch (Exception e) {throw newRuntimeException("Failed to update request URL", e);}}
}

注解:

  1. FeignLoadBalancerInterceptor 實現 RequestInterceptor 接口,在 Feign 發起請求前攔截。
  2. 通過 LoadBalancer 組件(需自行實現或集成)獲取最優服務實例地址。
  3. 利用反射技術動態更新 Feign 客戶端的請求 URL,繞過 final 修飾符限制。

04負載均衡算法的多樣化實現

為了滿足不同業務場景需求,我們精心設計了多種負載均衡算法,并通過配置靈活切換。

輪詢算法(RoundRobin):像接力賽跑一樣,依次將請求分配給每個服務實例。

@Component("roundRobin") 
public class RoundRobinLoadBalancer implements LoadBalancer {private Atomic Integer position=newAtomicInteger(0);private final List<String> serviceInstances;@Overridepublic String selectServiceInstance(String serviceName) {intidx= Math.abs(position.getAndIncrement() % serviceInstances.size());return serviceInstances.get(idx);}
}

加權輪詢算法(WeightedRoundRobin):根據不同實例的承載能力分配權重,權重越高,分配到請求的概率越大。

@Component("weightedRoundRobin")
public class WeightedRoundRobinLoadBalancer implements LoadBalancer {private final Map<String, Integer> weights;private Atomic Integer currentWeight=new AtomicInteger(0);@Overridepublic String selectServiceInstance(String serviceName) {String selectedInstance=null;int maxWeight=0;for (Map.Entry<String, Integer> entry : weights.entrySet()) {currentWeight.addAndGet(entry.getValue());if (currentWeight.get() > maxWeight) {maxWeight = currentWeight.get();selectedInstance = entry.getKey();}}return selectedInstance;}
}

隨機算法(RandomAlgo):如同擲骰子般隨機挑選服務實例,簡單直接。

@Component("randomAlgo")
public class RandomLoadBalancer implements LoadBalancer {private final Randomrandom=newRandom();private final List<String> serviceInstances;@Overridepublic String selectServiceInstance(String serviceName) {return serviceInstances.get(random.nextInt(serviceInstances.size()));}
}

加權隨機算法(WeightRandom):在隨機挑選的基礎上,綜合考慮實例權重,權重越大被選中的概率越高。

@Component("weightRandom")
public class WeightedRandomLoadBalancer implements LoadBalancer {private final Map<String, Integer> weights;private final Randomrandom=newRandom();@Overridepublic String selectServiceInstance(String serviceName) {int totalWeight= weights.values().stream().mapToInt(Integer::intValue).sum();int randomWeight= random.nextInt(totalWeight);for (Map.Entry<String, Integer> entry : weights.entrySet()) {randomWeight -= entry.getValue();if (randomWeight <= 0) {return entry.getKey();}}retur nnull;}
}

05定義 Feign 接口實現負載均衡調用

@FeignClient(name = "api-service", url = "http://api.example.com",configuration = FeignLoadBalancerConfig.class)
public interface ApiServiceFeign {@GetMapping("/query")Response fetchData(@RequestParam("param1") String param1,@RequestParam("param2") String param2);
}

注解:

  1. @FeignClient 注解的 configuration 屬性引入負載均衡相關配置,激活自定義攔截器。
  2. 接口方法通過 @GetMapping 定義具體請求路徑和參數映射,Feign 會自動將方法參數轉換為 HTTP 請求參數。

06配置細節與熔斷保障

在 application.yml 中合理配置,確保負載均衡與熔斷降級協同工作:

spring:cloud:openfeign:circuitbreaker:enabled:true# 啟用熔斷功能okhttp:enabled:true# 啟用 OkHttp 客戶端httpclient:enabled:true# 啟用 Apache HttpClientmax-connections:300# 最大連接數max-connections-per-route:100# 每路由最大連接數load:
balance:algorithm:com.example.loadbalancer.RoundRobin# 指定負載均衡算法instances:-http://server1.example.com:8080-http://server2.example.com:8081-http://server3.example.com:8082weights:http://server1.example.com:8080:1http://server2.example.com:8081:2http://server3.example.com:8082: 3

通過上述設計與實現,我們成功賦予 Feign 調用第三方接口的負載均衡能力,并通過熔斷降級保障系統穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87432.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87432.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87432.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

k8s pod調度基礎

目錄 一&#xff1a;replication controller和replicaset 1&#xff1a;replication controller replication controller的使用示例。 2&#xff1a;標簽與標簽選擇器 &#xff08;1&#xff09;標簽 &#xff08;2&#xff09;標簽選擇器 &#xff08;3&#xff09;標簽…

學習者的Python項目靈感

一、實用工具類 - 文件批量重命名工具 用 os 模塊實現按規則&#xff08;如添加日期、序號、替換關鍵詞&#xff09;批量重命名文件&#xff0c;適合處理大量圖片/文檔。 - 簡易待辦事項管理器&#xff08;To-Do List&#xff09; 用 tkinter 或 PyQt 做GUI界面&#xff0c;…

gRPC服務發現

基于 etcd 實現的服務發現&#xff0c;按照非規范化的 etcd key 實現&#xff0c;詳細見代碼注釋。 package discoveryimport ("context""encoding/json""fmt""go.etcd.io/etcd/api/v3/mvccpb"clientv3 "go.etcd.io/etcd/client/…

基于Linux的Spark本地模式環境搭建實驗指南

一、實驗目的 掌握Spark本地模式的安裝與配置方法驗證Spark本地環境是否搭建成功了解Spark基本操作和運行原理 二、實驗環境準備 操作系統&#xff1a;Linux&#xff08;推薦ubuntu&#xff09;Java環境&#xff1a;JDK 1.8或以上版本內存&#xff1a;至少4GB&#xff08;推…

數學建模_時間序列

什么是時間序列時間序列預測方法/模型條件&#xff1a;非白噪音平穩平穩性評估不平穩變成平穩然后用ARIMA模型確定p,qAR模型(ARMA特例)MA模型(ARMA特例)ARMA模型(普適)灰色模型神經網絡/LSTM組合預測模型向量數據預測結果和為1的情況什么是時間序列 省略具體圖形例子 時間序列…

linux用rpm包升級sudo包為sudo-1.9.17-2版本

rpm下載地址&#xff1a; https://www.sudo.ws/dist/packages/1.9.17p1/ 備注&#xff1a;其他壓縮包下載地址&#xff1a;https://www.sudo.ws/download.html sudo-1.9.17-2.el7.x86_64.rpm 檢查一下&#xff0c;本地sudo版本&#xff0c;執行&#xff1a;sudo -V 或者sudo -…

【開源項目】一款真正可修改視頻MD5工具視頻質量不損失

文章目錄 視頻MD5修改工具 ???? 目錄? 功能特點?? 系統要求??? 設計架構?? 技術原理?? 核心代碼1. 視頻MD5修改核心邏輯2. 前端異步處理代碼3. 錯誤處理與日志記錄?? 安裝方法方法一:直接下載方法二:使用本地服務器?? 使用教程基本使用步驟高級使用技巧??…

Day05: Python 中的并發和并行(1)

理解 Python 中的線程和進程 理解線程和進程是實現在 Python 中并發和并行的基礎。這種知識使你能夠編寫能夠看似同時執行多個任務的程序&#xff0c;從而提高性能和響應能力。本課程將深入探討線程和進程的核心概念、它們的區別&#xff0c;以及它們如何為更高級的并發技術奠…

Spring Boot 集成 MinIO 實現分布式文件存儲與管理

Spring Boot 集成 MinIO 實現分布式文件存儲與管理 一、MinIO 簡介 MinIO 是一個高性能的分布式對象存儲服務器&#xff0c;兼容 Amazon S3 API。它具有以下特點&#xff1a; 輕量級且易于部署高性能&#xff08;讀寫速度可達每秒數GB&#xff09;支持數據加密和訪問控制提供…

從小白入門,基于Cursor開發一個前端小程序之Cursor 編程實踐與案例分析

Cursor 編程實踐與案例分析 Cursor 編程實踐與案例分析 1. 什么是 Cursor&#xff1f; Cursor 是一款面向開發者的 AI 編程助手&#xff0c;集成于本地 IDE&#xff0c;支持自然語言與代碼的無縫協作。它不僅能自動補全、重構、查找代碼&#xff0c;還能理解業務上下文&#…

一、如何用MATLAB畫一個三角形 代碼

一、如何用MATLAB畫一個三角形 代碼在MATLAB中繪制三角形可以通過指定三個頂點的坐標并使用 fill 或 patch 函數實現。以下是詳細代碼示例&#xff1a;方法1&#xff1a;使用 fill 函數&#xff08;簡單填充&#xff09;% 定義三角形的三個頂點坐標 (x, y) x [0, 1, 0.5]; % …

Postman自動化測試提取相應body體中的參數

文章目錄Postman自動化測試提取相應body體中的參數1. 示例響應 Body 參數2. 提取響應 Body 參數Postman自動化測試提取相應body體中的參數 上一篇的文中介紹了使用postman自動化測試時從響應的header中提取token參數&#xff0c;很多同學私信問如何從響應體body中提取參數。 有…

vue-39(為復雜 Vue 組件編寫單元測試)

實際練習:為復雜 Vue 組件編寫單元測試 單元測試對于確保復雜 Vue 組件的可靠性和可維護性至關重要。通過隔離和測試代碼的各個單元,您可以在開發過程的早期發現并修復錯誤,從而構建更健壯和可預測的應用程序。本課程重點介紹為復雜 Vue 組件編寫單元測試的實用方面,建立在…

c語言中的函數IV

函數的先后關系 直接把函數放在程序上方是可以的 在實際開發中&#xff0c;我們更希望把main函數放在前面 這樣子直接把自己定義的函數放在main函數下方&#xff0c;編譯會出現warning和error正確的解決方案是&#xff1a;把函數的頭放到main函數上方&#xff0c;這樣就能正常…

大模型Decoder-Only深入解析

Decoder-Only整體結構 我們以模型Llama-3.1-8B-Instruct為例&#xff0c;打印其結構如下&#xff08;后面會慢慢解析每一部分&#xff0c;莫慌&#xff09;&#xff1a; LlamaForCausalLM((model): LlamaModel((embed_tokens): VocabParallelEmbedding(num_embeddings128256,…

web網頁,在線%電商,茶葉,商城,網上商城系統%分析系統demo,于vscode,vue,java,jdk,springboot,mysql數據庫

經驗心得 這也是幫之前一客戶加了幾個功能&#xff0c;需要掌握crud&#xff0c;前后端開發&#xff0c;前后端怎么對接&#xff0c;前后端通訊是以那種格式&#xff0c;把這些掌握后咱們就可以進行網站開發了。后端記好一定要分層開發&#xff0c;不要像老早一起所有代碼寫到一…

MybatisPlus-05.核心功能-條件構造器

一.條件構造器 我們前面使用的MP功能主要是根據id進行操作的&#xff0c;并未涉及到復雜查詢。而根據id所進行的增刪改查操作在MP中都有直接的封裝。但是遇到復雜的查詢條件時&#xff0c;如何使用MP進行操作是我們要考慮的問題。因此MP為我們提供了條件構造器。 在BaseMapper…

ES6從入門到精通:常用知識點

變量聲明ES6引入了let和const替代var。let用于聲明可變的塊級作用域變量&#xff0c;const用于聲明不可變的常量。塊級作用域有效避免了變量提升和污染全局的問題。let name Alice; const PI 3.1415;箭頭函數箭頭函數簡化了函數寫法&#xff0c;且自動綁定當前上下文的this值…

51單片機教程(十一)- 單片機定時器

11、單片機定時器 項目目標 通過定時器/計數器實現流水燈控制。知識要點 定時器的結構。TMOD和TCON;定時/計數器工作方式;定時/計數器編程步驟;1、項目分析 前面的流水燈的時間控制通過空循環語句來實現,定時不是很精確。本章通過用定時器來控制流水燈任務可以實現精確的時…

基于opencv的疲勞駕駛監測系統

博主介紹&#xff1a;java高級開發&#xff0c;從事互聯網行業多年&#xff0c;熟悉各種主流語言&#xff0c;精通java、python、php、爬蟲、web開發&#xff0c;已經做了多年的畢業設計程序開發&#xff0c;開發過上千套畢業設計程序&#xff0c;沒有什么華麗的語言&#xff0…