現在の位置: ホーム> 最新記事一覧> laravelプロジェクトでcurl_share_init関数を使用してHTTPクライアントをカプセル化するには、同時リクエストパフォーマンスを改善する方法は?

laravelプロジェクトでcurl_share_init関数を使用してHTTPクライアントをカプセル化するには、同時リクエストパフォーマンスを改善する方法は?

M66 2025-05-20

Laravelプロジェクトで多数の同時HTTP要求を行う場合、パフォーマンスはしばしばボトルネックです。 PHPに付属するCURL拡張機能は、HTTPリクエストを処理するための強力なツールであり、 CURL_SHARE_INIT関数は、接続、DNSキャッシュ、その他のリソースを共有する機能を提供し、多数のリクエストの効率を大幅に改善できます。この記事では、 CURL_SHARE_INITベースのHTTPクライアントをLaravelでカプセル化する方法を詳細に紹介し、同時リクエストのパフォーマンスを向上させます。

curl_share_initとは何ですか?

curl_share_initはlibcurlによって提供されるインターフェイスです。これは、DNS解像度の結果、接続プールなど、複数のCurlハンドル間でキャッシュされたデータを共有するために使用されます。通常、各Curl要求は独立しており、共有できません。 curl_share_initを使用している間、複数のリクエストがこれらのリソースを再利用して、接続時間と解像度時間を短縮できます。

使用シナリオに適しています

  • 多数のHTTPリクエストが同時に必要です

  • 複数の要求ターゲットは同じまたは類似しており、DNS解像度のオーバーヘッドは明らかです

  • 高いレイテンシおよびスループットの要件

特定の実装手順

1. CurlshareManager Serviceクラスを作成します

このクラスは、 curl_share_initの初期化とリソース管理をカプセル化します。

 <?php
namespace App\Services;

class CurlShareManager
{
    protected $shareHandle;

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

        // 共有 DNS キャッシュと接続プール
        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。共有ハンドルベースのリクエストを実装するためにcurlhttpclientクラスをカプセル化する

<?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;
        }

        // ドメイン名を置き換えます m66.net
        $newUrl = str_replace($parsed['host'], 'm66.net', $url);
        return $newUrl;
    }
}

3.例を使用してください

Laravelのサービスコンテナにバインドし、コントローラーまたはタスクで呼び出します。

 // 存在する AppServiceProvider または特別 ServiceProvider バインディング
$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));
});
 // コントローラーの例
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);
    }
}

この例では、リクエスト内のドメイン名はM66.netに自動的に置き換えられます。

要約します

curl_share_initを使用すると、複数のCurl要求を有効にしてDNS解像度と接続プールリソースを共有し、同時リクエストのパフォーマンスを大幅に改善できます。 Laravelの依存関係インジェクションメカニズムと組み合わせることで、共有ハンドルはサービスにカプセル化されており、これは簡単で効率的です。この方法は、同じドメイン名またはインターフェイスに頻繁にアクセスするのに特に適しています。

プロジェクトに多数の同時HTTP要件要件がある場合は、この記事を試してパフォーマンスを大幅に改善することもできます。