读书人

mod_jk2引起Apache+Tomcat重复提交有关

发布时间: 2012-09-01 09:33:02 作者: rapoo

mod_jk2引起Apache+Tomcat重复提交问题

以前项目中遇到的一个很诡异的问题,记录下来分享一下。

?

一个很老的项目的生产环境是采用Apache httpd + Tomcat?,使用mod_jk2的插件进行整合,其实这个插件早已停止更新了,反而是mod_jk(1.x)插件的生命周期还在维持。

?

具体问题的现象是,项目中有一些耗时较多的处理页面,例如一个创建新项目的业务画面,前台页面submit之后,后台要处理一系列的文件,还要登录数据库等,其实在设计阶段已经考虑到了重复提交的问题,所以画面上做了控制(提交之后画面按钮禁用,直到后台操作完成)。开发测试阶段没有出现过问题,然而到了客户的生产环境,在运行了一段时间之后,出现了几次数据重复提交的问题,客户提交给我们解决。

?

搭设测试环境后,尝试后发现提交按钮按下后,如果关闭浏览器或者通过地址栏输入其他URL并跳转后就会发生服务器端重复提交。经过反复的调查,首先确定了浏览器端没有任何问题,提交的请求只有一次;但是Tomcat中部署的服务程序确实在个别情况下接收到两次请求,与程序代码也没有关系;最后把注意力集中到了Apache的httpd上面。

?

先是怀疑httpd存在问题,但是google之后没有发现有类似的反馈,考虑到如果真的有问题应该会有很多用户发现的,所以最后怀疑到了mod_jk2上面,更换成了mod_jk(1.x)插件之后就没有问题了。

?

照理说事情到此就可以解决了,但是不幸的是项目的客户非常较真,认为更换mod_jk插件的话整个系统就需要重新测试才能上线,所以不同意,要求调查清楚原先为什么有问题,被逼无奈只好去查mod_jk2的源代码。

mod_jk2的代码可以从这里下载:http://archive.apache.org/dist/tomcat/tomcat-connectors/jk2/source/jakarta-tomcat-connectors-jk2-2.0.4-src.zip

?

因为对C不是很熟悉,所以从httpd的log入手,在出现重复提交问题的时候,log中能查到一条对应的记录:“ajp13.service() ajpGetReply recoverable error 3”,在代码中搜索可以找到是jk_worker_ajp13.c的line547输出的,分析其所在的函数jk2_worker_ajp13_forwardStream之后,发现问题的大致原理是:服务端处理完请求之后,发回响应消息,但是因为浏览器端已经被关闭或者迁移到其他页面,所以试图发回响应时会得到失败的消息,但是mod_jk2插件会试图恢复这一错误(但是这种情况显然无法恢复了),试图恢复的方式是再次向Tomcat发送一开始的请求,这就构成了第二次提交,而在浏览器和Tomcat服务器来看确实是没有任何问题的。(这个仅仅是个人的理解,因为对这方面不是很了解,所以可能理解的不对,不过对于解决问题影响不大)

?

出问题的函数代码片段如下,可以看到一开始定义了JK_RETRIES变量值为2,如果把这个值改为1就不会出现上面的问题了,但是显然客户是不会接受这一方案的,于是继续调查其他解决方法。

?

[workerEnv]logger=logger.apache2sslEnable=1timing=1forwardURICompatUnparsednoRecoveryIfRequestSentnoRecoveryIfHeaderSentdisabled=0debug=5 [logger.apache2]level=DEBUG [shm]file=${serverRoot}/logs/shm.filesize=1048576disabled=0debug=5 [channel.socket:192.168.13.4:8009]tomcatId=server2keepalive=0timeout=0disabled=0debug=5#---LB---lb_factor=1……

?

?

?注意:只需要写上noRecoveryIfHeaderSent就可以了,如果不写这个属性,那么就是默认值。

?

以上的都经过了测试,如果有哪位朋友遇到类似的问题,请随意参考~

读书人网 >Apache

热点推荐