一鍵協(xié)程化在協(xié)程相關(guān)的內(nèi)容中,最后我們要講的就是這個(gè)一鍵協(xié)程化的功能。這玩意又是什么意思呢?我們先看下面的例子。 簡(jiǎn)單例子
先不考慮循環(huán)中間那個(gè)寫文件的操作,現(xiàn)在這兩個(gè)協(xié)程,你覺(jué)得會(huì)是怎么運(yùn)行的?注意,外面有沒(méi)有 run 都是一樣的。 如果你試了就會(huì)發(fā)現(xiàn),while() 會(huì)阻塞協(xié)程。又來(lái)了,又是同步阻塞和異步非阻塞的問(wèn)題,來(lái)來(lái)回回有完沒(méi)有完。 這還真沒(méi)辦法,【Swoole系列4.5】協(xié)程并發(fā)調(diào)度https://mp.weixin.qq.com/s/41hKQqTkHNolBxHJMM4vAg 中,我們講過(guò) sleep() 在容器內(nèi)外的表現(xiàn)會(huì)有不同,但 while() 則是不管有沒(méi)有容器都會(huì)阻塞的。同樣,如果是一個(gè)非常耗時(shí)的 IO 任務(wù),也會(huì)帶來(lái)這樣的問(wèn)題,這就會(huì)讓本來(lái)可以異步來(lái)回切換調(diào)度的協(xié)程功能退化成一個(gè)同步阻塞的功能。這可不是我們期望的結(jié)果呀。 好在 Swoole 團(tuán)隊(duì)的各路大神們經(jīng)過(guò)不斷地努力研究,總算克服了這個(gè)問(wèn)題。最開(kāi)始,他們也是一個(gè)一個(gè)地寫異步客戶端,但是呢?實(shí)現(xiàn)復(fù)雜,很難完美支持;用戶需要更改的代碼很多;很難覆蓋所有操作。于是,它們轉(zhuǎn)換了實(shí)現(xiàn)思路,通過(guò) Hook 原生的 PHP 函數(shù)實(shí)現(xiàn)的方式來(lái)實(shí)現(xiàn)協(xié)程客戶端。也就是給原生的那些功能函數(shù)加外掛,讓它們直接就可以支持協(xié)程化操作。 具體表現(xiàn)是什么呢?就是沒(méi)什么表現(xiàn)了。我們之前怎么寫代碼,現(xiàn)在還是怎么寫,不用考慮異步阻塞的問(wèn)題,只需要加上一行代碼就行了。這下你知道我們上回說(shuō)過(guò)為什么不推薦使用之前的協(xié)程 MySQL 和 Redis 客戶端了吧,直接使用一鍵協(xié)程化就行了。
現(xiàn)在你再試試上面的例子。
相信 222 就會(huì)先輸出出來(lái)了。注意,這里要打開(kāi)中間寫文件的注釋。為什么呢?因?yàn)樗?Hook 的功能函數(shù)中,不包含 while() ,我們需要借助里面的一些可以一鍵協(xié)程化的函數(shù)來(lái)讓協(xié)程實(shí)現(xiàn)調(diào)度。也就是說(shuō),在文件寫入的時(shí)候,協(xié)程會(huì) yield() 起來(lái),等待后續(xù)完成后回來(lái)繼續(xù)執(zhí)行這個(gè)協(xié)程中的內(nèi)容。 具體我們?cè)賮?lái)看下面官網(wǎng)給出的例子。 官網(wǎng)例子
Co::set(['hook_flags' => SWOOLE_HOOK_TCP]) 這種形式也可以設(shè)置協(xié)程化,它和 \Swoole\Runtime::enableCoroutine() 的效果一樣,但是它更像是 ini_set() ,也就是可以在程序執(zhí)行過(guò)程中動(dòng)態(tài)地調(diào)整。而 \Swoole\Runtime::enableCoroutine() 則最好是在服務(wù)啟動(dòng)后馬上就進(jìn)行全局配置,它也支持參數(shù),默認(rèn)就是 SWOOLE_HOOK_ALL 。參數(shù)內(nèi)容我們后面再說(shuō)。 在這個(gè)測(cè)試代碼中,創(chuàng)建 100 個(gè)協(xié)程,每個(gè)協(xié)程里面都去連接 redis 。注釋已經(jīng)標(biāo)明得很清楚了,它會(huì)在 connect() 的時(shí)候埋下勾子 Hook ,然后產(chǎn)生協(xié)程調(diào)度,也就是 yield() 和 resume() 連接完成后會(huì)再切換回來(lái)。同樣地,get() 的時(shí)候也會(huì)這樣。這就是用戶態(tài)多協(xié)程處理的最典型表現(xiàn)。 不難聯(lián)想到,PDO 相關(guān)的操作也是這樣的套路。 Hook信息對(duì)于 Swoole 來(lái)說(shuō),目前能夠 Hook 的內(nèi)容包括:
無(wú)法 Hook 的包括:
說(shuō)實(shí)話,大部分情況下是能夠覆蓋我們的業(yè)務(wù)場(chǎng)景了。如果有確實(shí)無(wú)法支持的,那么還是得靠我們自己去調(diào)度實(shí)現(xiàn)了。 各種參數(shù)上面可支持的擴(kuò)展列表,其實(shí)也對(duì)應(yīng)著一系列的參數(shù)。比如說(shuō) SWOOLE_HOOK_ALL 就是打開(kāi)全部的協(xié)程化支持。另外還可以單獨(dú)打開(kāi)下面這些,也可以通過(guò)或操作打開(kāi)某幾個(gè)。
每個(gè)標(biāo)簽對(duì)應(yīng)的內(nèi)容大家可以自己去官網(wǎng)上查閱,在這里我也就不做搬運(yùn)工了。 總結(jié)不容易不容易啊,各位,恭喜下自己吧,我們的協(xié)程篇也結(jié)束了。不知道大家有什么收獲,反正我是收獲滿滿。之前接觸過(guò) Java 中的線程,但對(duì)協(xié)程確實(shí)只是有那么一點(diǎn)點(diǎn)概念,沒(méi)有正式的好好學(xué)習(xí)過(guò)。經(jīng)過(guò)這次,不敢說(shuō)完全了解,但多少還是讓我對(duì)協(xié)程有了一個(gè)新的認(rèn)識(shí)。 至此,Swoole 基礎(chǔ)和核心進(jìn)階相關(guān)的內(nèi)容全部完成了,其實(shí)我們可以看到,在 Swoole 的開(kāi)發(fā),要轉(zhuǎn)變很多之間的開(kāi)發(fā)思想,同時(shí)也要清楚地知道進(jìn)程和協(xié)程相關(guān)的內(nèi)容,這些,其實(shí)也就是本系列最核心的內(nèi)容了。 接下來(lái),我們將繼續(xù)學(xué)習(xí)是將是 Swoole 的一些擴(kuò)展功能和知識(shí)點(diǎn),以及最后的框架方面的學(xué)習(xí),精彩內(nèi)容依然還是值得期待的,大家要堅(jiān)持下去哦! 測(cè)試代碼: https://github.com/zhangyue0503/swoole/blob/main/4.Swoole%E5%8D%8F%E7%A8%8B/source/4.8%E4%B8%80%E9%94%AE%E5%8D%8F%E7%A8%8B%E5%8C%96.php 參考文檔: https://wiki./#/runtime?id=sethookflags |
|
來(lái)自: 硬核項(xiàng)目經(jīng)理 > 《待分類》