feign 调用常见问题避坑指南
原创
©著作权归作者所有:来自51CTO博客作者wx5925899fdb5f1的原创作品,请联系作者获取转载授权,否则将追究法律责任
feign 调用常见问题避坑指南!
前奏
很多时候,我们在使用微服务框架的时候,就基本上少不了与feign打交道。毕竟服务之间的调用,基本上都不会用手写http工具类去调了,这样显得有点麻烦了,feign更方便了。而且feign,还自带了负载均衡的策略(ribbon提供),如果我们的服务是集群的,feign还能负载调用。这些估计大家都懂吧?不会还有人不懂吧?那这个要深入学习了。在用feign的日常中,难免会遇到些问题,那下面,我来总结下,我司在项目开发中遇到的问题。虽说不是大问题,但至少是点经验分享,希望可以帮助到大家。当然有些问题可以通过升级到 openfeign 进行轻松解决。
400 Bad Request
在使用feign调用的使用出现400 Bad request的问题 , 这个 menuIds 数量比较多,导致400 错误。发现问题出在menuIds 跟在URL后面。
@PostMapping("/public/getMenusByIdsAndTypes")
List<SysMenuDto> getMenusByIdsAndTypes(@RequestParam("menuIds") String menuIds,
@RequestParam("menuType") String menuType);
解决办法
修改方法为
@PostMapping("/llsydn/getMenusByIdsAndTypes")
List<SysMenuDto> getMenusByIdsAndTypes(@RequestBody MultiValueMap<String,String> queryParam);
调用方法为
public List<SysMenuDto> getMenusByIdsAndNotType(String menuIds, String menuType){
MultiValueMap valueMap=new LinkedMultiValueMap();
valueMap.add("menuIds",menuIds);
valueMap.add("menuType",menuType);
return systemClient.getMenusByIdsAndTypes(valueMap);
}
非法字符串错误
是feign 调用的时候启用了**「压缩」** 导致的。
Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
解决办法
关闭压缩
feign.compression.request.enabled=false
feign.compression.response.enabled=false
或者使用okHttp
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
字符串中文乱码
在Feign调用时,传到目标服务的方法中,字符串里的中文变成问号了
解决办法
在Feign的接口的注解中指定consumes字符集: UTF-8
@PostMapping(value = "/portal/core/appdata/install",consumes = "application/json;charset=UTF-8")
void install(@RequestBody String data);
如果此时data为[{},{}]
格式的JSON字符串,即JSON数组字符串,又会报参数类型不匹配的错误,要把参数改为对象数组或者List对象:
@PostMapping(value = "/portal/core/appdata/install",consumes = "application/json;charset=UTF-8")
void install(@RequestBody Object[] data);
too many Body parameters
feign的post请求只能有一个body feign的post方法中,只能使用一个@RequestBody或者不带该注解,不能使用多个@RequestBody。
解决办法
只保留一个@RequestBody注解
Read time out
feign调用超时,会出现这个问题。一般来说当我们的业务需要处理的时间很大时,会出现这个问题。例如,上传excel文件。那这里我们可以进行feign的超时时间设置。这里只针对指定的feign client
解决办法
@FeignClient(name = "systemClient")
public interface SystemClient {
@RequestMapping(path = "/llsydn/importExcel", consumes = {"multipart/form-data"})
JsonResult importExcel(@RequestPart(name="file") MultipartFile file);
}
修改 systemClient 的默认超时时间
feign:
httpclient:
enabled: true
client:
config:
default:
#默认时间设置为10s
ConnectTimeOut: 10000
ReadTimeOut: 10000
#调用system微服务,默认时间设置为30s
systemClient:
ConnectTimeOut: 30000
ReadTimeOut: 30000