If an asynchronous request expires before opening a connection, inspect the transport's active limits as well as network timeouts. libcurl queues transfers when those limits are occupied, and their timeout budgets continue while queued.

For Guzzle 7's shared cURL multi handler:

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlMultiHandler;

$multi = new CurlMultiHandler([
    'options' => [
        CURLMOPT_MAX_TOTAL_CONNECTIONS => 24,
        CURLMOPT_MAX_HOST_CONNECTIONS => 4,
    ],
]);
$client = new Client([
    'handler' => HandlerStack::create($multi),
]);

Use this client for the asynchronous work and supply its intended proxy option on the operations. The values are example budgets. For public requests allowed through a public intermediary, the HTTP proxy list provides candidates for the operations’ proxy URLs.

OptionBudget
MAX_TOTAL_CONNECTIONSSimultaneously open connections under the multi handle
MAX_HOST_CONNECTIONSConnections to one host/port; proxy connections count against the proxy endpoint
MAXCONNECTSConnections retained in the cache after use

Several websites using the same proxy do not automatically receive separate proxy connection allowances. Idle-cache capacity neither opens connections in advance nor makes them interchangeable: reuse depends on route, destination, protocol and authentication.

Keep the application task budget and any provider allowance consistent with these transport budgets. They count connections, not requests per second. Raising a socket timeout cannot identify whether a queue or network wait consumed the time.

Winndannde jowitiiɗe heen