在生产环境使用feign调用外部接口时,偶尔会出现下面错误
12020-10-15 11:00:18,535 [] ERROR com.shein.abc.rmp.controller.RecExplainConfigController - rec_explain_query.fail 2f 3feign.codec.DecodeException: Error while extracting response for type [class com.alibaba.fastjson.JSONObject] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected end-of-input in field name; nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input in field name 4 5 at [Source: (PushbackInputStream); line: 1, column: 108927] 6 7 at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:169) 8 9 at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:133) 10 11 at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) 12 13Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class com.alibaba.fastjson.JSONObject] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected end-of-input in field name; nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input in field name 14 15 at [Source: (PushbackInputStream); line: 1, column: 108927] 16 17 at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:115) 18 19 at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:60) 20 21 at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:45) 22 23 at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:165) 24 25 ... 112 common frames omitted 26C 27Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected end-of-input in field name; nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input in field name 28 29 at [Source: (PushbackInputStream); line: 1, column: 108927] 30 31 at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:243) 32 33 at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:225) 34 35 at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:100) 36 37 ... 115 common frames omitted 38C 39Caused by: com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input in field name 40 41 at [Source: (PushbackInputStream); line: 1, column: 108927] 42 43 at com.fasterxml.jackson.core.base.ParserMinimalBase._reportInvalidEOF(ParserMinimalBase.java:618) 44 45 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.parseEscapedName(UTF8StreamJsonParser.java:1962) 46 47 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.slowParseName(UTF8StreamJsonParser.java:1867) 48 49 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._parseName(UTF8StreamJsonParser.java:1651) 50 51 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextFieldName(UTF8StreamJsonParser.java:1005) 52 53 at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.mapObject(UntypedObjectDeserializer.java:896) 54 55 at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserialize(UntypedObjectDeserializer.java:654) 56 ... 117 common frames omitted
这个很明显是json反序列化失败,根据提示json字符串不全,根据上面的报错,分别预估了几个可能原因,并针对性的排查。 1、feign中是否有拦截器,截取了响应结果 排查结果:无
2、是否服务端响应的结果就不全 经过排查,服务端响应结果没问题,并支持gzip压缩
3、打印feign的debug日志,并查询出header中的content-length是否与响应结果不一致,这里不了解content-length的可以参考下面链接: Content-Length是如何工作的 HTTP 协议中的 Transfer-Encoding 这两篇文章中有详细的描述,当实际响应结果比content-length大时会被截取
既然服务端支持gzip压缩,且请求结果返回值比较大,这时我们是否考虑feign开启gzip压缩
1feign: 2 compression: 3 request: 4 # 开启请求压缩 5 enabled: true 6 # 配置压缩的 MIME TYPE 7 mime-types: text/xml,application/xml,application/json 8 # 配置压缩数据大小的下限 9 min-request-size: 2048 10 response: 11 # 开启响应压缩 12 enabled: true
开启压缩后重新请求,报下面的错误
1feign.codec.DecodeException: Error while extracting response for type [class com.alibaba.fastjson.JSONObject] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; 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 2 at [Source: (PushbackInputStream); line: 1, column: 2] 3 at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:169) 4 at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:133) 5Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class com.alibaba.fastjson.JSONObject] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; 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 6 at [Source: (PushbackInputStream); line: 1, column: 2] 7 at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:115) 8 at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:60) 9 at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:45) 10 at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:165) 11 ... 114 common frames omitted 12Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; 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 13 at [Source: (PushbackInputStream); line: 1, column: 2] 14 at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:243) 15 at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:225) 16 at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:100) 17 ... 117 common frames omitted 18Caused by: com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens 19 at [Source: (PushbackInputStream); line: 1, column: 2] 20 at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804) 21 at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:693) 22 at com.fasterxml.jackson.core.base.ParserMinimalBase._throwInvalidSpace(ParserMinimalBase.java:644) 23 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._skipWSOrEnd(UTF8StreamJsonParser.java:2951) 24 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:691) 25 at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4142) 26 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001) 27 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3085) 28 at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:237) 29 ... 119 common frames omitted
这个报错比较明显了,反序列化解析出问题,经过排查发现是HttpURLConnection不支持gzip反序列化,SpringCloud需要升级到Hoxton才能解决该问题:
https://github.com/spring-cloud/spring-cloud-openfeign/pull/230
还有一种方案是将httpclient换成okhttp,如下配置变更:
1feign: 2 okhttp: 3 enabled: true 4 httpclient: 5 enabled: false
pom中增加相关依赖
1 <!-- okhttp --> 2 <dependency> 3 <groupid>io.github.openfeign</groupid> 4 <artifactid>feign-okhttp</artifactid> 5 </dependency>
配置后重新启动,不再报错。
参考链接:
https://www.jianshu.com/p/df37eb5f2169
https://blog.csdn.net/wo18237095579/article/details/83344529
https://imququ.com/post/transfer-encoding-header-in-http.html
https://blog.piaoruiqing.com/2019/09/08/do-you-know-content-length/</generated></generated></generated></generated></generated></generated></generated></generated>