(解决curl_easy_perform阻塞很久的问题)libcurl的share interface与curl_easy_perform的性能
不是libcurl的性能不好,而是我沒有用好它
最近在使用libcurl实现客户端程序和http server通讯功能的时候,发现libcurl的性能不好。 具体情况是我在每次http连接时初始化一个新的curl handle,参数设置完成后,调用curl_easy_perform方法执行本连接。 如果程序中需要用到http连接比较少,感觉不到异常。但在测试中发现,程序需要大量http连接的时候,curl_easy_perform的性能很差。
调查发现,在curl_easy_perform方法每次执行时,libcurl都会启动一个线程,执行结束后结束这个线程。经研究libcurl的源代码发现,libcurl在curl_easy_perform方法中启动的线程用于做DNS解析, libcurl对于每一个curl hanlle有一个DNS cache,默认超时时间为60秒,如果不重用curl handle的话,这个dns cache在连接完成后就被析构了。我的程序没有重用curl handle,所以每个连接都会去启动线程做DNS解析。
问题来了,在不重用curl handle的情况下,怎么保证DNS cache一直有效,各个不同的curl handle能共用这个DNS cache呢?答案是有的,有个CURLOPT_DNS_USE_GLOBAL_CACHE设置,可以让libcurl所有http连接都使用一个全局的DNS cache。但是在查阅libcurl文档的时候,看到下面一段话:
15.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE Remove support for a global DNS cache. Anything global is silly, and we already offer the share interface for the same functionality but done "right".
也就是CURLOPT_DNS_USE_GLOBAL_CACHE将会在以后版本被去除掉,原因是设置CURLOPT_DNS_USE_GLOBAL_CACHE后虽然能够使用全局DNS cache,但任何全局的东西都是愚蠢的,而且libcurl已经提供了share interface可以用恰当的方式做同样的事。
在使用share interface的curl_share_init初始化share handle以后,使用curl_share_setopt设置共享对象,目前可以支持cookie和dns,在每一个curl handle执行前,使用CURLOPT_SHARE选项把这个share handle设置给curl handle,这样多个curl handle就可以共用同一个DNS cache了,代码如下:
[c-sharp:nogutter:firstline[1]] view plaincopy
将上面的这段代码放进curl的设置当中,当没有连接外网的时候调用curl_easy_perform就不会阻塞太久,不超过一秒,如果没有加的话,会阻塞20-50s的时间,很操蛋!总之加上上面的就好了! 注意,默认的DNS cache的超时时间为60秒,如果想把超时设得大一些,可以使用CURLOPT_DNS_CACHE_TIMEOUT选项来设置,如上将超时时间设为5分钟。
用share interface的话,我们在程序中可以灵活配置具体哪些http连接使用哪些DNS cache。在超时时间内,每次curl_easy_perform执行时不会再启动解析DNS的线程了,效率大大提高。
实践证明,不是libcurl的性能不好,而是我沒有用好它。:) |
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)