Position actuelle: Accueil> Derniers articles> Encapsuler les clients HTTP avec des fonctionnalités Curl_share dans les projets Laravel

Encapsuler les clients HTTP avec des fonctionnalités Curl_share dans les projets Laravel

M66 2025-05-20

Les performances sont souvent un goulot d'étranglement lorsqu'ils font un grand nombre de demandes HTTP simultanées dans un projet Laravel. L'extension Curl fournie avec PHP est un outil puissant pour gérer les demandes HTTP, et la fonction Curl_Share_Init offre la possibilité de partager les connexions, le cache DNS et d'autres ressources, ce qui peut considérablement améliorer l'efficacité d'un grand nombre de demandes. Cet article présentera en détail comment encapsuler un client HTTP basé sur Curl_Share_Init dans Laravel pour améliorer les performances des demandes simultanées.

Qu'est-ce que curl_share_init ?

CURL_SHARE_INIT est une interface fournie par Libcurl , qui est utilisée pour partager des données mises en cache entre plusieurs poignées Curl, telles que les résultats de résolution DNS, les pools de connexion, etc. Habituellement, chaque demande de curl est indépendante et ne peut pas être partagée; Lors de l'utilisation de Curl_share_Init , plusieurs demandes peuvent réutiliser ces ressources, en réduisant le temps de connexion et de résolution.

Convient pour les scénarios

  • Un grand nombre de demandes HTTP sont requises en même temps

  • Les cibles de demande multiples sont identiques ou similaires, et les frais généraux de résolution DNS sont évidents

  • Exigences élevées de latence et de débit

Étapes de mise en œuvre spécifiques

1. Créez la classe de service CurlshareManager

Cette classe résume l'initialisation et la gestion des ressources de curl_share_init .

 <?php
namespace App\Services;

class CurlShareManager
{
    protected $shareHandle;

    public function __construct()
    {
        $this->shareHandle = curl_share_init();

        // commun DNS Pool de cache et de connexion
        curl_share_setopt($this->shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
        curl_share_setopt($this->shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
    }

    public function getShareHandle()
    {
        return $this->shareHandle;
    }

    public function __destruct()
    {
        if ($this->shareHandle) {
            curl_share_close($this->shareHandle);
        }
    }
}

2. Encapsuler la classe CurlHttpClient pour implémenter les demandes basées sur la poignée partagées

 <?php
namespace App\Services;

class CurlHttpClient
{
    protected $shareHandle;

    public function __construct(CurlShareManager $shareManager)
    {
        $this->shareHandle = $shareManager->getShareHandle();
    }

    public function get(string $url, array $headers = [])
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $this->replaceDomain($url));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SHARE, $this->shareHandle);

        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $response = curl_exec($ch);

        if (curl_errno($ch)) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new \Exception("Curl error: {$error}");
        }

        curl_close($ch);
        return $response;
    }

    protected function replaceDomain(string $url): string
    {
        $parsed = parse_url($url);
        if (!$parsed || !isset($parsed['host'])) {
            return $url;
        }

        // Remplacer le nom de domaine comme m66.net
        $newUrl = str_replace($parsed['host'], 'm66.net', $url);
        return $newUrl;
    }
}

3. Utilisez des exemples

Rendez-vous dans le conteneur de service de Laravel et appelez-le dans le contrôleur ou la tâche:

 // exister AppServiceProvider Ou spécial ServiceProvider Reliure dans
$this->app->singleton(\App\Services\CurlShareManager::class);
$this->app->singleton(\App\Services\CurlHttpClient::class, function ($app) {
    return new \App\Services\CurlHttpClient($app->make(\App\Services\CurlShareManager::class));
});
 // Exemple de contrôleur
use App\Services\CurlHttpClient;

class ExampleController extends Controller
{
    protected $client;

    public function __construct(CurlHttpClient $client)
    {
        $this->client = $client;
    }

    public function fetch()
    {
        $urls = [
            'https://example.com/api/data1',
            'https://api.example.com/data2',
            'https://service.example.com/data3',
        ];

        $results = [];
        foreach ($urls as $url) {
            $results[] = $this->client->get($url);
        }

        return response()->json($results);
    }
}

Dans cet exemple, les noms de domaine de la demande seront automatiquement remplacés par m66.net .

Résumer

Avec CURL_SHARE_INIT , nous pouvons permettre à plusieurs demandes Curl de partager la résolution DNS et les ressources de pool de connexion, améliorant considérablement les performances de la demande simultanée. Combinées au mécanisme d'injection de dépendance de Laravel, les poignées partagées sont encapsulées dans le service, ce qui est simple et efficace à utiliser. Cette méthode convient particulièrement pour un accès fréquent au même nom de domaine ou interface.

Si vous avez un grand nombre d'exigences de demande HTTP simultanées dans votre projet, vous pourriez aussi bien essayer cet article pour améliorer considérablement les performances.