PHP并發請求優化:使用`curl_multi_select()`實現高效的多請求處理

PHP并發請求優化:使用curl_multi_select()實現高效的多請求處理

背景

最近在項目中遇到一個需求,需要從多個 1 級網站(超過 200 個)獲取數據,并且是通過 POST 請求瞬間發送到這些網站上。開始時我直接使用了 curl_exec() 逐一發送請求,但是很快就發現了一個問題:這個方法是阻塞式的,只能一次發送一個請求。處理 200 多個請求時,性能非常差。顯然,這種方法不適合大規模的并發請求。

為了解決這個問題,我查閱了大量資料,最后找到了一個不錯的方案——使用 curl_multi_exec()curl_multi_select() 實現并發請求。這樣不僅能大幅提升性能,還能避免 CPU 資源的浪費。下面是我的經驗分享,希望對大家有幫助。

1. 為什么不用 curl_exec()

最開始,我像往常一樣使用 curl_exec() 來發送請求,但是遇到了以下兩個問題:

  1. 性能低下:每次只能處理一個請求,多個請求只能串行執行,耗時較長。
  2. 資源消耗大:頻繁的網絡請求導致 CPU 長時間空轉,系統資源被大量占用。

顯然,這樣的方式不適合處理 200 多個并發請求,尤其是當項目需要高效、實時獲取數據的時候。所以我需要找到一種更好的方式來實現并發請求。

2. 使用 curl_multi_exec() 實現并發請求

為了提升并發請求的效率,我決定使用 curl_multi_exec()。它可以將多個 cURL 請求組合在一起并行執行,從而大大提高了處理效率。

基本使用方法

首先,簡單介紹一下如何使用 curl_multi_exec()。這個函數允許同時執行多個 cURL 請求,而不需要等待每個請求的完成。

$multiCurl = curl_multi_init();  // 初始化multi cURL句柄// 創建單個cURL請求
$ch1 = curl_init('https://example.com');
$ch2 = curl_init('https://example2.com');// 將單個cURL句柄加入multi句柄中
curl_multi_add_handle($multiCurl, $ch1);
curl_multi_add_handle($multiCurl, $ch2);// 執行并發請求
do {$status = curl_multi_exec($multiCurl, $active);
} while ($active && $status == CURLM_OK);// 關閉cURL句柄
curl_multi_remove_handle($multiCurl, $ch1);
curl_multi_remove_handle($multiCurl, $ch2);
curl_multi_close($multiCurl);

通過這種方法,我可以同時發送多個請求,而不必等待每個請求逐一完成。對比 curl_exec(),處理多個請求的效率提高了很多。

3. 優化:結合 curl_multi_select() 降低系統資源消耗

雖然 curl_multi_exec() 可以并發處理多個請求,但它本身并不會阻塞,因此我發現頻繁調用它會導致系統的 CPU 資源大量消耗。這個問題在處理大量請求時尤其明顯。

后來經過一番摸索,發現了 curl_multi_select()。這個函數可以阻塞進程,直到有請求完成或發生變化(如接收到數據等)。這樣可以減少不必要的 CPU 占用,讓系統只在有必要時才執行檢查。

curl_multi_select() 的用法

通過 curl_multi_select(),我能有效減少 CPU 的空轉等待。它的工作方式很簡單:在等待時段內,如果有請求狀態發生變化(比如完成、錯誤等),它就會繼續執行。如果沒有變化,進程會阻塞直到超時。

$multiCurl = curl_multi_init();// 創建多個cURL請求
$ch1 = curl_init('https://example.com');
$ch2 = curl_init('https://example2.com');// 添加請求句柄
curl_multi_add_handle($multiCurl, $ch1);
curl_multi_add_handle($multiCurl, $ch2);do {$status = curl_multi_exec($multiCurl, $active);if ($active) {// 使用 curl_multi_select 等待請求狀態的變化,避免頻繁CPU循環curl_multi_select($multiCurl);}} while ($active && $status == CURLM_OK);// 獲取并處理每個請求的響應
curl_multi_remove_handle($multiCurl, $ch1);
curl_multi_remove_handle($multiCurl, $ch2);
curl_multi_close($multiCurl);

在這段代碼中,curl_multi_select() 用于等待活動發生,只有當請求完成或者有數據時,才會繼續執行,節省了 CPU 資源。

4. 實際應用:批量并發請求

為了處理項目中的大規模并發請求,我最終實現了一個可以同時發送多個請求的批處理腳本。以下是完整代碼:

<?php// 初始化multi cURL句柄
$multiCurl = curl_multi_init();
$curlHandles = [];// 準備多個URL
$urls = ['https://example.com','https://example2.com','https://example3.com','https://example4.com'
];// 創建cURL句柄并將其添加到multi句柄中
foreach ($urls as $i => $url) {$ch = curl_init($url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回結果而不是直接輸出$curlHandles[$i] = $ch;curl_multi_add_handle($multiCurl, $ch);
}do {$status = curl_multi_exec($multiCurl, $active);if ($active) {// 阻塞等待直到有請求完成curl_multi_select($multiCurl);}} while ($active && $status == CURLM_OK);// 獲取并處理每個請求的響應
foreach ($curlHandles as $i => $ch) {$response = curl_multi_getcontent($ch);echo "Response from URL {$urls[$i]}: $response\n";curl_multi_remove_handle($multiCurl, $ch);  // 移除句柄
}// 關閉multi句柄
curl_multi_close($multiCurl);

通過這個方法,我成功實現了向 200 多個 1 級網站同時發起 POST 請求的需求,速度比最初的逐一請求快了很多倍。而且系統資源消耗也得到了很好的控制,避免了 CPU 的過度占用。

5. 總結

通過使用 curl_multi_exec()curl_multi_select(),我們可以大幅提升 PHP 中并發請求的處理效率,特別是當需要處理大量外部請求時。這種方法不僅能提高響應速度,還能有效降低系統資源的消耗,是非常適合大規模并發處理的解決方案。

希望這篇文章能為大家提供一些幫助,如果有類似需求的開發者也可以嘗試這個方法。有什么問題或建議,歡迎留言交流!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72798.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【leetcode hot 100 206】反轉鏈表

解法一&#xff1a;&#xff08;頭插法&#xff09;在遍歷鏈表時&#xff0c;將當前節點的 next 指針改為指向前一個節點。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val)…

【QT】-易錯點筆記-2025-2-7

1,QList<phy_simulator*> pList;為空不能append()追加,要先new,再用 QList<phy_simulator> pList為空時,確實不能調用 append() 方法。原因很簡單,QList 是一個類對象,在 C++ 中,指針本身并不代表它指向的對象。因此,當你有一個指向 QList<phy_simulato…

AI-Deepseek + PPT

01--Deepseek提問 首先去Deepseek問一個問題&#xff1a; Deepseek的回答&#xff1a; 在汽車CAN總線通信中&#xff0c;DBC文件里的信號處理&#xff08;如初始值、系數、偏移&#xff09;主要是為了 將原始二進制數據轉換為實際物理值&#xff0c;確保不同電子控制單元&…

實驗一:在Windows 10/11下配置和管理TCP/IP

目錄 1.【實訓目標】 2.【實訓環境】 3.【實訓內容】 4.【實訓步驟】 1.【實訓目標】 1.了解網絡基本配置中包含的協議、服務、客戶端。 2.了解Windows支持的網絡協議及參數設置方法。 3.掌握TCP/IP協議的配置。 2.【實訓環境】 硬件環境&#xff1a;每人一臺計算機&a…

Java直通車系列14【Spring MVC】(深入學習 Controller 編寫)

目錄 基本概念 編寫 Controller 的步驟和要點 1. 定義 Controller 類 2. 映射請求 3. 處理請求參數 4. 調用業務邏輯 5. 返回響應 場景示例 1. 簡單的 Hello World 示例 2. 處理路徑變量和請求參數 3. 處理表單提交 4. 處理 JSON 數據 5. 異常處理 基本概念 Cont…

EA - 開源工程的編譯

文章目錄 EA - 開源工程的編譯概述筆記環境備注x86版本EABase_x86EAAssert_x86EAThread_x86修改 eathread_atomic_standalone_msvc.h原始修改后 EAStdC_x86EASTL_x86EAMain_x86EATest_x86備注備注END EA - 開源工程的編譯 概述 EA開源了‘命令與征服’的游戲源碼 嘗試編譯. 首…

一招解決Pytorch GPU版本安裝慢的問題

Pytorch是一個流行的深度學習框架&#xff0c;廣泛應用于計算機視覺、自然語言處理等領域。安裝Pytorch GPU版本可以充分利用GPU的并行計算能力&#xff0c;加速模型的訓練和推理過程。接下來&#xff0c;我們將詳細介紹如何在Windows操作系統上安裝Pytorch GPU版本。 查看是否…

為解決局域網IP、DNS切換的Windows BAT腳本

一、背景 為解決公司普通人員需要切換IP、DNS的情況&#xff0c;于是搞了個windows下的bat腳本&#xff0c;可以對有線網絡、無線網絡進行切換設置。 腳本內容 echo off title 多網絡接口IP切換工具:menu cls echo echo 請選擇要配置的網絡接口: echo echo 1. 有線網絡&am…

uni_app實現下拉刷新

1. 在頁面配置中啟用下拉刷新 首先&#xff0c;你需要在頁面的 pages.json 文件中啟用下拉刷新功能。 {"pages": [{"path": "pages/index/index","style": {"navigationBarTitleText": "首頁","enablePull…

OpenCV計算攝影學(14)實現對比度保留去色(Contrast Preserving Decolorization)的函數decolor()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 將彩色圖像轉換為灰度圖像。它是數字印刷、風格化的黑白照片渲染&#xff0c;以及許多單通道圖像處理應用中的基本工具。 cv::decolor 是 OpenCV…

Qt常用控件之 縱向列表QListWidget

縱向列表QListWidget QListWidget 是一個縱向列表控件。 QListWidget屬性 屬性說明currentRow當前被選中的是第幾行。count一共有多少行。sortingEnabled是否允許排序。isWrapping是否允許換行。itemAlignment元素的對齊方式。selectRectVisible被選中的元素矩形是否可見。s…

關于 QPalette設置按鈕背景未顯示出來 的解決方法

若該文為原創文章&#xff0c;轉載請注明原文出處 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/146047054 長沙紅胖子Qt&#xff08;長沙創微智科&#xff09;博文大全&#xff1a;開發技術集合&#xff08;包含Qt實用技術、樹莓派、三維、OpenCV…

PostgreSQL 安裝與使用

下載地址: EDB: Open-Source, Enterprise Postgres Database Management 安裝圖形化安裝界面安裝。安裝完后將bin目錄配置到系統環境變量 執行psql -h localhost -p 5432 -U postgres 密碼在安裝過程中設置的 ? 0、修改密碼 ALTER USER sonar WITH PASSWORD 123456; 1、新…

【基礎3】快速排序

核心思路 快速排序是Java中Arrays.sort()的實現原理&#xff0c;采用分治策略&#xff0c;通過選擇基準元素&#xff0c;將數組分為兩個子數組&#xff0c;使得左邊元素 ≤ 基準元素 ≤ 右邊元素&#xff0c;然后遞歸排序子數組。 舉個簡單的例子&#xff0c;圖書管理員需要按…

FreeSWITCH 簡單圖形化界面40 - 使用mod_curl模塊進行http請求

FreeSWITCH 簡單圖形化界面40 - 使用mod_curl模塊進行http請求 0、界面預覽00、簡介1、編譯安裝1.1 編輯模塊配置文件 2、使用2.1 撥號規則GET 請求POST 請求JSON 數據 2.2 Lua 腳本GET 請求POST 請求JSON 數據 3 、示例3.1 示例 1&#xff1a;提交 CDR 到第三方接口3.2 示例 2…

Linux 開發工具

linux中&#xff0c;常見的軟件安裝方式---下載 yum/apt.rpm安裝包安裝源碼安裝 yum 查看軟件包 通過yumlist命令可以羅列出當前?共有哪些軟件包.由于包的數?可能?常之多,這?我們需要使? grep 命令只篩選出我們關注的包.例如: # Centos $ yum list | grep lrzsz lr…

Agent革命:Manus如何用工作流拆解掀起AI生產力革命

一、現象級產品的誕生背景 2025年3月6日&#xff0c;一款名為Manus的AI產品在技術圈引發地震式傳播。其官方測試數據顯示&#xff1a;在GAIA基準測試中&#xff0c;基礎任務準確率達86.5%&#xff08;接近人類水平&#xff09;&#xff0c;中高級任務完成率突破57%。這標志著A…

Linux13-TCP\HTTP

一、TCP粘包問題 1.TCP在接受數據時,多包數據粘在一起 2.原因: 2.1TCP發送數據時,會根據緩沖區數據的情況進行重新組包 2.2TCP接收方,沒有及時讀走緩沖區數據,導致緩沖區大量數據緩存。 3.如何解決 3.1發指定大小字節 將要發數據,封裝在結構體里 struct data { …

網絡安全等級保護2.0 vs GDPR vs NIST 2.0:全方位對比解析

在網絡安全日益重要的今天&#xff0c;各國紛紛出臺相關政策法規&#xff0c;以加強信息安全保護。本文將對比我國網絡安全等級保護2.0、歐盟的GDPR以及美國的NIST 2.0&#xff0c;分析它們各自的特點及差異。 網絡安全等級保護2.0 網絡安全等級保護2.0是我國信息安全領域的一…

oracle通過dmp導入數據

1、創建用戶&#xff0c;并賦予sysdba權限 登錄sysdba用戶 sqlplus / as sysdba 賦予sysdba權限 grant sysdba to your_user; 2、導入dmp文件 imp target_user/passwordip:port/SERVER_NAME fromusersource_user tousertarget_user fileyour.dmp logdmp_file.log statist…