• 2013-11-22

    战斗HTTP(下)

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/239188397.html

    当我在Moco的代码库里删除了关闭链接的代码时,我惊奇地发现Moco的一个测试失败了。怎么会失败呢?难道测试里面还有人需要强制关闭链接。

    带着种种疑问我又踏上了新一轮的代码跟踪之旅,这次的所有代码都在我自己的代码库里,一个简单的单元测试,无非是里面用到了Apache的HTTP Client。又是无数次的重试,我站到了一个InputStream的面前,这是在处理应答体时,要从HTTP应答流中读内容,然后,挂掉了。显然,当我强制关闭链接,读取就会返回,所以,测试可以通过。

    为什么会是这样?

    我不再简单粗暴地关闭链接,而是根据情况,如果客户端希望保持链接,我就保持,否则才会关闭。结果,测试依然是挂的。原因是这个测试请求保持链接,所以,服务器端不会关闭它的链接,所以,还会遇到相同的问题,它会挂住。

    到底什么样的行为才是正确的呢?我找到一本厚厚的《HTTP权威指南》,仔细读了一下保持链接的章节。我对HTTP如何处理链接有了一个相对完整的认识,但对于这个问题,我依然没有答案。

    其它测试也会有保持链接的需求,为什么就可以顺利通过,而只有这个测试会挂住。

    坐在电脑面前解决不了的问题,往往需要在路上解决。我突然意识到,通过者和不通过者似乎是有些许差别的,赶紧回到电脑前,打开日志,这个不通过的测试与其它测试最大的差别是,它只有应答头,没有应答体。不奇怪,因为这个测试就是测试能够返回正确的HTTP头。

    我似乎明白了,当客户端要求保持链接时,它还是需要从链接中读取数据的,但应该读取多少,谁能告诉它这个答案呢?如果没有额外的提示,似乎就只能挂住。答案就在Content-Length上,有了这个HTTP头,客户端就知道该读多少了。

    想通这一点,代码就好改了。在保持链接的情况下,如果没有Content-Length,就设置相应的Content-Length。

    果然测试一遍通过,又把之前同事的测试用例拿了过来,重新跑了一遍,一切正常。放到他们的工程里面测试,也是顺利通过。

    从发现一个不稳定的问题,到最终比较完整地修复了它,前前后后两个星期。如果没有我那个执着的同事,可能我也不会严肃地对待这个问题;没有仔细地解决这个问题,也不会对HTTP协议处理有个新的认识。非常感谢我这个执着的同事,他叫崔鹏飞,下一次Moco发布公告中,我可要着力感谢一下他。

    一个同事跑到我面前,我在使用Moco时发现一个问题,它有时会挂住。你用的是不是CXF,我问他。是啊!他回答。我笑了,因为我刚刚修好了这个问题。

    分享到:

    历史上的今天:

    引用地址: