在多线程情况下重用libcurl连接的正确方法

时间:2019-03-19 13:07:14

标签: c libcurl

我想使用libcurl实现HTTP通知系统。基本上,我有一个线程工作者池和一个通知队列。将通知放入队列后,池中的空闲工作程序将其接收并将其发送给接收方(主机,ip和URL路径是通知的参数)。

我的第一个实现基于curl easy interface。因此,基本上每个工作人员都运行以下代码(简化版):

static void* workerFunc(...) {
  CURL* curlHandler = curl_easy_init();
  for (;;) {
     // Takes a notification from the queue
     // Use curlHandler to send it, e.g:
     //
     // curl_easy_setopt(curlHandler , CURLOPT_URL, <notification URL>);
     // curl_easy_setopt(curlHandler , CURLOPT_POSTFIELDS, <notification payload>);
     // etc.
     //
     // CURLcode res = curl_easy_perform(curlHandler);
  }  
}

到目前为止,一切都很好。该代码有效。

但是,它有一个问题:curlHandler对象是每个工作线程本地的,因此我们不利用libcurl在后台(默认为libcurl keeps a cache of 5 connections per handler)进行的连接重用。当系统的负载(即队列中已发布的通知)很高时,这可能是一个严重的问题,因为我们可能会以打开过多的并行连接来结束向同一目的地的访问,而不是重新使用它们。

在最坏的情况下,让我们想象一下,例如对于400个工作人员池,所有通知都具有相同的目的地(不用说example.com:9999)。在高负载情况下(所有工作人员并行发送通知),我们最终可以同时与example.com:9000建立400 x 5 = 2000个连接!

我解决这个问题的第一个想法是使curlHandler对象成为全局对象。这样,我们可以为所有工作人员利用相同的libcurl连接池。但是,除非我实现基于互斥/信号量的保护机制,否则我想由于多线程(即两个线程在curl_easy_setopt(curlHandler , CURLOPT_URL, <notification URL>)上发生冲突)将无法正常工作。

在自己的代码中处理mutext / sempahores总是很困难,所以我想知道是否有其他解决方案(可能在libcurl级别itslef上实现)更容易。我查看了licurl文档,该文档非常适合作为单个函数的参考,并且数据结构,但我还没有找到针对这种情况的具体说明(也许在这种情况下无法使用curl easy接口?)

请了解其他面临相同问题的人的经验以及可以采用的解决方案。

谢谢!

0 个答案:

没有答案