分享

(解决curl_easy_perform阻塞很久的问题)libcurl的share interface与curl_easy_perform的性能

 dwlinux_gs 2016-01-07

最近在使用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
  1. void set_share_handle(CURL* curl_handle)  
  2. {  
  3.     static CURLSH* share_handle = NULL;  
  4.     if (!share_handle)  
  5.     {  
  6.         share_handle = curl_share_init();  
  7.         curl_share_setopt(share_handle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);  
  8.     }  
  9.     curl_easy_setopt(curl_handle, CURLOPT_SHARE, share_handle);  
  10.     curl_easy_setopt(curl_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5);  
  11. }  

 将上面的这段代码放进curl的设置当中,当没有连接外网的时候调用curl_easy_perform就不会阻塞太久,不超过一秒,如果没有加的话,会阻塞20-50s的时间,很操蛋!总之加上上面的就好了!

注意,默认的DNS cache的超时时间为60秒,如果想把超时设得大一些,可以使用CURLOPT_DNS_CACHE_TIMEOUT选项来设置,如上将超时时间设为5分钟。

 

用share interface的话,我们在程序中可以灵活配置具体哪些http连接使用哪些DNS cache。在超时时间内,每次curl_easy_perform执行时不会再启动解析DNS的线程了,效率大大提高。

 

实践证明,不是libcurl的性能不好,而是我沒有用好它。:)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多