5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細使用 @目錄5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細使用前言1. OpenFeign 介紹1.1 Feign 和 OpenFeign 區(qū)別2. Op
@[toc]
- 對應上一篇學習內容:??? 4. Spring Cloud Ribbon 實現(xiàn)“負載均衡”的詳細配置說明_ribbon升級到了loadbalancer-CSDN博客
- 對應下一篇學習內容:???
OpenFeign 是什么 ?
OpenFeign 是個聲明式
WebService
客戶端,使用 OpenFeign 讓編寫 Web Service客戶端更簡單。
它的使用方法是 定義一個服務接口,然后在上面添加注解。
OpenFeign 也支持可插拔式的 編碼器 和 解碼器 。
Spring Cloud 對 OpenFeign 進行了封裝使其支持了 Spring MVC 標注注解 和
HttpMessageConverters
。
OpenFeign 可以與 Eureka 和 Ribbon 組合使用以支持負載均衡。
OpenFeign 官網(wǎng)地址: https://github.com/spring-cloud/spring-cloud-openfeign
簡單的說:就是一個 Web Service 客戶端訪問的,轉發(fā)的一個組件,可以實現(xiàn) Server 集群的通信,簡化 Web Service 客戶端 。
Feign:
org.springframework.cloud
spring-cloud-starter-openfeign
OpenFeign:
org.springframework.cloud
spring-cloud-starter-openfeign
需求分析&圖解
示意圖:
參考 member-service-consumer-80 創(chuàng)建 member-service-consumer-openfeign-80(具體步 驟參考以前)
pom.xml
文件當中,導入相關的 jar 依賴。特別是這里:我們的主角
openFeign
。
org.springframework.cloud
spring-cloud-starter-openfeign
完整的 pom.xml 文件信息:
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">
e-commerce-center
com.rainbowsea
1.0-SNAPSHOT
4.0.0
member-service-consumer-openfeign-80
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.rainbowsea
e_commerce_center-common-api
${project.version}
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
application.yml
進行一些相關的配置信息, 內容如下:
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
# 配置 eureka client 注意,因為這里該模塊是作為 client 客戶端的角色的,所有要將自己client的信息發(fā)送給 Server 當中去的
eureka:
client:
register-with-eureka: true # 表示將自己注冊到 Eureka-Server 當中
fetch-registry: true # 表示將信息發(fā)送到 Eureka-Server 當中
service-url:
# 表示將自己注冊到那個 eureka-server
# defaultZone: http://localhost:9001/eureka
# 將本微服務注冊到多個 eureka - server 當中,使用逗號間隔即可
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
member-service-consumer-openfeign-80
的主啟動類,也就是場景啟動器。
在:創(chuàng)建包
com.rainbowsea.springcloud
,創(chuàng)建名為
MemberConsumerOpenfeignApplication80
的主啟動類,如下圖所示:
package com.rainbowsea.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient // 表示作為 Eureka Client 角色
@EnableFeignClients // 啟動 OpenFeignClient
public class MemberConsumerOpenfeignApplication80 {
public static void main(String[] args) {
SpringApplication.run(MemberConsumerOpenfeignApplication80.class, args);
}
}
添加主啟動類之后,我們可以測試一下,是否成功將該模塊
member-service-consumer-openfeign-80
注冊到了 Eureka Server 當中去了。
注意:下面的操作就是:是 OpenFeign 的核心內容了。
member-service-consumer-openfeign-80
模塊當中創(chuàng)建一個
com.rainbowsea.springcloud.service
包,在該包當中創(chuàng)建一個
MemberFeignService
接口,注意注意是接口
interface
不是類。如下圖所示:
package com.rainbowsea.springcloud.service;
import com.rainbowsea.springcloud.entity.Result;
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
public interface MemberFeignService {
}
然后我們需要將其中,我們
member-service-consumer-openfeign-80
模塊是作為 Eureka Client 客戶端存在的,這里使用 OpenFeign 簡化客戶端,我們還需將 ,我們 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要調用的哪個
provider service(服務器/服務集群)
處理我們的業(yè)務,這里我們是
服務集群
,這里我們有兩個 privoid service 可以處理我們所需的業(yè)務,如下圖所受:分別為:
member-service-provider-10000,member-service-provider-10002 這兩個服務(這兩個服務,是已經相互注冊好了,配置為了服務集群了 )
這里我們在
MemberFeignService
接口類上使用
@FeignClient
注解標注,我們這個 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要調用的哪個
provider service(服務器/服務集群)
處理我們的業(yè)務。如下圖所示:
package com.rainbowsea.springcloud.service;
import com.rainbowsea.springcloud.entity.Result;
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
//這里 MEMBER-SERVICE-PROVIDER 就是 Eureka Server 服務提供方注冊的名稱
@FeignClient(value = "MEMBER-SERVICE-PROVIDER") // 這個 value 值就是,對應我們想要訪問的 provider(提供服務/服務集群)的 name 名稱
public interface MemberFeignService {
}
同時我們還需要在
MemberFeignService
接口當中定義一個方法。
注意這個方法,必須必須和你 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要調用的哪個
provider service(服務器/服務集群)
中的處理對應業(yè)務的 哪個方法 ,保持一致(權限修飾符一致,**Http請求方式(包括了所對應的請求映射路徑)**一致,參數(shù)類型,參數(shù)個數(shù)一致,返回值類型也是一致的,方法名可以不一致(但強烈建議也保持一致)),所以強烈建議,直接從對應的 provider service 當中復制過來即可。如下圖:我們使用的是getMemberById
根據(jù) id 查詢的業(yè)務處理。我們只需將其方法名復制過來即可。
package com.rainbowsea.springcloud.service; import com.rainbowsea.springcloud.entity.Result; 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 //這里 MEMBER-SERVICE-PROVIDER 就是 Eureka Server 服務提供方注冊的名稱 @FeignClient(value = "MEMBER-SERVICE-PROVIDER") // 這個 value 值就是,對應我們想要訪問的 provider(提供服務/服務集群)的 name 名稱 public interface MemberFeignService { // 注意:這里定義方法-就是遠程調用的接口,建議復制過來 /* 1.遠程調用的方式是get 2.遠程調用的 url http://MEMBER-SERVICE-PROVIDER(注冊到服務當中的別名)/member/get/{id} 3.MEMBER-SERVICE-PROVIDER 就是服務提供方法 Eureka Server 注冊的服務 4. openfeign 會根據(jù)負載均衡決定調用 10000/10002 -默認是輪詢 5.因為openfeign 好處是支持了 spring mvc 注解 + 接口解構 6. 想要使用 OPFeign 需要在對應場景啟動器的位置配置上: @EnableFeignClients // 啟動 OpenFeignClient */ @GetMapping("/member/get/{id}") Result getMemberById(@PathVariable("id") Long id); }
最后,我們在當前
member-service-consumer-openfeign-80
模塊也就是我們的 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 編寫控制器,在
com.rainbowsea.springcloud.controller
包下,編寫對應的控制器。如下圖所示:
package com.rainbowsea.springcloud.controller;
import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberFeignService;
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;
@RestController
public class MemberConsumerFeignController {
// 裝配MemberFeignService
@Resource
private MemberFeignService memberFeignService;
@GetMapping("/member/consumer/openfeign/get/{id}")
public Result getMemberById(@PathVariable("id") Long id) {
// 調用接口中的方法
return memberFeignService.getMemberById(id);
}
}
- 特別說明,因為我們的 OpenFeign 就是一個通過
接口+注解的
方式作為Eureka Client 客戶端,調用其中 Service 服務器- Openfeign 的使用的特點:
微服務接口+@FeignClient
,使用接口進行解耦(簡單的說:就是使用接口調用對應 provider 提供服務的集群)
測試,啟動服務器
瀏覽器輸入 : http://localhost/member/consumer/openfeign/get/1
觀察訪問的 10000/10002 端口的服務是輪詢的
@FeignClient(value = "MEMBER-SERVICE-PROVIDER")
// 這個 value 值就是,對應我們想要訪問的 provider(提供服務/服務集群)的 name 名稱 所以:注意不要將提供注冊的名稱,寫錯了
說明 OpenFeign 提供了日志打印功能,可以通過配置來調整日志級別,從面對 OpenFeign 接口的調用情況進行監(jiān)控和輸出。
日志級別:
- NONE: 默認的,不顯示任何日志
- BASIC: 僅記錄請求方式,URL,響應狀態(tài)碼及執(zhí)行時間
- HEADERS:除了 BASIC 中定義的信息之外,還有請求和響應的頭信息
- FULL: 除了HEADERS 中定義的信息之外,還有請求和響應的正文及元數(shù)據(jù)
常見的日志級別有 5 種,分別是 error、warn、info、debug、trace
- error:錯誤日志,指比較嚴重的錯誤,對正常業(yè)務有影響,需要運維配置監(jiān)控的;
- warn:警告日志,一般的錯誤,對業(yè)務影響不大,但是需要開發(fā)關注;
- info:信息日志,記錄排查問題的關鍵信息,如調用時間、出參入?yún)⒌鹊龋?
- debug:用于開發(fā) DEBUG 的,關鍵邏輯里面的運行時數(shù)據(jù);
- trace:最詳細的信息,一般這些信息只記錄到日志文件中。
在member-service-consumer-openfeign-80 創(chuàng)建 com.Rainbowsea.springcloud.config.OpenFeignConfig.java 類
package com.rainbowsea.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenFeignConfig {
@Bean
public Logger.Level loggerLever() {
// /日志級別指定為 FULL
return Logger.Level.FULL;
}
}
在
member-service-consumer-openfeign-80
模塊當中修改
application.yml
進行配置我們是對哪個類進行日志打印信息,以及打印配置的日志信息的
級別
。
logging:
level:
# 對 MemberFeignService 接口調用過程打印信息-Debug
com.rainbowsea.springcloud.service.MemberFeignService: debug
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
# 配置 eureka client 注意,因為這里該模塊是作為 client 客戶端的角色的,所有要將自己client的信息發(fā)送給 Server 當中去的
eureka:
client:
register-with-eureka: true # 表示將自己注冊到 Eureka-Server 當中
fetch-registry: true # 表示將信息發(fā)送到 Eureka-Server 當中
service-url:
# 表示將自己注冊到那個 eureka-server
# defaultZone: http://localhost:9001/eureka
# 將本微服務注冊到多個 eureka - server 當中,使用逗號間隔即可
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
logging:
level:
# 對 MemberFeignService 接口調用過程打印信息-Debug
com.rainbowsea.springcloud.service.MemberFeignService: debug
測試
瀏覽器: http://localhost/member/consumer/openfeign/get/1
IDEA 后端查看打印的顯示的日志信息:
OpenFeign 超時: 我們先來看如下一個問題:
我們模擬網(wǎng)絡異常,在
member-service-provider-10000
和
member-service-provider-10002
兩個 service 服務提供方當中的
getMemberById
方法,模擬超時 ,這里暫停 5秒。
// 模擬超時 ,這里暫停 5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
瀏覽器訪問 http://localhost/member/consumer/openfeign/get/1
測試效果:
瀏覽器顯示: Read timed out executing GET http://MEMBER-SERVICE-PROVIDER/member/get/1
IDEA后端顯示: java.net.SocketTimeoutException: Read timed out
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.RetryableException: Read timed out executing GET http://MEMBER-SERVICE-PROVIDER/member/get/1] with root cause
原因分析: OpenFeign 默認超時時間 1 秒鐘 ,即等待返回結果 1 秒 ,超過了 1 秒,則會報錯。
設置超時時間
說明: 在某些情況下,一個服務調用時間可能要超過 1 秒,就需要重新設置超時時間。
這里我們設置超時時間設置為:
8秒
,而我們模擬的是 5秒,5 秒小于 8 秒,可以還在超時時間的范圍內,可以被訪問。
對于 OpenFeign 超時時間,我們需要在
application.yaml
文件當中進行配置。
如下圖所示:
# OpenFeign 超時
ribbon:
# #設置 feign 客戶端超時時間(openFeign 默認支持 ribbon) #指的是建立連接后從服務器讀取到可用資源所用的時間,
# #時間單位是毫秒
ReadTimeout: 8000
# #指的是建立連接所用的時間,適用于網(wǎng)絡狀況正常的情況下,
# #兩端連接所用的時間
ConnectTimeout: 8000
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
# 配置 eureka client 注意,因為這里該模塊是作為 client 客戶端的角色的,所有要將自己client的信息發(fā)送給 Server 當中去的
eureka:
client:
register-with-eureka: true # 表示將自己注冊到 Eureka-Server 當中
fetch-registry: true # 表示將信息發(fā)送到 Eureka-Server 當中
service-url:
# 表示將自己注冊到那個 eureka-server
# defaultZone: http://localhost:9001/eureka
# 將本微服務注冊到多個 eureka - server 當中,使用逗號間隔即可
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
logging:
level:
# 對 MemberFeignService 接口調用過程打印信息-Debug
com.rainbowsea.springcloud.service.MemberFeignService: debug
# OpenFeign 超時
ribbon:
# #設置 feign 客戶端超時時間(openFeign 默認支持 ribbon) #指的是建立連接后從服務器讀取到可用資源所用的時間,
# #時間單位是毫秒
ReadTimeout: 8000
# #指的是建立連接所用的時間,適用于網(wǎng)絡狀況正常的情況下,
# #兩端連接所用的時間
ConnectTimeout: 8000
瀏覽器輸出: http://localhost/member/consumer/openfeign/get/1, 不會出現(xiàn)超時,會輪詢訪問 10000/10002
當我們在
pom.xml
當中添加了
spring-boot-starter-actuator
的依賴 jar ,就就可以使用該 監(jiān)控系統(tǒng)了。不需要其他的配置
spring-boot-starter-actuator 是spring boot 程序的監(jiān)控系統(tǒng),可以實現(xiàn)健康檢查,info 信息等
訪問http://localhost:80/actuator 可以看到相關鏈接,還可以做相關配置。
spring-boot-starter-actuator
訪問的語法鏈接:url地址+自身模塊對應的端口號/actuator
。
WebService
客戶端,使用 OpenFeign 讓編寫 Web Service客戶端更簡單。
微服務接口+@FeignClient
,使用接口進行解耦(簡單的說:就是使用接口調用對應 provider 提供服務的集群)
微服務接口+@FeignClient
,使用接口進行解耦(簡單的說:就是使用接口調用對應 provider 提供服務的集群)
spring-boot-starter-actuator
訪問的語法鏈接:
url地址+自身模塊對應的端口號/actuator
。
“在這個最后的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回復是我創(chuàng)作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續(xù)在其他的領域奮斗。感謝你們,我們總會在某個時刻再次相遇!
本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權,請發(fā)郵件[email protected]
湘ICP備2022002427號-10 湘公網(wǎng)安備:43070202000427號© 2013~2025 haote.com 好特網(wǎng)