1、 feign不指定url调用不通,
新知识:原来url:http://172.29.126.162:1010/hc-system/platform/organization/person/10001
使用微服务调用:http://hc-system/platform/organization/person/10001,去掉ip和端口也能调用通。
(ribbon负载均衡)feign指定ip和端口时,会把ip和端口拼在url前,不指定的话会把服务名拼接在url前。
背景:开始写松兰山项目时,使用feign调用hc那边服务的接口,因为不指定url(ip和端口)时调用不通,所以指定了url,这时是能够调通的。
①最开始指定ip、端口时,
这时候因为指定了url,所以不会把服务名拼接在url前,只会把ip、端口拼在url前,打开feign日志查看url。
完整url: http://172.29.126.162:1010/hc-system/platform/organization/person/10001 能够调通。
②后面去掉了url,直接部署,发现报错,
完整url变成: http://hc-system/hc-system/platform/organization/person/10001。
这时我才怀疑不指定url时会自动把服务名拼接在url前,然后发起请求。
③后面因为正式环境要开始上了,所以必须把url去掉,这时候去掉了url无法调用,后来才知道貌似feign会不指定ip时,会自动把服务名拼接在url前面(还不知道为什么),因此导致错误。
不指定url时:
这时就能请求成功!!!!!
ps:还有个小问题,我之前的项目,不指定ip和端口,但是还是在url前加上了服务名,不知道为什么还是能请求成功,还需要进一步思考。
2、 背景:feign调用不通,报错,困了我快一个月!!!可恶,中间花了两天解决,把百度都试了一遍,都没有用,都快哭了,现在说下解决过程。
开始我打开了日志进行进一步查看报错信息,需要在feign使用配置文件中加入日志级别,日志级别是FULL,并在配置文件中也加入日志级别。
3、然后发现报错404 not found,开始以为是参数不够,被调用为三个参数,调用时传两个参数,加上了之后还是报错,然后发现是注解用错了,之前用的是@PathVariable(复制过来没有改),使用@RequestParam后错误改变(低级错误)。
4、报错: nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (ByteArrayInputStream); line: 1, column: 2]。
5、然后feign调用接口,使用String接收,把字符串打印出来, 发现乱码了???
还发现传回来是二进制数据??
然后开始了疯狂的百度中,中间试了无数次,各种加什么配置,去掉压缩之类的都不行,还有加过滤器什么的也不行。
最后终于在一个大哥的文章中发现了答案,他和我一样是打印出来发现乱码,这个问题就是gzip接收到的还是压缩数据,所以乱码,还是试了一下他说没用的配置,结果对我有用!!!!!(他下面真正对她有用的方法对我没用,也是加拦截器)
答案:在配置文件中加入feign.compression.response.useGzipDecoder为true即可。
6、乱码的事情没了,发现只有中文乱码了,靠!!!!!!又整了我好久好久,百度的所有方案都试过了,还看了feign日志所有参数,好像也没问题的,人都快哭了,终于找到了解决方案。
@Configuration
public class FeignConfig implements RequestInterceptor {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
public Decoder feignDecoder() {
return new ResponseEntityDecoder(new SpringDecoder( () -> {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter() {
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
Object result=null;
if ("java.lang.String".equals(type.getTypeName())) {
result= StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("utf8"));
} else {
result=super.read(type, contextClass, inputMessage);
}
return result;
}
};
return new HttpMessageConverters(fastConverter);
}));
}
@Override
public void apply(RequestTemplate requestTemplate) {
try {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
if (null != servletRequestAttributes) {
HttpServletRequest request = servletRequestAttributes.getRequest();
// 获取所有头文件信息的key
Enumeration<String> headerNames = request.getHeaderNames();
if (null != headerNames) {
while (headerNames.hasMoreElements()) {
// 获取头文件的key和value
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
// 跳过content-length,不然可能会报too many bites written问题
if ("content-length".equalsIgnoreCase(headerName)) {
continue;
}
// 将令牌数据添加到头文件中,当用feign调用的时候,会传递给下一个微服务
requestTemplate.header(headerName, headerValue);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
参考:Feign乱码 - 知乎
答案:加了个解码器,转成utf8就可以了。
7、本来前面的feign调用都能够在线上正常运行了,突然很多feign调用报错,还都是同一个错。
feign.codec.DecodeException: Error while extracting response for type [com.entity.Result<com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.emergency.pojo.HcUser>>] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: syntax error, expect {, actual [, pos 685, fieldName roles, fastjson-version 1.2.83; nested exception is com.alibaba.fastjson.JSONException: syntax error, expect {, actual [, pos 685, fieldName roles, fastjson-version 1.2.83
说是转换问题,主要我feign调好之后就没动过代码了,咋突然坏了??
然后我进行了大量百度,试了很多也改不好,我以为是nacos配置的修改了的问题或者又要重写解码器,实际情况就是一个服务是的接口是好的,另一个服务的几个接口是报错的。后面让一个同事看了一下,原来是被调用方把数据结构给改了,靠,导致转换错误,是中间一个字段从对象改成了对象的数组,导致json转换错误。
答案:还是先好好看看错误,不用一开始就把问题想的太复杂,先看看被调用方有没有修改。