OpenFeign和Gateway
- 一.OpenFeign介紹
- 二.快速上手
- 1.引入依賴
- 2.開啟openfeign的功能
- 3.編寫客戶端
- 4.修改遠程調用代碼
- 5.測試
- 三.OpenFeign參數傳遞
- 1.傳遞單個參數
- 2.多個參數、傳遞對象和傳遞JSON字符串
- 3.最佳方式寫代碼
- 繼承的方式
- 抽取的方式
- 四.部署OpenFeign
- 五.統一服務入口-Gateway
- 1.網關
- 2.常見網關實現
- 六.快速上手
- 七.Gateway
- 1.Predicate
- 2.Route Predicate Factories
- 3.Gateway Filter Factories(網關過濾器工廠)
- GatewayFilter
- GlobalFilter
- 過濾器執行順序
- ?定義過濾器
- 八.部署Gateway
一.OpenFeign介紹
OpenFeign是?個聲明式的Web Service 客戶端。它讓微服務之間的調?變得更簡單,類似controller
調?service,只需要創建一個接口,然后添加注解即可使?OpenFeign。
OpenFeign的前身:
Feign 是 Netflix 公司開源的一個組件。
- 2013年6月:Netflix發布 Feign的第一個版本 1.0.0
- 2016年7月:Netflix發布Feign的最后一個版本 8.18.0
- 2016年:Netflix 將 Feign 捐獻給社區
- 2016年7月:OpenFeign 的首個版本 9.0.0 發布,之后一直持續發布到現在.
可以簡單理解為Netflix Feign 是OpenFeign的祖先。或者說OpenFeign 是Netflix Feign的升級版。OpenFeign 是Feign的一個更強大更靈活的實現。
Spring Cloud Feign
Spring Cloud Feign 是 Spring 對 Feign 的封裝,將 Feign 項目集成到 Spring Cloud生態系統中。
受 Feign 更名影響,Spring Cloud Feign 也有兩個 starter
- spring-cloud-starter-feign
- spring-cloud-starter-openfeign
由于Feign的停更維護,對應的,我們使用的依賴是 spring-cloud-starter-openfeign
OpenFeign 官方文檔
Spring Cloud Feign官方文檔
二.快速上手
1.引入依賴
在訂單項目中引入openfeign的依賴:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
2.開啟openfeign的功能
給訂單項目的啟動類加上openfeign的注解:
3.編寫客戶端
在訂單服務中寫一個api,value代表微服務的名稱,path代表Feign客戶端的統一前綴
4.修改遠程調用代碼
5.測試
三.OpenFeign參數傳遞
1.傳遞單個參數
ProductController:
ProductAPI:
在Order項目中寫一個FeignController:
2.多個參數、傳遞對象和傳遞JSON字符串
ProductController:
ProductAPI:
FeignController:
3.最佳方式寫代碼
繼承的方式
創建一個公共的包來提取公共代碼,創建包的方式和之前相同:
再將ProductAPI里面寫的代碼復制到新的ProductAPI項目的包中的,寫成接口的形式:
此時需要將ProductInfo引入到這個項目中,但是其他的幾個微服務項目都有這個類于是,可以將這個代碼復制到這個API項目中,其他的微服務項目直接刪除原來的ProductInfo這個類,通過API項目打包的形式放入到起到微服務的POM文件中:
-
先進行install,把當前工程打成jar包,放在Maven的本地倉庫
-
打包好后對其進行引入后,就會有POM文件自動生成:
-
實現接口:
-
訂單的微服務中ProductAPI繼承接口:
-
使用了ProductInfo和繼承了或者實現了ProductInterface都要將ProductInfo的包重新引入,并對方法進行一些修改。
抽取的方式
-
依舊是先建一個module,并在pom文件中引入對應的依賴:
-
將Order微服務的ProductAPI接口放到product-api微服務項目中的api包中,刪除Order原有的api接口:
-
對product-api進行打包:
-
啟動服務端
-
抽取調用方:
-
進行測試即可
四.部署OpenFeign
對兩個服務進行打包,Maven打包默認是從遠程倉庫下載的,product-api 這個包在本地,有以下解決方案:
- 上傳到Maven中央倉庫(參考:如何發布Jar包到Maven中央倉庫,比較麻煩)[不推薦]
- 搭建Maven私服,上傳Jar包到私服 [企業推薦]
- 從本地讀取Jar包 [個人學習階段推薦]
前兩種方法比較復雜,咱們使用第三種方式
- 從product-api的打包成功后的結果里找到本地Maven路徑寫到Order微服務的POM文件中:
- 上傳到云服務器上:
- 啟動jar包:
五.統一服務入口-Gateway
1.網關
API網關(簡稱網關)也是?個服務,通常是后端服務的唯一入口。它的定義類似設計模式中的Facade模式(門面模式,也稱外觀模式)。它就類似整個微服務架構的門面,所有的外部客戶端訪問,都需要經過它來進行調度和過濾。
網關核心功能:
權限控制: 作為微服務的入口,對用戶進行權限校驗,如果校驗失敗則進行攔截
動態路由: ?切請求先經過網關,但網關不處理業務,而是根據某種規則,把請求轉發到某個微服務
負載均衡:當路由的目標服務有多個時,還需要做負載均衡
限流: 請求流量過高時,按照網關中配置微服務能夠接受的流量進行放行,避免服務壓力過大
2.常見網關實現
業界常用的網關方式有很多,技術方案也較成熟,其中不乏很多開源產品,比如Nginx,Kong,Zuul,
Spring Cloud Gateway等。下面介紹兩種常見的網關方案。
Zuul
Zuul 是 Netflix 公司開源的一個API網關組件,是Spring Cloud Netflix 子項目的核心組件之一,它可以
和 Eureka、Ribbon、Hystrix 等組件配合使用
在Spring Cloud Finchley正式版之前,Spring Cloud推薦的網關是Netflix提供的Zuul(此處指Zuu 1.X).
然而Netflix在2018年宣布一部分組件進入維護狀態,不再進行新特性的開發。這部分組件中就包含Zuul
Spring Cloud Gateway
Spring Cloud Gateway 是Spring Cloud的?個全新的API網關項目,基于Spring + SpringBoot等技術
開發,目的是為了替換掉Zuul。
旨在為微服務架構提供一種簡單而有效的途徑來轉發請求,并為他們提供橫切關注點,比如:安全性,監控/指標和彈性。
在性能方面,根據官方提供的測試報告,Spring Cloud Gateway的RPS(每秒請求數)是Zuul的1.6倍。測
試報告參考
六.快速上手
- 創建項目和之前相同
- 引入網關的依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.example</groupId><artifactId>spring-cloud-gateway</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>gateway</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies></project>
- 寫啟動類:
- 寫配置信息:
server:port: 10030 # ?關端?
spring:application:name: gateway # 服務名稱cloud:nacos:discovery:server-addr: 1.95.194.117:8848gateway:routes: # ?關路由配置- id: order-service #路由ID, ?定義, 唯?即可uri: lb://order-service #?標服務地址predicates: #路由條件- Path=/order/**,/feign/**- id: product-service #路由ID, ?定義, 唯?即可uri: lb://product-service #?標服務地址predicates: #路由條件- Path=/product/**
- 測試
七.Gateway
1.Predicate
Predicate是Java 8提供的一個函數式編程接口,它接收一個參數并返回一個布爾值,用于條件過濾,請求參數的校驗。
代碼:
直接通過實現接口后,調用方法來使用:
直接是在創建對象的時候重寫方法來使用:
使用lambda表達式的使用:
Predicate 的其他方法
- isEqual(Object targetRef):比較兩個對象是否相等,參數可以為Null
- and(Predicate other):短路與操作,返回一個組成Predicate
- or(Predicate other):短路或操作,返回一個組成Predicate
- test(T t):傳入一個Predicate參數,用來做判斷
- negate(): 返回表示此Predicate邏輯否定的Predicate
2.Route Predicate Factories
Route Predicate Factories (路由斷言工廠,也稱為路由謂詞工廠,此處謂詞表示一個函數),在Spring
Cloud Gateway中,Predicate提供了路由規則的匹配機制。
我們在配置文件中寫的斷言規則只是字符串,這些字符串會被Route Predicate Factory讀取并處理,轉
變為路由判斷的條件。比如前面章節配置的 Path=/product/** ,就是通過Path屬性來匹配URL前綴是 /product 的請求。
這個規則是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 來實現的。Spring Cloud Gateway默認提供了很多Route Predicate Factory,這些Predicate會分別匹配HTTP請求的不同屬性,并且多個Predicate可以通過and邏輯進行組合。
更多參考
3.Gateway Filter Factories(網關過濾器工廠)
Predicate決定了請求由哪?個路由處理,如果在請求處理前后需要加?些邏輯,這就是Filter(過濾器)的
作用范圍了。
Filter分為兩種類型:Pre類型和Post類型。
Pre類型過濾器:路由處理之前執行(請求轉發到后端服務之前執行),在Pre 類型過濾器中可以做鑒權,限流等。
Post類型過濾器:請求執行?完成后,將結果返回給客戶端之前執行。
Spring Cloud Gateway 中內置了很多Filter,用于攔截和鏈式處理web請求。比如權限校驗,訪問超時等設定。
Spring Cloud Gateway從作用范圍上,把Filter可分為GatewayFilter 和GlobalFilter。
GatewayFilter: 應用到單個路由或者一個分組的路由上。
GlobalFilter: 應用到所有的路由上,也就是對所有的請求生效。
GatewayFilter
GatewayFilter 同 Predicate 類似,都是在配置文件 application.yml 中配置,每個過濾器的邏輯都是固定的。比如 AddRequestParameterGatewayFilterFactory 只需要在配置文件中寫AddRequestParameter,就可以為所有的請求添加?個參數,我們先通過?個例子來演示GatewayFilter如何使用。
快速上手:
- 添加yml配置
- order微服務中添加過濾器參數:
- 通過網管訪問后,日志中打印出userName:
GatewayFilter詳細介紹官網
Default Filters
前面的filter添加在指定路由下,所以只對當前路由生效,若需要對全部路由生效,可以使用spring.cloud.gateway.default-filters 這個屬性需要?個filter的列表。
yml配置
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
GlobalFilter
lobalFilter是Spring Cloud Gateway中的全局過濾器,它和GatewayFilter的作用是相同的。
GlobalFilter 會應用到所有的路由請求上,全局過濾器通常用于實現與安全性,性能監控和日志記錄等相關的全局功能。
Spring Cloud Gateway 內置的全局過濾器也有很多,比如:
- Gateway Metrics Filter:網關指標,提供監控指標
- Forward Routing Filter:用于本地forword,請求不轉發到下游服務器。
- LoadBalancer Client Filter:針對下游服務,實現負載均衡。
更多過濾器參考:Global Filters
演示:
- 添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 添加yml配置
spring:application:name: gateway # 服務名稱cloud:nacos:discovery:server-addr: gateway:metrics:enabled: true
management:endpoints:web:exposure:include: "*"endpoint:health:show-details: alwaysshutdown:enabled: true
- 測試
過濾器執行順序
一個項目中,既有GatewayFilter,又有 GlobalFilter時,執行的先后順序是什么呢? 請求路由后,網關會把當前項目中的GatewayFilter和GlobalFilter合并到一個過濾器鏈(集合)中,并進行排序,依次執行過濾器。
每一個過濾器都必須指定一個int類型的order值,默認值為0,表示該過濾的優先級。order值越小,優先級越高,執行順序越靠前。
- Filter通過實現Order接口或者添加@Order注解來指定order值。
- Spring Cloud Gateway提供的Filter由Spring指定.用戶也可以自定義Filter,由用戶指定。
- 當過濾器的order值?樣時,會按照 defaultFilter > GatewayFilter > GlobalFilter的順序執行
?定義過濾器
Spring Cloud Gateway提供了過濾器的擴展功能,開發者可以根據實際業務來?定義過濾器,同樣自定
義過濾器也?持GatewayFilter 和 GlobalFilter兩種.
自定義GatewayFilter
自定義GatewayFilter,需要去實現對應的接口 GatewayFilterFactory,Spring Boot 默認幫我們實現的抽象類是 AbstractGatewayFilterFactory,我們可以直接使用。
定義GatewayFilter
- 寫一個Custom的Config
- 自定義一個CustomGatewayFilterFactory類:
- 增加一點yml的配置:
- 測試:
**自定義GlobalFilter **
GlobalFilter的實現比較簡單,它不需要額外的配置,只需要實現GlobalFilter接口,自動會過濾所有的
Filter.
定義GlobalFilter:
八.部署Gateway
- 打包
- 把打好的jar包上傳云服務器
- 再通過nohup命令啟動jar包