Feign的日志配置
有时候我们遇到Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要配置Feign的日志了,以此让Feign把请求信息输出来。
全局配置
定义一个配置类,指定日志级别:
package com.morris.user.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置@Configuration
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
通过源码可以看到日志等级有4种,分别是:
- NONE:不记录任何日志(默认值),性能最佳,适用于生产
- BASIC:仅记录请求方法、URL、响应状态代码以及执行时间,适用于生产环境追踪问题
- HEADERS:在BASIC级别的基础上,记录请求和响应的header
- FULL:记录请求和响应的header、body和元数据,比较适用于开发及测试环境定位问题
上面只是指定日志的内容,还需要在配置文件中配置Client的日志级别才能正常输出日志,格式是"logging.level.feign接口包路径=debug":
logging:
level:
com.morris.user.client.OrderClient: debug
会看到如下的打印日志:
2023-08-14 13:53:42.948 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] ---> GET http://order-service/order/findOrderByUserId?userId=1 HTTP/1.1
2023-08-14 13:53:42.948 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] ---> END HTTP (0-byte body)
2023-08-14 13:53:43.169 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] <--- HTTP/1.1 200 (213ms)
2023-08-14 13:53:43.170 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] connection: keep-alive
2023-08-14 13:53:43.170 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] content-type: application/json
2023-08-14 13:53:43.170 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] date: Mon, 14 Aug 2023 05:53:43 GMT
2023-08-14 13:53:43.170 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] keep-alive: timeout=60
2023-08-14 13:53:43.170 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] transfer-encoding: chunked
2023-08-14 13:53:43.171 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId]
2023-08-14 13:53:43.171 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] [{"id":1,"userId":1,"goodName":"Iphone 13","price":9999}]
2023-08-14 13:53:43.171 DEBUG 22948 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#findOrderByUserId] <--- END HTTP (57-byte body)
局部配置
局部配置可以让指定调用的微服务生效,在@FeignClient注解中指定使用的配置类
package com.morris.user.client;
import com.morris.user.config.FeignConfig;
import com.morris.user.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(value = "order-service", path = "/order", configuration = FeignConfig.class)
public interface OrderClient {
@GetMapping("findOrderByUserId")
List<Order> findOrderByUserId(@RequestParam("userId") Long userId);
}
注意FeignConfig类不要加@Configuration注解,否则就会被Spring扫描到,变成了一个全局的配置。
同样需要在配置文件中指定日志的级别才会打印:
logging:
level:
com.morris.user.client.OrderClient: debug
局部配置可以在yml中配置,对应属性配置类: org.springframework.cloud.openfeign.FeignClientProperties.FeignClientConfiguration
feign:
client:
config:
order-service: #对应微服务
loggerLevel: FULL
拦截器
每次Feign发起http调用之前,会去执行拦截器中的逻辑,拦截器可以修改请求的参数或者头部信息。
例如我们可以在拦截器中对请求头增加认证信息,增加链路追踪信息。
下面通过拦截器在请求头中增加一个参数实现分布式系统中请求的链路追踪,自定义拦截器需要实现RequestInterceptor接口:
package com.morris.user.config;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import java.util.UUID;
public class FeignTraceRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 业务逻辑
String traceId = UUID.randomUUID().toString();
template.header("TID", traceId);
}
}
全局配置
与日志的全局配置一样,放入到一个配置文件中。
package com.morris.user.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置@Configuration
@Configuration
public class FeignConfig {
@Bean
public FeignTraceRequestInterceptor feignTraceRequestInterceptor() {
return new FeignTraceRequestInterceptor();
}
}
局部配置
在@FeignClient注解中指定配置文件,注意FeignConfig类不要加@Configuration注解,否则就会被Spring扫描到,变成了一个全局的配置。
@FeignClient(value = "order-service", path = "/order", configuration = FeignConfig.class)
也可以在yml中配置:
feign:
client:
config:
order-service: #对应微服务
requestInterceptors[0]: #配置拦截器
com.morris.user.config.FeignTraceRequestInterceptor
order-service
端可以通过@RequestHeader获取请求参数,建议在Filter,Interceptor中统一处理。
超时时间配置
通过Options可以配置连接超时时间和读取超时时间,Options的第一个参数是连接的超时时间(ms),默认值是 2s;第二个是请求处理的超时时间(ms),默认值是5s。
全局配置
与日志、拦截器的全局配置一样,放入到一个配置文件中。
package com.morris.user.config;
import feign.Logger;
import feign.Request;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置@Configuration
@Configuration
public class FeignConfig {
@Bean
public Request.Options options() {
return new Request.Options(5000, 10000);
}
}
超时了会抛出SocketTimeoutException异常:
2023-08-15 09:45:53.595 ERROR 11104 --- [nio-8030-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : 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://order-service/order/findOrderByUserId] with root cause
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_281]
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[na:1.8.0_281]
局部配置
在@FeignClient注解中指定配置文件,注意FeignConfig类不要加@Configuration注解,否则就会被Spring扫描到,变成了一个全局的配置。
@FeignClient(value = "order-service", path = "/order", configuration = FeignConfig.class)
也可以在yml中配置:
feign:
client:
config:
order-service: #对应微服务
# 连接超时时间,默认2s
connectTimeout: 5000
# 请求处理超时时间,默认5s
readTimeout: 10000
Feign的底层用的是Ribbon,但超时时间以Feign配置为准。
客户端组件配置
Feign中默认使用JDK原生的URLConnection发送HTTP请求,我们可以集成别的组件来替换掉URLConnection,比如Apache HttpClient,OkHttp。
Feign发起调用真正执行逻辑:feign.Client#execute(扩展点)
配置Apache HttpClient
引入HttpClient依赖:
<!-- Apache HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>10.1.0</version>
</dependency>
然后修改yml配置,将Feign的Apache HttpClient启用:
feign:
#feign 使用 Apache HttpClient 可以忽略,默认开启
httpclient:
enabled: true
关于配置可参考源码:org.springframework.cloud.openfeign.FeignAutoConfiguration
测试:调用会进入feign.httpclient.ApacheHttpClient#execute
配置OkHttp
引入OkHttp的依赖:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
然后修改yml配置,将Feign的HttpClient禁用,启用OkHttp,配置如下:
feign:
#feign 使用 okhttp
httpclient:
enabled: false
okhttp:
enabled: true
关于配置可参考源码:org.springframework.cloud.openfeign.FeignAutoConfiguration
测试:调用会进入feign.okhttp.OkHttpClient#execute
GZIP压缩配置
开启压缩可以有效节约网络资源,提升接口性能,我们可以配置GZIP来压缩数据:
feign:
# 配置 GZIP 来压缩数据
compression:
request:
enabled: true
# 配置压缩的类型
mime-types: text/xml,application/xml,application/json
# 最小压缩值
min-request-size: 2048
response:
enabled: true
开启后在日志中会看到请求头中有gzip:
2023-08-15 14:38:38.482 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] ---> POST http://order-service/order/bigJson HTTP/1.1
2023-08-15 14:38:38.482 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] Accept-Encoding: gzip
2023-08-15 14:38:38.483 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] Accept-Encoding: deflate
2023-08-15 14:38:38.483 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] Content-Encoding: gzip
2023-08-15 14:38:38.483 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] Content-Encoding: deflate
2023-08-15 14:38:38.483 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] Content-Length: 289891
2023-08-15 14:38:38.483 DEBUG 23664 --- [nio-8030-exec-1] com.morris.user.client.OrderClient : [OrderClient#bigJson] Content-Type: application/json
注意:只有当Feign的Http组件不是okhttp3的时候,压缩才会生效,配置源码在FeignAcceptGzipEncodingAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@EnableConfigurationProperties({FeignClientEncodingProperties.class})
@ConditionalOnClass({Feign.class})
@ConditionalOnBean({Client.class})
@ConditionalOnProperty(
value = {"feign.compression.response.enabled"},
matchIfMissing = false
)
@ConditionalOnMissingBean(
type = {"okhttp3.OkHttpClient"}
)
@AutoConfigureAfter({FeignAutoConfiguration.class})
public class FeignAcceptGzipEncodingAutoConfiguration {
public FeignAcceptGzipEncodingAutoConfiguration() {
}
@Bean
public FeignAcceptGzipEncodingInterceptor feignAcceptGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
return new FeignAcceptGzipEncodingInterceptor(properties);
}
}
核心代码就是@ConditionalOnMissingBean(type=“okhttp3.OkHttpClient”),表示Spring BeanFactory中不包含指定的bean时条件匹配,也就是没有启用okhttp3时才会进行压缩配置。
编码器解码器配置
Feign中提供了自定义的编码解码器设置,同时也提供了多种编码器的实现,比如Gson、Jaxb、Jackson。我们可以用不同的编码解码器来处理数据的传输。如果你想传输XML格式的数据,可以自定义XML编码解码器来实现获取使用官方提供的Jaxb。
扩展点:Encoder & Decoder文章来源:https://www.toymoban.com/news/detail-662864.html
public interface Encoder {
void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException;
}
public interface Decoder {
Object decode(Response response, Type type) throws IOException, DecodeException, FeignException;
}
Java配置方式
配置编码解码器只需要在Feign的配置类中注册Decoder和Encoder这两个类即可:文章来源地址https://www.toymoban.com/news/detail-662864.html
@Bean
public Decoder decoder() {
return new JacksonDecoder();
}
@Bean
public Encoder encoder() {
return new JacksonEncoder();
}
yml配置方式
feign:
client:
config:
order-service: #对应微服务
# 配置编解码器
encoder: feign.jackson.JacksonEncoder
decoder: feign.jackson.JacksonDecoder
到了这里,关于【openfeign】OpenFeign的扩展、日志、超时时间、拦截器、客户端组件、压缩的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!