真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程

這篇文章給大家介紹如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比阿壩州網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式阿壩州網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋阿壩州地區(qū)。費(fèi)用合理售后完善,10年實(shí)體公司更值得信賴。

目前的Swoole 內(nèi)置了豐富的協(xié)程組件供開(kāi)發(fā)者直接調(diào)用以便快速實(shí)現(xiàn)異步非阻塞的并發(fā)編程,省去了開(kāi)發(fā)者自己實(shí)現(xiàn)相應(yīng)底層代碼的麻煩:

TCP/UDP Client:Swoole\Coroutine\Client
TCP/UDP Server:Swoole\Coroutine\Server
HTTP/WebSocket Client:Swoole\Coroutine\HTTP\Client
HTTP/WebSocket Server:Swoole\Coroutine\HTTP\Server
HTTP2 Client:Swoole\Coroutine\HTTP2\Client
redis Client:Swoole\Coroutine\Redis
MySQL Client:Swoole\Coroutine\MySQL
PostgreSQL Client:Swoole\Coroutine\PostgreSQL

在協(xié)程 Server 中使用對(duì)應(yīng)的協(xié)程版 Client 來(lái)實(shí)現(xiàn)全異步 Server,同時(shí) Swoole 提供了協(xié)程工具集:Swoole\Coroutine,提供了獲取當(dāng)前協(xié)程ID、反射調(diào)用等能力。

通過(guò) setDefer 機(jī)制實(shí)現(xiàn)并發(fā)編程

我們以 Redis 和 MySQL 客戶端請(qǐng)求為例,使用上述 Swoole\Coroutine\Redis 和 Swoole\Coroutine\MySQL 組件,可以實(shí)現(xiàn)異步 Redis 和 MySQL 客戶端:

on('Request', function ($request, $response) {var_dump(time());$mysql = new Swoole\Coroutine\MySQL();$mysql->connect(['host' => '127.0.0.1','user' => 'root','password' => 'root','database' => 'laravel58',]);$mysql->setDefer();$mysql->query('select sleep(3)');var_dump(time());$redis1 = new Swoole\Coroutine\Redis();$redis1->connect('127.0.0.1', 6379);$redis1->setDefer();$redis1->set('hello', 'world');var_dump(time());$redis2 = new Swoole\Coroutine\Redis();$redis2->connect('127.0.0.1', 6379);$redis2->setDefer();$redis2->get('hello');$result1 = $mysql->recv();$result2 = $redis2->recv();var_dump($result1, $result2, time());$response->end('Request Finish: ' . time());});$server->start();

由于 Swoole 會(huì)在 TCP Server 和 HTTP Server 回調(diào)函數(shù)中會(huì)自動(dòng)開(kāi)啟協(xié)程,所以不需要顯式通過(guò) go 關(guān)鍵字啟動(dòng)協(xié)程,然后我們可以在回調(diào)函數(shù)中使用 MySQL 和 Redis 客戶端協(xié)程組件發(fā)起請(qǐng)求。

要理解上述代碼的運(yùn)行原理,需要先了解協(xié)程的 setDefer 機(jī)制,絕大部分協(xié)程組件都支持 setDefer,該機(jī)制可以將請(qǐng)求響應(yīng)式的接口拆分為兩個(gè)步驟:先發(fā)送數(shù)據(jù), 再并發(fā)收取響應(yīng)結(jié)果。

由于大多數(shù)情況下,「建立連接和發(fā)送數(shù)據(jù)的耗時(shí)」相較于「等待響應(yīng)的耗時(shí)」來(lái)說(shuō)可以忽略不計(jì), 所以可以簡(jiǎn)單理解為 defer 模式下, 多個(gè)客戶端的請(qǐng)求響應(yīng)是并發(fā)的(實(shí)際上只有接收響應(yīng)是并發(fā)的,建立連接和發(fā)送請(qǐng)求是串行的)。

以上述代碼為例,設(shè)置 setDefer(true) 后,通過(guò) Redis 或 MySQL 客戶端發(fā)起請(qǐng)求,將不再等待服務(wù)器返回結(jié)果,而是在發(fā)送請(qǐng)求之后,立即返回 true。在此之后可以繼續(xù)發(fā)起其他 Redis、MySQL 請(qǐng)求,最后再使用 recv() 方法接收響應(yīng)內(nèi)容。

我們將上述代碼保存到 coroutine/http.php,然后在終端啟動(dòng)這個(gè) HTTP 服務(wù)端:

php coroutine/http.php

接下來(lái),在 Postman 中對(duì)服務(wù)端發(fā)起請(qǐng)求,會(huì)在等待幾秒后看到返回的響應(yīng)內(nèi)容:

如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程

前三個(gè)時(shí)間分別是 mysql、redis1、redis2 三個(gè)客戶端發(fā)起請(qǐng)求的時(shí)間,可以看到,盡管 mysql 中會(huì)休眠 3 秒,但是通過(guò) defer 機(jī)制實(shí)現(xiàn)了三個(gè)請(qǐng)求的并發(fā)執(zhí)行。

通過(guò)子協(xié)程+通道實(shí)現(xiàn)并發(fā)編程

除了 setDefer 機(jī)制外,Swoole 還支持通過(guò)子協(xié)程+通道實(shí)現(xiàn)并發(fā)編程,下面我們通過(guò)子協(xié)程+通道的方式來(lái)改寫(xiě)上面的代碼實(shí)現(xiàn):

on('Request', function ($request, $response) {$channel = new \Swoole\Coroutine\Channel(3);go(function () use ($channel) {var_dump(time());$mysql = new Swoole\Coroutine\MySQL();$mysql->connect(['host' => '127.0.0.1','user' => 'root','password' => 'root','database' => 'laravel58',]);$result = $mysql->query('select sleep(3)');$channel->push($result);});go(function () use ($channel) {var_dump(time());$redis1 = new Swoole\Coroutine\Redis();$redis1->connect('127.0.0.1', 6379);$result = $redis1->set('hello', 'world');$channel->push($result);});go(function () use ($channel) {var_dump(time());$redis2 = new Swoole\Coroutine\Redis();$redis2->connect('127.0.0.1', 6379);$result = $redis2->get('hello');$channel->push($result);});$results = [];for ($i = 0; $i < 3; $i++) {$results[] = $channel->pop();}$response->end(json_encode(['data' => $results,'time' => time()]));});$server->start();

我們將 MySQL 和 Redis 客戶端連接請(qǐng)求調(diào)用改寫(xiě)為通過(guò)三個(gè)子協(xié)程實(shí)現(xiàn),同時(shí)去掉 setDefer 設(shè)置,因?yàn)檫@三個(gè)子協(xié)程已經(jīng)是并發(fā)調(diào)用了,此外,由于三個(gè)子協(xié)程之間數(shù)據(jù)是相互隔離的,所以我們通過(guò) Swoole\Coroutine\Channel (即通道)實(shí)現(xiàn)協(xié)程之間的數(shù)據(jù)共享和通信,初始化其緩沖空間為 3,然后通過(guò) use 方式將其引入到子協(xié)程中,把響應(yīng)結(jié)果通過(guò) push 方法放到 Channel 里面,接下來(lái)在服務(wù)端 onRequest 回調(diào)函數(shù)末尾通過(guò)一個(gè)循環(huán)將 Channel 中的數(shù)據(jù)通過(guò) pop 方法依次取出來(lái)放到數(shù)組 $results 中,最后通過(guò) $response->end() 方法將結(jié)果以 JSON 格式返回給客戶端。

我們將上述代碼保存到 coroutine/http2.php,然后在終端通過(guò)如下命令啟動(dòng)這個(gè)新的 HTTP 服務(wù)端:

php coroutine/http2.php

還是在 Postman 中請(qǐng)求這個(gè)服務(wù)端,將響應(yīng)格式調(diào)整為 JSON,會(huì)看到結(jié)果如下:

如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程

由于 MySQL 請(qǐng)求執(zhí)行耗時(shí)最長(zhǎng),所以位置最靠后。在啟動(dòng)服務(wù)器的終端,可以看到打印出的三個(gè)客戶端請(qǐng)求時(shí)間,完全一致,說(shuō)明它們是并發(fā)執(zhí)行的:

如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程

顯然,通過(guò)子協(xié)程 + 通道還可以很方便的實(shí)現(xiàn) Redis、MySQL 連接池。

關(guān)于如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。


網(wǎng)站標(biāo)題:如何通過(guò)swoole協(xié)程實(shí)現(xiàn)并發(fā)編程
本文鏈接:http://weahome.cn/article/gdjisd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部