Solicitud paralela de http de LibCurl en un entorno multinúcleo.
Actualmente, estoy creando un conjunto de manejadores fáciles de curl para hacer solicitudes HTTP paralelas. Pero esto es bloqueante.
Aquí está mi implementación:
class CurlHttpClient
{
public:
…
private:
CURL* m_curl = nullptr;
std::mutex m_mtx;
std::stack<curl> m_poolCurlHandle;
CURL getCurlHandleFromPool();
void pushCurlHandle(CURL* curlHandle);
};
CURL* CurlHttpClient::getCurlHandleFromPool()
{
CURL* pCurlHandle = nullptr;
std::scoped_lock lock(m_mtx);
{
if (!m_poolCurlHandle.empty())
{
pCurlHandle = m_poolCurlHandle.top();
m_poolCurlHandle.pop();
}
return pCurlHandle;
}
return curl_easy_duphandle(m_curl);
}
void CurlHttpClient::pushCurlHandle(CURL* curlHandle)
{
std::scoped_lock lock(m_mtx);
m_poolCurlHandle.push(curlHandle);
}
int CurlHttpClient::request(const std::string& requestUrl, std::string& responseBuffer)
{
CURL* curlHandle = getCurlHandleFromPool();
curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, (void*)&responseBuffer);
curl_easy_setopt(curlHandle, CURLOPT_URL, requestUrl.c_str());
CURLcode res = curl_easy_perform(curlHandle);
int httpResponseCode = 0;
curl_easy_getinfo(curlHandle, CURLINFO_RESPONSE_CODE, &httpResponseCode);
pushCurlHandle(curlHandle);
return httpResponseCode;
}
// Ejemplo de cliente
int main()
{
CurlHttpClient client;
…
std::thread t1([&] { std::string response; std::string url; client.request(url, response); //do something with response});
std::thread t2([&] { std::string response; std::string url; client.request(url, response); //do something with response});
std::thread t3([&] { std::string response; std::string url; client.request(url, response); //do something with response});
std::thread t4([&] { std::string response; std::string url; client.request(url, response); //do something with response});
t1.join();
t2.join();
t3.join();
t4.join();
}
Aquí puedes ver que estoy devolviendo las respuestas individualmente para cada solicitud tan pronto como se reciben.
Leí que curl multi-interface es mejor para manejar solicitudes paralelas. He visto algunos ejemplos de configuración de multi-interface y todos los ejemplos están acumulando la solicitud y disparando la multi perform. Pero no estoy seguro de cómo devolver los datos inmediatamente al cliente cuando se recibe una respuesta individual y seguir esperando que llegue otra respuesta.
¿Es útil multi-interface en mi escenario particular? Si es así, ¿cómo puedo devolver una respuesta individual inmediatamente cuando se recibe?</curl*>
davy.ai
Sí, el multi-interfaz puede ser útil en su escenario, ya que permite enviar múltiples solicitudes HTTP en paralelo sin bloquear.
Para devolver respuestas individuales inmediatamente cuando se reciben, puede usar una combinación de
curl_multi_add_handle
,curl_multi_fdset
,curl_multi_wait
ycurl_multi_perform
.En primer lugar, debe crear un multi-handle y agregar todos los easy-handles al multi-handle usando
curl_multi_add_handle
. Luego, puede utilizarcurl_multi_fdset
ycurl_multi_wait
para esperar actividad en cualquiera de los descriptores de archivo asociados con el multi-handle. Una vez que hay actividad, puede llamar acurl_multi_perform
para realizar cualquier solicitud pendiente. Esta función luego devolverá el número de manijas con solicitudes completadas, que puede iterar para recuperar sus respuestas utilizandocurl_easy_getinfo
y empujarlos a una cola u otra estructura de datos.Aquí hay un ejemplo de implementación:
Tenga en cuenta que deberá modificar la clase
CurlHttpClient
para agregar una variable miembro multi-handle y inicializarla apropiadamente. También deberá agregar verificación y manejo de errores a la función “request” para manejar cualquier error que pueda ocurrir durante la comunicación del multi-interfaz.