免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

Swoole4.4中怎么實現協程搶占式調度器-創新互聯

本篇文章為大家展示了Swoole4.4中怎么實現協程搶占式調度器,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

網站建設哪家好,找成都創新互聯公司!專注于網頁設計、網站建設、微信開發、小程序制作、集團企業網站建設等服務項目。為回饋新老客戶創新互聯還提供了叢臺免費建站歡迎大家使用!

協程調度


去年Swoole推出了4.0版本后,完整的支持PHP協程,我們可以基于協程實現CSP編程,身邊的開發者驚呼,原來PHP代碼還可以這樣寫。Swoole的協程默認是基于IO調度,程序中有阻塞會自動讓出當前協程,協程的各種優勢我們不在這里展開討論。如果是IO密集型的場景,可以表現得很不錯。但是對于CPU密集型的場景,會導致一些協程因為得不到CPU時間片被餓死。

搶占式調度

我們在今年年初就計劃實現Swoole的搶占式調度,以滿足實現有些場景下的不均衡調度帶來的問題。我們中間經歷了幾個版本,在這里和大家分享一下開發過程中的動機和解決辦法。

Swoole4.4中怎么實現協程搶占式調度器

我們目的是為了均衡調度每個協程的CPU時間,比如協程3需要比較長的執行時間,我們必須把協程3的CPU時間主動中斷,而不依賴IO事件,使得每個協程得到平均的執行時間。

起初,我們的想法是可以從PHP的循環中自動檢測執行實踐,若達到限制,可以自動讓出當前協程。因為畢竟很少有人一馬平川的寫出占用很多CPU的代碼,大都通過循環條件來控制。我們hook循環指令,每次執行循環指令的時候,都來檢查協程的執行時間,我們很欣喜的得到了最初的版本。但是這樣做比較hack,而且opcode經過opcache優化后,情況會變得有些復雜。

后來我們使用PHPticks機制,也就是在PHP代碼編譯期間,注入ticks指令,可以執行相應的函數,我們可以在這些函數中檢測處理協程的時間,達到搶占式的效果,但是這里有一個問題,PHPdeclare(ticks=N)語法,只對當前腳本范圍有效,也就是說項目稍微大點,require或者include進來的腳本,并不會自動注入ticks指令,這樣Swoole開發者幾乎是無法接受的。我們也試圖給PHP官方提一個PR,可以在擴展層設置一個全局默認的ticks,但是官方不愿意采納我們的提交,因為官方覺得這個功能對性能損耗比較大,而且有可能在PHP8移除這個功能。其實經過實測這個性能損耗并不大,而且我們已經在生產環境驗證,并取得了顯著的效果,即可以讓出某些CPU密集的邏輯部分,使得服務整個相應時間更加均衡。


下圖是我們生產環境一個RPC接口的調用端統計數據對比,客戶端等待超時時間為2s,超時則統計為錯誤。


Swoole4.4中怎么實現協程搶占式調度器


左邊一側是沒有搶占式調度,右側是開了搶占式調度,可以發現,左側總是會有偶爾超時情況,而經過優化之后,沒有一個超時的請求,請求響應時間非常平滑,提升了服務的穩定性。


Swoole4.4中怎么實現協程搶占式調度器


可以從上圖看出,由于搶占式調度的加入,去除了請求耗時高的毛刺,使得平均請求時間變得更加平滑,穩定。

想要做搶占式調度,對于PHP來說,有兩個途徑

  • 單線程的PHP的執行流,通過執行指令做文章,可以在PHP執行流程中注入邏輯,以檢查執行時間,再加上Swoole的協程能力,可以在不同的協程中切換,以達到搶占CPU的目的。

  • 考慮開線程,負責檢查當前執行協程執行時間。

經過以上辦法的嘗試,注入指令的路數基本是無法得到官方的支持,我們只能另謀出路,多開一個線程,只負責檢查當前協程。具體的做法是,利用PHP-7.1.0引入的VM interrupt機制,默認每隔5ms檢查一下當前協程是否達到較大執行時間,默認為10ms,如果超過,則讓出當前協程,達到被其他協程搶占的目的。

示例代碼

需要Swoole 4.4或更高版本
<?php
Co::set(['enable_preemptive_scheduler' => 1]);
$start = microtime(1);
echo "start\n";
$flag = 1;

go(function () use (&$flag) {
 echo "coro 1 start to loop\n";
 $i = 0;
 for (;;) {
  if (!$flag) {
   break;
  }
  $i++;
 }
 echo "coro 1 can exit\n";
});
 
$end = microtime(1);
$msec = ($end - $start) * 1000;
echo "use time $msec\n";
go(function () use (&$flag) {
 echo "coro 2 set flag = false\n";
 $flag = false;
});
echo "end\n";

執行結果

start
coro 1 start to loop
use time 11.121988296509
coro 2 set flag = false
end
coro 1 can exit

可以發現,代碼邏輯可以從第一個協程的死循環中自動yield出來,執行第二個協程,如果沒有這個特性,第二個協程永遠不會被執行,導致被餓死。而這樣做,第二個協程可以順利被執行,最后執行結束后,第一個協程也會接著繼續往下執行。達到我們的第二個協程主動搶占第一個協程CPU的效果。

這個特性在生產環境非常有用,尤其是對于實時系統或者響應時間比較敏感的場景。

上述內容就是Swoole4.4中怎么實現協程搶占式調度器,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注創新互聯行業資訊頻道。

名稱欄目:Swoole4.4中怎么實現協程搶占式調度器-創新互聯
文章轉載:http://m.newbst.com/article38/diojsp.html

成都網站建設公司_創新互聯,為您提供手機網站建設網站建設網站維護網站排名微信公眾號App開發

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

搜索引擎優化