<span><span><span class="hljs-meta"><?php</span></span><span>
</span><span><span class="hljs-comment">// 以下是與文章內容無關的 PHP 代碼示例</span></span><span>
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"歡迎使用PHP小工具!\n"</span></span><span>;
</span><span><span class="hljs-variable">$time</span></span><span> = </span><span><span class="hljs-title function_ invoke__">date</span></span><span>(</span><span><span class="hljs-string">'Y-m-d H:i:s'</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"當前時間: <span class="hljs-subst">$time</span></span></span><span>\n";
</span><span><span class="hljs-meta">?></span></span><span>
</span></span>
在PHP 中,使用curl_multi_*系列函數可以實現並發請求,從而提升HTTP 請求的效率。然而,在實際開發中, curl_multi_remove_handle()調用失敗的情況時有發生。本文將分析常見原因,並提供快速排查和解決方法。
curl_multi_remove_handle()用於將單個cURL 句柄從cURL 多線程句柄中移除:
<span><span><span class="hljs-variable">$mh</span></span><span> = </span><span><span class="hljs-title function_ invoke__">curl_multi_init</span></span><span>();
</span><span><span class="hljs-variable">$ch1</span></span><span> = </span><span><span class="hljs-title function_ invoke__">curl_init</span></span><span>(</span><span><span class="hljs-string">"https://example.com"</span></span><span>);
</span><span><span class="hljs-variable">$ch2</span></span><span> = </span><span><span class="hljs-title function_ invoke__">curl_init</span></span><span>(</span><span><span class="hljs-string">"https://example.org"</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_multi_add_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch1</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_multi_add_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch2</span></span><span>);
</span><span><span class="hljs-comment">// 執行請求</span></span><span>
</span><span><span class="hljs-variable">$running</span></span><span> = </span><span><span class="hljs-literal">null</span></span><span>;
</span><span><span class="hljs-keyword">do</span></span><span> {
</span><span><span class="hljs-title function_ invoke__">curl_multi_exec</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$running</span></span><span>);
} </span><span><span class="hljs-keyword">while</span></span><span> (</span><span><span class="hljs-variable">$running</span></span><span> > </span><span><span class="hljs-number">0</span></span><span>);
</span><span><span class="hljs-comment">// 移除句柄</span></span><span>
</span><span><span class="hljs-title function_ invoke__">curl_multi_remove_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch1</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_multi_remove_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch2</span></span><span>);
</span><span><span class="hljs-comment">// 關閉句柄</span></span><span>
</span><span><span class="hljs-title function_ invoke__">curl_multi_close</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_close</span></span><span>(</span><span><span class="hljs-variable">$ch1</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_close</span></span><span>(</span><span><span class="hljs-variable">$ch2</span></span><span>);
</span></span>
如果curl_multi_remove_handle()調用失敗,通常返回FALSE 。
句柄未加入multi 句柄<br> 只有已經通過curl_multi_add_handle()添加到multi 句柄的cURL 句柄才能被移除如果句柄從未添加,或已被移除,再調用curl_multi_remove_handle()就會失敗。
重複移除句柄<br> 同一個cURL 句柄只能從multi 句柄中移除一次多次調用會導致失敗。
multi 句柄已關閉<br> 如果在調用curl_multi_remove_handle()之前, curl_multi_close()已經執行,multi 句柄被銷毀,自然無法移除子句柄
cURL 執行過程中未正確停止<br> 如果multi 執行循環( curl_multi_exe c ) 尚未完成,或仍處於運行狀態,嘗試移除句柄可能會失敗通常建議先確保$running為0。
資源損壞或句柄無效<br> 如果cURL 句柄被意外關閉或失效,也會導致移除失敗這種情況常發生在異常處理或錯誤的資源管理中。
確認句柄已加入multi
在調用curl_multi_remove_handle()前,可以記錄添加的句柄:
<span><span><span class="hljs-variable">$handles</span></span><span> = [];
</span><span><span class="hljs-title function_ invoke__">curl_multi_add_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch1</span></span><span>);
</span><span><span class="hljs-variable">$handles</span></span><span>[] = </span><span><span class="hljs-variable">$ch1</span></span><span>;
</span></span>
確保多句柄仍然有效<br> 調用curl_multi_close()前執行移除操作
等待所有請求完成<br> 使用循環檢測$running是否為0,再移除句柄
<span><span><span class="hljs-keyword">do</span></span><span> {
</span><span><span class="hljs-title function_ invoke__">curl_multi_exec</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$running</span></span><span>);
} </span><span><span class="hljs-keyword">while</span></span><span> (</span><span><span class="hljs-variable">$running</span></span><span> > </span><span><span class="hljs-number">0</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_multi_remove_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch1</span></span><span>);
</span></span>
檢查返回值和錯誤信息<br> 如果返回FALS E ,可以通過curl_error($ch)或curl_multi_errno($mh)獲取具體錯誤信息
調試日誌<br> 在復雜並發請求中,可以用日誌記錄添加、移除句柄的順序,避免重複移除或未添加即移除的情況
始終確保每個cURL 句柄只添加一次,移除一次。
移除句柄前,保證multi 執行循環已結束。
不要在關閉multi 句柄後再移除子句柄。
使用調試日誌記錄句柄狀態,便於快速定位問題。
遇到異常或資源損壞情況,可重新初始化句柄再嘗試。
通過遵循上述方法,可以有效減少curl_multi_remove_handle()調用失敗的情況,提高PHP 並發請求的穩定性和可維護性。