今天在进行CGI外网部署的时候,出现一个很奇怪的问题。
先说明一下背景:
在webserver上的一个CGI-A会通过libcurl来访问另一个webserver上的CGI-B,并将调用的结果返回给前台。
问题的表现:
前台看到是CGI-A超时,抓包发现在调用CGI-B的时候,http请求正常返回,但是时延达到1s左右。
但是当在浏览器直接输入CGI-B的链接的时候,就在40ms之内即可返回。
具体抓包如下:
命令:
sudo tcpdump -s 0 -nX host [ip] -i eth1 -w data
libcurl调用CGI-B:
http://www.vimer.cn/wp-content/uploads/2010/09/data_err
浏览器直接访问CGI-B:
http://www.vimer.cn/wp-content/uploads/2010/09/data_suc
在wireshark中仔细的对比了请求包,发现只有两个地方不同:
libcurl调用CGI-B:
浏览器直接访问CGI-B:
但是当时怎么也没有想到居然真的就出在了gzip的问题上。
后来总监过来看了一眼,注意,就一眼!(果然姜还是老的辣啊),就说,是不是gzip的问题啊。然后杯具的想起来CGI-B所在的webserver是默认打开gzip压缩的。
于是关掉gzip压缩,测试,果然OK了!
果然,是libcurl默认是不认识gzip压缩的!而这也解释了为什么在浏览器中直接输入CGI-B的url可以正常访问了~
为了根查,特意看了一下libcurl的文档,发现果然如果要libcurl支持gzip压缩是需要设置的:
curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip"); // Accept-Encoding
说明如下:
CURLOPT_ENCODING
Sets the contents of the Accept-Encoding: header sent in an HTTP request, and enables decoding of a response when a Content-Encoding: header is received. Three encodings are supported: identity, which does nothing, deflate which requests the server to compress its response using the zlib algorithm, and gzip which requests the gzip algorithm. If a zero-length string is set, then an Accept-Encoding: header containing all supported encodings is sent.
This is a request, not an order; the server may or may not do it. This option must be set (to any non-NULL value) or else any unsolicited encoding done by the server is ignored. See the special file lib/README.encoding for details.
参考链接:
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTENCODING
http://blog.chinaunix.net/u2/61797/showart_520044.html
杯具啊,查了一下午,搞到最后我都要去直接strace webserver的接入进程了……,结果却是这么简单的原因。。。
故事大王 on #
原来折腾了一下午,竟然是GZIP的问题。
libcurl默认不打开GZIP压缩支持,难道是为了加快处理?
另外,Q总监果然强大啊~~~~~
Reply
BruceLi on #
类似的故事http://sysio4me.appspot.com/?p=11001
Reply
Dante on #
哈哈,每一个诡异的错误背后都藏着一个简单的原因,说的有道理啊~~
Reply
妞妞 on #
哈哈哈姜的还是老的辣
Reply
peter on #
囧抓的包。。。
Reply
Dante on #
呃?啥意思?
Reply
手机短信 on #
谢谢楼主的文章~我的问题解决了
Reply
One on #
有指导意义
Reply