PHP的併發處理

什麼是進程、線程、協程

進程 Process

  • 計算機中的程序關於某數據集合上的一次運行活動,“一個執行中的程序”
  • 系統進行資源分配和調度的基本單位
  • 三態模型:
    多道程序系統中,進程在處理器上交替運行,狀態不斷地發生變化
    • 運行:正在處理機上運行;
    • 就緒:當一個進程獲得了除處理機以外的一切所需資源,一旦得到處理機即可運行,則稱處於就緒狀態。可按多個優先級來劃分隊列。如,當一個進程由於時間片用完而進入就緒狀態時,排入低優先級;當進程由IO操作完成而進入就緒狀態時,排入高優先級隊列。
    • 阻塞:也稱爲等待或睡眠狀態,一個進程正在等待某一事件發生(例如請求IO而等待IO完成等)而暫時停止運行,這時即使把處理機分配給進程也無法運行。
  • 五態模型:
    • 新建態:進程剛剛被創建時沒有被提交的狀態,等待系統完成創建進程的所有必要信息。
    • 活躍就緒/靜止就緒:
      • 活躍就緒,指進程在主存並且可被調度的狀態;
      • 靜止就緒,是指進程被對換到輔存時的就緒狀態,是不能被直接調度的狀態,只有當主存中沒有活躍就緒態進程,或者是掛起就緒態進程具有更高的優先級,系統將把掛起就緒態進程調回主存並轉換爲活躍就緒。
    • 運行:-
    • 活躍阻塞/靜止阻塞:
      • 活躍阻塞,是指進程已在主存,一旦等待的事件發生便進入活躍就緒狀態;
      • 靜止阻塞,進程對換到輔存時的阻塞狀態,一旦等待的事件發生便進入靜止就緒狀態。
    • 終止態:進程已結束運行,回收除進程控制塊之外的其他資源,並讓其他進程從進程控制塊中收集有關信息。

線程 Thread

  • 有時被稱爲輕量級進程(LightWeight Process, LWP),程序執行流的最小單元。
  • 一個相對獨立的、可調度的執行單元,系統獨立調度和分配CPU的基本單位。
  • 共享進程的地址空間和資源。
  • 狀態:就緒、阻塞、運行
    • 就緒狀態:具備運行的所有條件,邏輯上可以運行,在等待處理機
    • 運行狀態:佔有處理機正在運行
    • 阻塞狀態:在等待一個事件(如某個信號量),邏輯上不可執行

協程 Coroutine

  • 一種用戶態的輕量級線程,調度完全由用戶控制
  • 擁有自己的寄存器上下文和棧
  • 調度切換時,將寄存器上下文和棧保存到其他地方,切回來的時候恢復,基本沒有內核切換的開銷
  • 可以不加鎖的訪問全局變量
  • 異步

什麼是多進程、多線程

多進程

同一個時間裏,同一個計算機系統中如果允許兩個或兩個以上的進程處於運行狀態,就是多進程

多線程

單個程序中同時運行多個線程完成不同的工作,就是多線程


同步阻塞模型

多進程,最早的服務端程序都是通過多進程、多線程來解決併發IO的問題;
一個請求創建一個進程,然後子進程進入循環同步堵塞地與客戶端連接進行交互,收發處理數據。
多線程,用多線程模式實現非常簡單,線程中直接向某一個客戶端連接發送數據。

缺點

  • 嚴重依賴進程的數量解決併發問題
  • 啓動大量進程會帶來額外的進程調度消耗

Multiprocess-multithread-synchronization-blocking


異步非阻塞模型

  • select 系統的查詢,一個進程內建立1024個連接,poll 模型,循環檢測是否有連接。
  • 現在各種高併發異步IO的服務器程序都是基於 epoll 實現的。
  • IO複用異步非阻塞程序使用經典的 Reactor 模型,顧名思義就是反應堆的意思,本身不處理任何數據收發。只是可以監視一個socket句柄的事件變化。

Reactor模型

  • Add: 添加一個socket到Reactor
  • Set: 修改socket對應的事件,如可讀可寫
  • Del: 從Reactor中移除,不再監聽事件
  • Callback: 事件發生後回調指定的函數

Nginx:多線程Reactor
Swoole:多線程Reactor + 多進程Worker

asynchronous-non-blocking


PHP併發編程實踐

Swoole擴展

  • 異步、並行、高性能網絡通信引擎,使用C語言編寫,提供了PHP語言的異步多線程服務器,異步TCP/UDP網絡客戶端,異步MySQL,異步Redis,數據庫連接池,AsyncTask,消息隊列,毫秒定時器,異步文件讀寫,異步DNS查詢
  • 爲PHP多進程的模式設計了多個併發數據結構和IPC通信機制,可以大大簡化多進程併發編程的工作
  • Swoole2.0支持了類似Go語言的協程,可以使用完全同步的代碼實現異步程序

消息隊列

  • 經典場景,
    • 註冊成功後發送郵件,發送短信
    • 串行方式:註冊成功後,先發送郵件,在發送短信
    • 並行方式:註冊成功後,同時發送郵件和短信
    • 消息隊列方式(離線方式):註冊成功後,將成功消息寫入隊列,此時直接返回成功給用戶,寫入隊列的時間非常短,可以忽略不計,然後異步發送郵件和短信 -
  • 應用解耦
    • 場景說明:用戶下單後,訂單系統需要通知庫存系統。
    • 假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗。
    • 訂單系統與庫存系統耦合
    • 引用隊列,用戶下單後,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功。
    • 訂閱下單的消息,採用拉/推的方式,獲取下單信息,庫存系統根據下單信息,進行庫存操作。
  • 流量削峯
    • 秒殺活動,流量瞬時激增,服務器壓力過大。
    • 用戶發起請求,服務器接收後,先寫入消息隊列。假如消息隊列長度超過最大值,則直接報錯或提示用戶。
    • 後續程序讀取消息隊列再做處理。
    • 控制請求量,緩解高流量。
  • 日誌處理
    • 場景:解決大量日誌的傳輸
    • 日誌採集程序將程序寫入消息隊列,然後通過日誌處理程序的訂閱消費日誌。
  • 消息通訊
    • 場景:聊天室
    • 多個客戶端訂閱同一主題,進行消息發佈和接收
  • 常見消息隊列產品
    • Kafka
    • ActiveMQ
    • ZeroMQ
    • RabbitMQ
    • Redis

接口的併發請求

curl_multi_init


參看

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章