最近一直在搞每个月一次的抽奖活动,并发量也比平时多了很多,随之而来的,就是平时遇不到的一些问题。这也是可喜可贺的啊,有问题才能成长,没有问题就是在浪费生命。前端
其中一个感受比较奇葩的问题,就是:Tomcat在接收POST请求时,偶发性的POST参数接收不全,这个比例还很高。以下所示:java
45应用服务器正常POST参数获取:nginx
2016-05-19 15:45:15 INFO :request param : body=[{"appDevice":{"qdPlatform":"weixin","qdVersion":"1.4.1"},"activityId":80,"curPlanId":381,"memberId":"ff808081547ef0b401549f64e6cb2ecb","projectId":"31605061701144","prizeIds":[437,436,435,440,439,438],"planIds":[370,371,372,373,374,375,376,377,378,379,380,381,382]}]
复制代码
45应用服务器不正常POST参数获取:后端
2016-05-19 16:03:16 INFO :request param : 7D,"activityId":80,"curPlanId":381,"memberId":"ff80808150f0fdd401510f83cae413a9","projectId":"708","prizeIds":[437,436,435,440,439,438][370,371,372,373,374,375,376,377,378,379,380,381,382][370,371,372,373,374,375,376,377,378,379,380,381,382]=[]
复制代码
排查问题以前,先理清服务架构,如图:浏览器
排查问题开始以前,简单说下本身排查问题的几个原则(仅供参考):tomcat
问题重现:必定要先重现问题,任何重现不了的问题,都不是问题。同理,任何存在的问题,都必然能再次重现。bash
由近及远:先确认本身的代码无问题,而后再去确认外部代码无问题(如:框架代码,第三方代码等)。服务器
由外到内:程序就是一个IPO,有输入Input(如:参数、环境等)也有输出Out(如:结果、异常等),输出Out是问题的表象,先肯定外部因素Input无问题,再确认程序代码逻辑无问题。网络
由浅入深:其实就是由易到难、自上向下,先从上层应用排查问题,如:上层API、应用层、HTTP传输等,而后再确认底层应用排查问题,如:底层API、网络层、系统层、字节码、JVM等;架构
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> keySet = parameterMap.keySet();
StringBuilder sb = new StringBuilder();
for(String key : keySet) {
sb.append(key).append("=").append(Arrays.toString(parameterMap.get(key))).append(",");
}
log.info("request param : " + sb.toString()) ;
复制代码
经过上面的两条日志输出,和以上代码的分析,能够得出如下结论:
以上代码不存在并发问题及逻辑Bug,POST参数是从原始request.getParameterMap()中获取,获取先后未作任何写入、转换处理;
经过不正常日志输出和以上代码逻辑来看,从request.getParameterMap()中获取的参数,"body"这个Key已经丢失,且对于的Value也存在部分丢失,ParameterMap中的Key-Val混乱;
很快就排除了这种可能,由于参数不全是偶发性产生的,若是是因为参数长度限制致使请求参数截断,而应该是100%产生参数不全的问题。
能够确认,用户的请求从浏览器发出在到达Nginx以前,POST请求参数就已经丢失;
注意:想要了解更多tcpdump和Wireshark分析使用,请参考聊聊tcpdump与Wireshark抓包分析。
在上面排查问题的过程当中,就已经肯定了是用户前端传过来的参数问题,但从前端代码排查来看,其实也没有发现问题,只是在前端作了个JSON序列化。因此为了不问题再次发生,将前端序列化去掉,保持HTTP请求参数原始传输,由前端的代理服务再进行序列化后,提交给后端应用。
其实对于问题的解决并不重要,有时或许只是一个空格、一个微小的配置等,重要的是在于问题的分析过程、分析思路,怎么样有个清晰的思路,快速的定位问题,才是解决问题的关键。