Spring Cloud 疑难杂症(4): Feign 访问缓慢及调用出错
使用Feign调用其他微服务的方法时,有时会出现缓慢的情况。经过排查发现并不是被调用方法自身缓慢造成的,极有可能是在fegin连接其他微服务这一个过程花费较长时间。
可以进行如下优化
使用OkHttp3
替换掉原生HttpClient
引入新依赖
1 2 3 4
| <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency>
|
配置文
1 2 3 4 5 6 7 8 9 10 11 12
| feign: httpclient: enabled: false okhttp: enabled: true hystrix: enabled: true client: config: default: connectTimeout: 10000 readTimeout: 10000
|
注意 目前没有证据证明访问速度因为这个配置变快(2020-04-03)
Okhttp 参数配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @AutoConfigureBefore(FeignAutoConfiguration.class) @Configuration @ConditionalOnClass(Feign.class) public class FeginOkHttpConfig { private int feiginOkHttpReadTimeout = 60; private int feignConnectTimeout = 60; private int feignWriteTimeout = 120;
@Bean public okhttp3.OkHttpClient okHttpClient() { return new okhttp3.OkHttpClient.Builder() .readTimeout(feiginOkHttpReadTimeout, TimeUnit.SECONDS) .connectTimeout(feignConnectTimeout, TimeUnit.SECONDS) .writeTimeout(feignWriteTimeout, TimeUnit.SECONDS) .connectionPool(new ConnectionPool(10, 5L, TimeUnit.MINUTES)) .build(); } }
|
Feign提前加载
feign是在使用时才进行加载,所以第一次访问时会有连接上的耗时,改成在程序启动时就进行加载可以加快连接速度
1 2 3 4 5 6 7 8 9 10
| ribbon: eureka: enabled: true ReadTimeout: 10000 ConnectTimeout: 10000 eager-load: enabled: true clients: deco-common-service
|
用户请求 content-length 覆盖到 微服务调用方法
Invalid character found in method name. HTTP method names must be tokens
遇到这里保存解决方法是情况外部请求头部中的 “content-type”, “content-length” 两个字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Slf4j public class FeignConfiguration implements RequestInterceptor { @Value("${rendering.token}") private String token; private static final String X_CLIENT_TOKEN_USER = "x-service-token";
@Override public void apply(RequestTemplate template) { List<String> headNameList = Arrays.asList("content-type", "content-length"); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder .getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); Enumeration<String> headerNames = request.getHeaderNames(); template.header(X_CLIENT_TOKEN_USER, token); if (headerNames != null) { while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String values = request.getHeader(name); if (!headNameList.contains(name)) { template.header(name, values); } } log.debug("feign interceptor header:{}",template); } } @Bean public feign.Logger.Level feignLoggerLevel(){ return feign.Logger.Level.FULL; } }
|
上一篇 « Spring Cloud 疑难杂症(3): docker swarm 环境下获取用户正确 IP
下一篇 » Spring Cloud 疑难杂症(5): docker swarm 环境下优雅更新服务