關于Feign的覆寫默認配置和Feign的日志
Feign的覆寫默認配置
A central concept in Spring Cloud’s Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the @FeignClient annotation. Spring Cloud creates a new ensemble as anApplicationContext on demand for each named client using FeignClientsConfiguration. This contains (amongst other things) an feign.Decoder, a feign.Encoder, and a feign.Contract.
上面是官網(wǎng)的API文檔中的說明,如下是我的翻譯:
Spring Cloud的Feign支持的一個中心概念是命名客戶端。
每個feign client是整體的一部分,它們一起工作以按需聯(lián)系遠程服務器,并且該整體具有一個名稱,開發(fā)人員可以使用@FeignClient將其命名。
Spring Cloud根據(jù)需要使用FeignClientsConfiguration為每個命名的客戶端創(chuàng)建一個新的整體作為ApplicationContext。
這包含(其他)feign.Decoder,feign.Encoder和feign.Contract。
Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of theFeignClientsConfiguration) using @FeignClient. Example:
@FeignClient(name = “stores”, configuration = FooConfiguration.class) public interface StoreClient { //.. }
上面文檔說,通過使用額外的配置@FeignClient注解,可以使Spring Cloud讓你完全的控制feign客戶端。
并且官網(wǎng)還給出了例子,那么我們也按照它提供的例子來在我們的工程師運用起來。
將接口類UserFeignClient進行修改,如下修改后的代碼:
@FeignClient(name = "microservice-provider-user", configuration = FooConfiguration.class) public interface UserFeignClient { ? ? /** ? ? ?* 注意:要使用Feign的注解 ? ? ?* <p> ? ? ?* <code>@RequestLine("GET /repos/{owner}/{repo}/contributors")</code> ? ? ?* <br> ? ? ?* <code>List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);</code> ? ? ?*? ? ? ?* @param id ? ? ?* @return ? ? ?*/ ? ? @RequestMapping(method = RequestMethod.GET, value = "/simple/{id}") // ?@RequestLine("GET /simple/{id}") ? ? public User findById(@PathVariable("id") Long id); }
在配置FeignClient的configuration指定的值FooConfiguration,這個類是不存在的,這里我們需要新建,官網(wǎng)中也給我創(chuàng)建了這個類的代碼,下面是我根據(jù)官網(wǎng)的代碼和我實際需求修改后的:
@Configuration public class FooConfiguration { ? ? @Bean ? ? public Contract feignContract() { ? ? ? ? return new feign.Contract.Default(); ? ? } }
完成之后,可以開始啟動工程了,當我們在啟動時,會報錯,錯誤關鍵如下:
Caused by: java.lang.IllegalStateException: Method findById not annotated with HTTP method type (ex. GET, POST)
這里錯誤是說我們沒有使用Http方法的注解導致的,但我們仔細檢查下代碼,我們使用的是@RequestMapping的注解方式,這里我也不知道怎么解釋,可能是我沒有深刻的理解吧,看了Feign 的GitHub的相關代碼后,我發(fā)現(xiàn)了另一種注解方式:
interface GitHub { ? @RequestLine("GET /repos/{owner}/{repo}/contributors") ? List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo); }
好的,現(xiàn)在將@RequestMapping注解改成@RequestLine,以及參數(shù)也修改成@Param,修改后:
@FeignClient(name = "microservice-provider-user", configuration = FooConfiguration.class) public interface UserFeignClient { ? ? /** ? ? ?* 注意:要使用Feign的注解 ? ? ?* <p> ? ? ?* <code>@RequestLine("GET /repos/{owner}/{repo}/contributors")</code> ? ? ?* <br> ? ? ?* <code>List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);</code> ? ? ?*? ? ? ?* @param id ? ? ?* @return ? ? ?*/ ? ? @RequestLine("GET /simple/{id}") ? ? public User findById(@Param("id") Long id); }
修改完成之后,再次重啟服務,發(fā)現(xiàn)啟動成功,而且可以訪問接口了。
WARNING Previously, using the url attribute, did not require the name attribute. Using name is now required.
官網(wǎng)中有個這樣的提醒:以前在使用URL屬性時,不必要使用那么屬性,但是在現(xiàn)在Feign中name屬性就是必要的了。
它也給了例子,如下面代碼:
@FeignClient(name = "${feign.name}", url = "${feign.url}") public interface StoreClient { ? ? //.. }
現(xiàn)在我們也來在我們的工程中實際運用一下。
新建一個接口FeignClient2,代碼如下:
@FeignClient(name = "xxx", url = "http://localhost:8761/", configuration = BeanConfiguration.class) public interface FeignClient2 { // ?@RequestMapping(value = "/eureka/apps/{serviceName}") ? ? @RequestLine("GET /eureka/apps/{serviceName}") ? ? public String findServiceInfoEurekaByServieName(@Param("serviceName") String serviceName); }
我們通過這個feign來獲取eureka server下注冊的實例信息,通過@FeignClient注解配置了name、url和configuration屬性,這里那么我隨便寫的內(nèi)容,因為這個僅僅表示這個feign的名稱而已,url配置的是eureka server的地址,configuration我們這里配的一個需要新建的類BeanConfiguration。
大家肯定還有疑惑,這個BeanConfiguration類配置了是起什么作用的了?
好的,這里就為大家答疑解惑,首先貼出該類的代碼:
@Configuration public class BeanConfiguration { ? ? @Bean ? ? public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { ? ? ? ? return new BasicAuthRequestInterceptor("micheal", "123456"); ? ? } }
看到代碼,也許大家可能就明白了,這個在請求時不需要輸入用戶名和密碼就可以直接調(diào)用Eureka Server,因為Feign通過這個配置的configuration類為我們做了用戶名和密碼的權限認證了。
完成上面的內(nèi)容了,接下來就是見證奇跡的時刻了。
啟動服務,在Eureka Server中查看到注冊成功了,我們就可以通過瀏覽器進行查看了。
Feign Logging 日志
A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the DEBUG level.
application.yml
logging.level.project.user.UserClient: DEBUG
官網(wǎng)API說:為每個Feign 客戶端創(chuàng)建日志,日志的默認名稱為所創(chuàng)建的Feign客戶端接口類的整個類名。Feign的日志僅僅只有在DEBUG級別時才會響應。
官網(wǎng)給我們提供了例子,按照官網(wǎng)提供的做法,現(xiàn)在來為我們對的工程配置Feign Logging。
以我們microservice-consumer-movie-feign-customizing工程為例,在配置文件application.yml進行Feign 日志配置,如下配置:
logging: ? level: ? ? com.spring.cloud.feign.UserFeignClient: DEBUG
com.spring.cloud.feign.UserFeignClient 是Feign Client接口類的完成類名。好了,完成了這個配置,是不是有點超激動想要一看是否真的能打印出日志了。
先不著急,我們接著查看官網(wǎng)API文檔中的內(nèi)容:
The Logger.Level object that you may configure per client, tells Feign how much to log. Choices are:
• NONE, No logging (DEFAULT).
• BASIC, Log only the request method and URL and the response status code and execution time.
• HEADERS, Log the basic information along with request and response headers.
• FULL, Log the headers, body, and metadata for both requests and responses.
For example, the following would set the Logger.Level to FULL:
@Configuration public class FooConfiguration { ? ? @Bean ? ? Logger.Level feignLoggerLevel() { ? ? ? ? return Logger.Level.FULL; ? ? } }
官網(wǎng)給我們提供了一些日志級別的等級,這里就不一一翻譯了。我們的重點是在上面所給的例子,上面例子說為日志設置為FULL級別的日志。
好,開始我們的配置,找到我們所配Feign 日志的客戶端接口類,我們發(fā)現(xiàn)我們配值得configuration的類時FooConfiguration類,好我們將官網(wǎng)中的feignLoggerLevel方法添加到我們的FooConfiguration類中。
完成之后,我們啟動工程,并先將日志清掉,再重新請求接口,發(fā)現(xiàn)確實打印出日志來了。
這里還需要補充一下:在配置文件application.yml中配置了Feign客戶端日志之后,如果不在configuration類中添加日志級別的話,是不會打印出日志的。因為在官網(wǎng)API中有提到“NONE, no loggin(DEFAULT)”,就是說默認日志級別時NONE的。
Feign進行日志配置
在微服務項目中項目啟動遇到 bug 時,很多方面的錯誤都有可能出現(xiàn),比如參數(shù)錯誤,接口調(diào)用錯誤等,或者是想了解服務接口的使用量和性能。
首先 Feign 支持自定義日志的配置,配置 Feign 的日志信息是針對以上情況效率很高的一種解決方案。
Feign有四種類型的日志
NONE
:不記錄任何日志信息,默認是 NONE 配置。BASIC
:只記錄發(fā)起請求的方法,請求的 URL 地址,請求狀態(tài)碼和請求的響應時間。HEADERS
:在 BASIC 級別的基礎上,還多記錄了請求頭和響應頭的信息。FULL
:記錄所有的日志信息,包括請求和響應的所有具體信息。
列出兩種在項目中配置Feign日志的方法
一:在配置文件中配置 Feign 的日志
feign: ? client: ? ? config: ? ? ? default: # 這里用default就是全局配置,如果是寫服務名稱,則是針對某個微服務的配置 ? ? ? ? loggerLevel: FULL # ?日志級別
其中 default 表示全局配置日志,將 default 改為具體的服務名稱,表示在調(diào)用這個服務的時候才會記錄日志。
loggerLevel 表示日志的水平,包含 NONE、BASIC、HEADERS、FULL 四種級別的日志。
二:通過配置類的方式
聲明一個類,取名為 FeignLoggerConfiguration。在類中聲明一個 Logger.Level 對象并返回日志級別,這里設置級別為 BASIC ,通過 @Bean 注解將該方法設置為 IOC 容器的組件。
public class FeignLevelConfiguration { ? ? @Bean ? ? public Logger.Level logLevel(){ ? ? ? ? return Logger.Level.BASIC; ? ? } }
同樣的可以設置全局配置和局部給某個服務配置。
全局配置:
在啟動類的 @EnableFeignClients 注解中加上參數(shù)
defaultConfiguration = FeignLoggerConfiguration .class
這里的 FeignLoggerConfiguration.class要和配置的日志類一致。
局部配置:
在配置了 Feign 的服務接口上的注解 @FeignClient("要調(diào)用的服務名稱") 加上參數(shù)
configuration = FeignLoggerConfiguration .class
這里設置調(diào)用的服務名稱為 testservice ,則注解改為
@FeignClient(value = "testservice", configuration = FeignLoggerConfiguration .class)?
這里的 FeignLoggerConfiguration.class 就是上面的日志配置類。
同時,在優(yōu)化 Feign 時可以從日志的級別入手,日志盡量使用 Basic 級別,因為打印日志太多會消耗 Feign 的性能。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Hadoop環(huán)境配置之hive環(huán)境配置詳解
這篇文章主要介紹了Hadoop環(huán)境配置之hive環(huán)境配置,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-12-12一文詳解Spring任務執(zhí)行和調(diào)度(小結)
這篇文章主要介紹了一文詳解Spring任務執(zhí)行和調(diào)度(小結),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08Spring框架實現(xiàn)AOP添加日志記錄功能過程詳解
這篇文章主要介紹了Spring框架實現(xiàn)AOP添加日志記錄功能過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12