封裝curl_multi讓請求與業務邏輯並行執行

薇文發表於2020-12-23

PHP開發中需要請求其它HTTP(S)服務介面時,很多人都會直接使用內建的curl工具。其中curl_multi可以將之前單個的curl請求新增到一個批處理中去並行執行,在時間開銷上實現max(介面1, 介面2, 介面3...)的效果,能夠降低我們的業務需要多服務資料聚合時對使用者產生的等待感。

那麼本文能夠帶來什麼呢?

  • 時間優化不止於max(介面1, 介面2, 介面3...),可達max(業務程式碼, 介面1, 介面2, 介面3...),讓請求後的等待期也能用來執行業務程式碼。
  • curl curl_multi的友好使用封裝,以物件的封裝來簡化程式碼中各種curl_*函式的記憶和凌亂。

環境

  • Win10 x64PHP8.0.0 TS x64

前言

  • curl_multi建立一個批處理,將多個curl控制程式碼加入其中,然後執行這個批處理
  • curl_multi_exec()執行批處理中需要操作的控制程式碼。
    • 傳送請求/接收處理響應,等待響應時則無需操作
  • curl_multi_select()阻塞等待,直到有待處理的控制程式碼/超時
    • 如某個控制程式碼接收到了響應。
    • 此函式可以避免等待期的死迴圈空轉exec情況。執行緒應該是掛起狀態,由底層觸發喚醒。

分析

  • 優化核心在於curl_multi_exec()curl_multi_select()
  • 通過除錯發現執行curl_multi_exec()第一次即為傳送HTTP請求報文,推測exec的執行粒度為HTTP請求/響應報文的處理。
  • 所以我們可以先傳送請求,然後執行自己的業務邏輯,最後需要時再獲取執行結果。這樣就可以複用等待響應的時間。
  • 因為重定向/HTTPS都會涉及到多次HTTP報文互動,封裝中儘量為其提供了可選優化引數。

測試(下方有結果圖)

  • 封裝&測試程式碼倉庫 gitee.com/VwenX/curl-mut
  • 本地使用node啟了一個http伺服器(程式碼見下圖,網上隨便找的改一下用)
  • 步驟
    • 目標http服務中設定了接到請求後等待300ms後才進行響應,並在響應中輸出實際等待時長
    • PHP作為客戶端請求3個介面,同時模擬執行業務1秒
    • 最終我們可以看到3個介面的耗時都在310ms以上。
    • 如果按照常規呼叫,整體耗時該在max(a, b, c)+業務=1317ms以上。但我們此番處理之後的整體耗時僅為1017ms,3個310+ms的請求幾乎沒有佔用什麼時間開銷!

測試結果圖

curlMut測試結果

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章