一、背景
SpringCloud微服务框架中使用OpenFeign做服务间调用时(入参为@ResponseBody标注的JavaBean,请求类型为POST),被调用方正常执行,调用方报错,报错信息如下:
nested exception is feign.RetryableException: Incomplete output stream executing POST http://SERVICE-A/user/] with root cause
二、原因分析
从报错的截图可以看出feign采用jdk原生HttpURLConnection向下游服务发起http请求,这里报错的原因是:执行POST的输出流不完整,即在OutputStream写入流时出错。
三、解决方案
1、使用Apache HttpClient替换掉原生的HttpURLConnection。
在服务调用方pom.xml文件中添加如下依赖:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
不需要在application.yml中使用feign.httpclient.enabled=true
指定使用HttpClient。
因为在将LoadBalancerFeignClient
注入到Spring容器时,采用HttpClient方式的配置类HttpClientFeignLoadBalancedConfiguration
的条件装配信息如下:
对属性feign.httpclient.enabled
做评估时,如果未指定该属性,则默认为true,因此只需要可以找到feign.httpclient
包的ApacheHttpClient
类即会使用Apache的httpClient。
2、使用okClient替换掉原生的HttpURLConnection
在服务调用方pom.xml文件中添加如下依赖:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
另外需要在application.yml中使用feign.okhttp.enabled=true
指定使用OKHttpClient。
因为在将LoadBalancerFeignClient
注入到Spring容器时,采用OKHttpClient方式的配置类OkHttpFeignLoadBalancedConfiguration
的条件装配信息如下:
对属性feign.okhttp.enabled
做评估时,如果未指定该属性(默认为false) 或指定为 false则当前配置类不符合条件装配的规则,则不会使用OKHttpClient;另外还需要引入feign.okhttp
包的OkHttpClient
类。
四、其他
想了解更多OpenFeign的知识点,可以看博主的OpenFeign系列文章:
- SpringCloud之Feign实现声明式客户端负载均衡详细案例
- SpringCloud之OpenFeign实现服务间请求头数据传递(OpenFeign拦截器RequestInterceptor的使用)
- SpringCloud之OpenFeign的常用配置(超时、数据压缩、日志)
- SpringCloud之OpenFeign的核心组件(Encoder、Decoder、Contract)
- SpringBoot启动流程中开启OpenFeign的入口(ImportBeanDefinitionRegistrar详解)
- 源码剖析OpenFeign如何扫描所有的FeignClient
- 源码剖析OpenFeign如何为FeignClient生成动态代理类
- …等等等