Я хотел бы реализовать систему уведомлений HTTP, используя libcurl . В основном у меня есть пул рабочих потоков и очередь уведомлений. Когда уведомление помещается в очередь, свободный сотрудник в пуле берет его и отправляет его получателю (хост, 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 хранит кеш из 5 соединений на обработчик ). Это может быть серьезной проблемой, когда нагрузка на систему (то есть опубликованные уведомления в очереди) высока, так как мы можем закончить слишком большим количеством параллельных соединений, открытых к одному и тому же месту назначения, вместо того, чтобы повторно их использовать.
В худшем случае давайте представим, что все уведомления имеют одно и то же назначение (не говоря уже example.com:9999
), например, для пула из 400 рабочих. В сценарии с высокой нагрузкой (все работники, отправляющие уведомления параллельно), мы можем одновременно получить 400 x 5 = 2000 подключений к example.com:9000
!
Моей первой идеей для решения этой проблемы было сделать объект curlHandler
глобальным. Таким образом, мы могли бы использовать один и тот же пул соединений libcurl для всех работников. Однако я предполагаю, что это не сработает из-за многопоточности (то есть два потока сталкиваются при curl_easy_setopt(curlHandler , CURLOPT_URL, <notification URL>)
), если я не реализую механизм защиты на основе мьютекса / семафора.
Работа с mutext / sempahores в собственном коде всегда трудна, поэтому мне интересно, будет ли проще какое-то другое решение (возможно, реализованное на уровне libcurl itslef). Я посмотрел документацию по licurl, которая довольно хороша для справки отдельных функций и структуры данных, но я не нашел конкретного описания для подобного случая (может быть, простой интерфейс curl не может быть использован в этом случае?)
Известно, как другие люди сталкиваются с такой же проблемой и какие решения могут быть применены, было бы здорово.
Спасибо!