第一个要分享的bug,是Java语言通过HTTP客户端RestTemplate调用弱语言PHP封装的HTTP接口引起的,对方将配置数据,处理成JSON提供给偶,其数据结构如下:
[{
“operateWord”:”测试1″,
“title”:”测试1″,
“url”:””
},{
“operateWord”:”测试2″,
“title”:”测试2″,
“url”:””
}]
Java这边通过对象的列表来接收java.util.List<Banner>
@Setter
@Getter
publicclassBanner{
privateStringoperateWord;
privateStringtitle;
privateStringurl;
}
自测验证,测试通过后上线,偶尔会出现可用率降低的情况,其异常日志的主要信息如下
java.lang.ClassCastException:com.alibaba.fastjson.JSONObjectcannotbecasttocom.alibaba.fastjson.JSONArray
后来此问题延续了一段时间,通过偶这边的出入参日志,和对方的接口日志,来配合复现,当该JSON中只有一个元素时,数据结构会由对象数组退化为对象,即当该返回值只有一个元素时,其返回结果如下:
{
“operateWord”:”测试2″,
“title”:”测试2″,
“url”:””
}
而Java这边是强一致语言,仍通过对象的数组去接收,如何能成功接收呢?随后,PHP侧的接口同事将其提供的返回值数据结构进行格式化,确保任何时候都返回对象的数组的JSON数据结构,Java这边就可以正常解析了。大家需要关注的是:弱语言的返回值,可能因元素个数的不同而转化其数据结构,从而在与Java的交互中出问题。
第二个要分享的bug是,RestTemplate使用过程中的不规范编码问题,对其通过Bean机制创建共享服务理解不透导致。通过RestTemplate获取配置信息,测试上线,7天时间内,无任何问题,时间一长,可用率陆陆续续下降,重启docker服务,该接口的可用率恢复,出现的异常信息如下
org.springframework.web.client.RestTemplate-GETrequestfor”http://xxx”resultedin400(BadRequest);invokingerrorhandler
Exceptioninthread”main”org.springframework.web.client.HttpClientErrorException:400BadRequest
atorg.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:88)
atorg.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:532)
由于400这个状态码,第一感觉就是对方接口有变更,从而引起偶的业务可用率下降。经对方同事排期,其7天内无任何变更,和偶这边的应用部署时间一致。近一个月的时间内,只能通过重启保障线上业务的正常可用。而偶这边在预发环境对该接口进行了多次压测,发现该400的状态可以复现。复现后,发现RestTemplate的请求头信息过大,已超过4k。再和代码对照起来看,将RestTemplate初始化Bean之后,在service代码中,不断的设置头信息,即
publicclassWxMappingJackson2HttpMessageConverterextendsMappingJackson2HttpMessageConverter{
privateObjectMapperobjectMapper=newObjectMapper();
publicWxMappingJackson2HttpMessageConverter(){
List<MediaType>mediaTypes=newArrayList<MediaType>();
mediaTypes.add(newMediaType(“text”,”html”,Charset.forName(“UTF-8”)));
mediaTypes.add(newMediaType(“text”,”plain”,Charset.forName(“UTF-8”)));//加入text/html类型的支持
setSupportedMediaTypes(mediaTypes);//tag6
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true);
setObjectMapper(objectMapper);
}
}
privatefinalstaticWxMappingJackson2HttpMessageConverterhttpMessageConverter=newWxMappingJackson2HttpMessageConverter();
restTemplate.getMessageConverters().add(httpMessageConverter);
该请求头过大,而ngix默认的请求头信息限制4k,当超时4k时,拒绝提供服务,从而导致400的状态码。
这两个bug,都是线上正常运行一段时间后,才出现的,这种往往更恼火,在测试阶段很隐蔽,线上出现之后,也不是很容易排查。编写代码时,还是需要用心去写,尽量避免这些bug呢。
作者:夕阳雨晴,偶的:偶尔美文,主流Java,为你讲述不一样的码农生活。
如果觉得《作为程序员 你有过一个简单bug查询了很久才解决的经历吗? – 网络》对你有帮助,请点赞、收藏,并留下你的观点哦!