PHP 8.5 curl_share_init_persistent() in Swoole workers: DNS and SSL session reuse across requests
PHP 8.5 adds curl_share_init_persistent() which creates cURL share handles that survive across PHP request boundaries within the same worker process. In a Swoole long-running worker this is interesting since DNS lookups, connection info, and SSL session data could be shared across coroutines handling different requests.
The docs explicitly forbid CURL_LOCK_DATA_COOKIE in the persistent share (throws ValueError) to prevent session data leaking between users. DNS and SSL session sharing should be safe.
Main concern before we try it: cURL is not coroutine-safe without Swoole’s hook, and I am not sure how persistent share handles interact with the cURL coroutine hook. Has anyone tested this in production?
We tested this in staging with Swoole 5.1 and PHP 8.5 with the cURL coroutine hook enabled. The persistent share handle works correctly when SWOOLE_HOOK_CURL is active. DNS cache sharing gave 8-12% speedup on endpoints that make multiple outbound calls to the same external services per request. Worth it for high-traffic workers.
The key thing: each coroutine needs its own curl handle, but they can all share the same persistent share handle. Create the share handle once at worker startup, then each request creates its own curl handle and attaches the share handle to it via CURLOPT_SHARE. Never share the curl handle itself between coroutines.
Same applies to RoadRunner workers since they are also long-lived PHP processes. Create the share handle in the worker boot phase before the request loop starts. We saw similar DNS cache benefits on a service that calls many different internal microservices by hostname.
@dmitry_kv @sergey_web thanks, that clears up the coroutine safety question. One more: does the persistent handle get destroyed between requests or does it truly live for the whole worker process lifetime? Asking because we need to know if we should recreate it on worker recycle.
It lives for the entire worker process lifetime. When Swoole recycles the worker after maxRequests, the handle is destroyed with the process. The “persistent” part means it survives individual PHP request boundaries, not worker restarts. No cleanup needed on your side, just create it once at boot and forget about it.
```php blocks are runnable.