Erros de DNS no libcurl / c-ares, mas não no curl da linha de comandos

1

Descrição do problema

Eu tenho um executável que envia dados repetidamente para um endpoint HTTPS, usando libcurl com libcares. Isso está recebendo tempos limite de resolução de DNS ocasionais em alguns clientes (não todos). Se eu executar o comando equivalente no curl da linha de comando, nunca vejo nenhum tempo limite.

O que torna isso ainda mais confuso é que o host é explicitamente especificado em / etc / hosts, portanto, não deve haver nenhuma resolução de DNS necessária.

O erro do libcurl (com o modo detalhado) é:

* Adding handle: conn: 0xcbca20
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 88 (0xcbca20) send_pipe: 1, recv_pipe: 0
* Resolving timed out after 2002 milliseconds
* Closing connection 88

Meu executável libcurl está enviando 2-3 consultas por segundo e vejo esse erro uma vez a cada 300 solicitações. Usando o curl de linha de comando, executei 10000 consultas sem um único tempo limite.

Alguém pode sugerir algo que eu possa tentar resolver esses erros do libcurl? Existe alguma configuração que eu preciso adicionar à minha configuração libcurl, ou configuração do sistema eu poderia estar faltando?

Eu não tinha certeza se deveria colocar isso no Stack Overflow, Server Fault ou Ask Ubuntu; desculpas se estiver no lugar errado.

Obrigado pelo seu tempo!

Informações mais detalhadas

O cliente é o Ubuntu 12.04, 64 bits. O mesmo problema foi observado em vários clientes, todos com o mesmo sistema operacional.

Os nomes de usuário / senhas / URLs foram ofuscados nos snippets a seguir.

Testador de curvas de linha de comando (usando v 7.22.0):

while true; do curl -v -u username:password "https://myhost.com/endpoint" -X POST --data "a=x&b=y" >> /tmp/commandLine.log 2>&1; sleep 0.1; done &

Código-fonte do Libcurl (usando o curl 7.30.0, com c-ares 1.10.0):

#include <curl/curl.h>
#include <unistd.h>
#include <string>
#include <iostream>

using namespace std;

int main(int argc, char** argv) {

   while (1) {

       // Initialise curl
       CURL *curl = curl_easy_init();

       // Set endpoint
       string urlWithEndpoint = "https://myhost.com/endpoint";
       curl_easy_setopt(curl, CURLOPT_URL, urlWithEndpoint.c_str());

       // Set-up username and password for request
       curl_easy_setopt(curl, CURLOPT_USERPWD, "username:password");

       // Append POST data specific stuff
       string postData = "a=x&b=y";
       long postSize = postData.length();
       curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postSize);
       curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, postData.c_str());

       //set timeouts
       curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
       curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2);
       curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 60);

       cout << endl << endl << "=========================================================" << endl << endl;
       cout << "Making curl request to " << urlWithEndpoint << "(POST size " << postSize << "B)" << endl;

       // Set curl to log verbose information
       curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);

       // Perform the request
       CURLcode curlRes = curl_easy_perform(curl);

       // Handle response
       bool success = false;
       if (curlRes == CURLE_OK) {
           long httpCode;
           curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
           success = (httpCode==200);
           cout << "Received response " << httpCode << endl;
       } else if ( curlRes == CURLE_OPERATION_TIMEDOUT ) {
           cout << "Received timeout" << endl;
       } else {
           cout << "CURL error" << endl;
       }

       curl_easy_cleanup(curl);

       if (success) {
           cout << "SUCCESS! (" << time(0) << ")" << endl;
           usleep(0.1*1e6);
       } else {
           cout << "FAILURE!!!! (" << time(0) << ")" << endl;
           usleep(10*1e6);
       }

   }

}
    
por geekydel 24.07.2017 / 11:18

1 resposta

0

Respondendo a minha própria pergunta ...

Descobriu-se que o problema estava na lib c-ares (que fornece resolução de DNS segura para thread no libcurl). Tendo recompilado libcurl com --enable-threaded-resolver, os tempos limite de resolução param.

Eu tentei atualizar para o mais recente lib c-ares, e procurando nos fóruns c-ares por erros semelhantes, mas sem sorte em qualquer frente. Então, eu estou abandonando o c-ares e usando o resolvedor rosqueado Curl daqui para frente.

    
por 25.07.2017 / 09:32