中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

成都網(wǎng)站建設(shè)易維達(dá)好互聯(lián)網(wǎng)營(yíng)銷的特點(diǎn)

成都網(wǎng)站建設(shè)易維達(dá)好,互聯(lián)網(wǎng)營(yíng)銷的特點(diǎn),網(wǎng)站建設(shè)成本分析,宜黃縣建設(shè)局網(wǎng)站為何 Hyperf 能夠在兩個(gè)端口上監(jiān)聽 WebSocket 連接? 源碼角度來看,在配置了多個(gè) Servers 時(shí),實(shí)際上,只啟動(dòng)了一個(gè) Server 注:我之前接觸的代碼都是啟動(dòng)一個(gè)服務(wù)綁定一個(gè)端口,之前也看過 swoole 擴(kuò)展的文檔…

為何?Hyperf?能夠在兩個(gè)端口上監(jiān)聽?WebSocket?連接?

源碼角度來看,在配置了多個(gè)?Servers?時(shí),實(shí)際上,只啟動(dòng)了一個(gè)?Server

注:我之前接觸的代碼都是啟動(dòng)一個(gè)服務(wù)綁定一個(gè)端口,之前也看過 swoole 擴(kuò)展的文檔,但是沒留意服務(wù)和監(jiān)聽端口也是分離的,這啟發(fā)了我一種思維,代碼凡是能繼續(xù)拆分的,就繼續(xù)拆分,這樣代碼就會(huì)有更多的靈活,每個(gè)功能都能進(jìn)行擴(kuò)展,將服務(wù)和端口進(jìn)行拆分之后,就可以在一個(gè) Server 綁定多個(gè) Port,每個(gè) Port 又能有獨(dú)立的事件。

/*** @param Port[] $servers* @return Port[]*/
protected function sortServers(array $servers): array
{$sortServers = [];foreach ($servers as $server) {switch ($server->getType()) {case ServerInterface::SERVER_HTTP:$this->enableHttpServer = true;if (! $this->enableWebsocketServer) {array_unshift($sortServers, $server);} else {$sortServers[] = $server;}break;case ServerInterface::SERVER_WEBSOCKET:$this->enableWebsocketServer = true;array_unshift($sortServers, $server);break;default:$sortServers[] = $server;break;}}return $sortServers;
}

從源碼看,排在第一個(gè)的服務(wù)配置,會(huì)被創(chuàng)建服務(wù),之后都是增加監(jiān)聽

protected function initServers(ServerConfig $config)
{$servers = $this->sortServers($config->getServers());foreach ($servers as $server) {$name = $server->getName();$type = $server->getType();$host = $server->getHost();$port = $server->getPort();$sockType = $server->getSockType();$callbacks = $server->getCallbacks();if (! $this->server instanceof SwooleServer) {$this->server = $this->makeServer($type, $host, $port, $config->getMode(), $sockType);$callbacks = array_replace($this->defaultCallbacks(), $config->getCallbacks(), $callbacks);$this->registerSwooleEvents($this->server, $callbacks, $name);$this->server->set(array_replace($config->getSettings(), $server->getSettings()));ServerManager::add($name, [$type, current($this->server->ports)]);if (class_exists(BeforeMainServerStart::class)) {// Trigger BeforeMainServerStart event, this event only trigger once before main server start.$this->eventDispatcher->dispatch(new BeforeMainServerStart($this->server, $config->toArray()));}} else {/** @var bool|\Swoole\Server\Port $slaveServer */$slaveServer = $this->server->addlistener($host, $port, $sockType);if (! $slaveServer) {throw new \RuntimeException("Failed to listen server port [{$host}:{$port}]");}$server->getSettings() && $slaveServer->set(array_replace($config->getSettings(), $server->getSettings()));$this->registerSwooleEvents($slaveServer, $callbacks, $name);ServerManager::add($name, [$type, $slaveServer]);}// Trigger beforeStart event.if (isset($callbacks[Event::ON_BEFORE_START])) {[$class, $method] = $callbacks[Event::ON_BEFORE_START];if ($this->container->has($class)) {$this->container->get($class)->{$method}();}}if (class_exists(BeforeServerStart::class)) {// Trigger BeforeServerStart event.$this->eventDispatcher->dispatch(new BeforeServerStart($name));}}
}

從makeServer函數(shù)來看,如果服務(wù)中有SERVER_WEBSOCKET,則這個(gè)會(huì)被作為主服務(wù)啟動(dòng),new?SwooleWebSocketServer

protected function makeServer(int $type, string $host, int $port, int $mode, int $sockType): SwooleServer
{switch ($type) {case ServerInterface::SERVER_HTTP:return new SwooleHttpServer($host, $port, $mode, $sockType);case ServerInterface::SERVER_WEBSOCKET:return new SwooleWebSocketServer($host, $port, $mode, $sockType);case ServerInterface::SERVER_BASE:return new SwooleServer($host, $port, $mode, $sockType);}throw new RuntimeException('Server type is invalid.');
}

$this->registerSwooleEvents($this->server,?$callbacks,?$name);?這句代碼會(huì)將?Websocket?的各種事件都注冊(cè)進(jìn)去,于是主服務(wù)器擁有?websocket?的各種事件,而后?http?服務(wù)器掛載?9501?端口上,綁定了?onrequest?事件,但是如果有?websocket?連接9501?端口上時(shí),默認(rèn)該服務(wù)器是自動(dòng)開啟?websocket?自動(dòng)升級(jí)的,又因?yàn)楸O(jiān)聽?9501?端口綁定的主服務(wù)器是?WebSocketServer,因此,WebSocketServer?默認(rèn)的?onmessage,onopen事件就會(huì)被拿來用。

推測(cè),如果開啟?9503?WebSocket服務(wù)器,那么理論上用?WebSocket連接?9501?端口,應(yīng)該就是連接的?9503?的回調(diào)事件。如果不想讓?http?監(jiān)聽端口自動(dòng)開啟?websocket?協(xié)議,則將open_websocket_protocol=false

<?php
return [
// 這里省略了該文件的其它配置
'servers' => [['name' => 'http','type' => Server::SERVER_HTTP,'host' => '0.0.0.0','port' => 9501,'sock_type' => SWOOLE_SOCK_TCP,'callbacks' => [Event::ON_REQUEST => [Hyperf\HttpServer\Server::class,'onRequest'],],'settings' => ['open_websocket_protocol' => false,]],]];

關(guān)于很多SWOOLE中出現(xiàn)的常量來看,這些東西在執(zhí)行腳本時(shí),會(huì)被自動(dòng)設(shè)置好,通過實(shí)際代碼運(yùn)行發(fā)現(xiàn)

define('SWOOLE_HTTP2_ERROR_COMPRESSION_ERROR', 9);
define('SWOOLE_HTTP2_ERROR_CONNECT_ERROR', 10);
define('SWOOLE_HTTP2_ERROR_ENHANCE_YOUR_CALM', 11);
define('SWOOLE_HTTP2_ERROR_INADEQUATE_SECURITY', 12);
define('SWOOLE_BASE', 1);
define('SWOOLE_PROCESS', 2);
define('SWOOLE_IPC_UNSOCK', 1);
define('SWOOLE_IPC_MSGQUEUE', 2);
define('SWOOLE_IPC_PREEMPTIVE', 3);

以下,隨便設(shè)置的一個(gè)test.php中輸出SWOOLE_BASE,都能輸出1,我之前都以為這些常量是運(yùn)行時(shí)設(shè)置的呢,看來這種理解是錯(cuò)誤的。

<?php
echo SWOOLE_BASE."\n";
echo "hello\n";// 輸出
1
hello

Hyperf-skeleton?給的默認(rèn)配置就是進(jìn)程模式,這個(gè)竟然沒有發(fā)現(xiàn),這樣就比較明確了,使用的都是PROCESS模式,那么在websocket連接時(shí),所有的連接都是由Manager來控制

SWOOLE_PRECESS?和?SWOOLE_BASE?兩種模式

Server?的兩種運(yùn)行模式介紹

在?Swoole\Server?構(gòu)造函數(shù)的第三個(gè)參數(shù),可以填?2?個(gè)常量值?--?SWOOLE_BASE或?SWOOLE_PROCESS,下面將分別介紹這兩個(gè)模式的區(qū)別以及優(yōu)缺點(diǎn)

SWOOLE_PROCESS

SWOOLE_PROCESS?模式的?Server?所有客戶端的?TCP?連接都是和主進(jìn)程建立的,內(nèi)部實(shí)現(xiàn)比較復(fù)雜,用了大量的進(jìn)程間通信、進(jìn)程管理機(jī)制。適合業(yè)務(wù)邏輯非常復(fù)雜的場(chǎng)景。Swoole?提供了完善的進(jìn)程管理、內(nèi)存保護(hù)機(jī)制。?在業(yè)務(wù)邏輯非常復(fù)雜的情況下,也可以長(zhǎng)期穩(wěn)定運(yùn)行。

Swoole?在?Reactor線程中提供了?Buffer?的功能,可以應(yīng)對(duì)大量慢速連接和逐字節(jié)的惡意客戶端。

進(jìn)程模式的優(yōu)點(diǎn):

  • 連接與數(shù)據(jù)請(qǐng)求發(fā)送是分離的,不會(huì)因?yàn)槟承┻B接數(shù)據(jù)量大某些連接數(shù)據(jù)量小導(dǎo)致?Worker?進(jìn)程不均衡

  • Worker?進(jìn)程發(fā)生致命錯(cuò)誤時(shí),連接并不會(huì)被切斷

  • 可實(shí)現(xiàn)單連接并發(fā),僅保持少量?TCP?連接,請(qǐng)求可以并發(fā)地在多個(gè)?Worker?進(jìn)程中處理

進(jìn)程模式的缺點(diǎn):

  • 存在?2?次?IPC?的開銷,master?進(jìn)程與?worker?進(jìn)程需要使用?unixSocket進(jìn)行通信

  • SWOOLE_PROCESS?不支持?PHP?ZTS,在這種情況下只能使用?SWOOLE_BASE?或者設(shè)置?single_thread為?true

SWOOLE_BASE

SWOOLE_BASE?這種模式就是傳統(tǒng)的異步非阻塞?Server。與?Nginx?和?Node.js?等程序是完全一致的。

worker_num參數(shù)對(duì)于?BASE?模式仍然有效,會(huì)啟動(dòng)多個(gè)?Worker?進(jìn)程。

當(dāng)有?TCP?連接請(qǐng)求進(jìn)來的時(shí)候,所有的?Worker?進(jìn)程去爭(zhēng)搶這一個(gè)連接,并最終會(huì)有一個(gè)?worker?進(jìn)程成功直接和客戶端建立?TCP?連接,之后這個(gè)連接的所有數(shù)據(jù)收發(fā)直接和這個(gè)?worker?通訊,不經(jīng)過主進(jìn)程的?Reactor?線程轉(zhuǎn)發(fā)。

  • BASE?模式下沒有?Master?進(jìn)程的角色,只有?Manager進(jìn)程的角色。

  • 每個(gè)?Worker?進(jìn)程同時(shí)承擔(dān)了?SWOOLE_PROCESS模式下?Reactor線程和?Worker?進(jìn)程兩部分職責(zé)。

  • BASE?模式下?Manager?進(jìn)程是可選的,當(dāng)設(shè)置了?worker_num=1,并且沒有使用?Task?和?MaxRequest?特性時(shí),底層將直接創(chuàng)建一個(gè)單獨(dú)的?Worker?進(jìn)程,不創(chuàng)建?Manager?進(jìn)程

BASE?模式的優(yōu)點(diǎn):

  • BASE?模式?jīng)]有?IPC?開銷,性能更好

  • BASE?模式代碼更簡(jiǎn)單,不容易出錯(cuò)

BASE?模式的缺點(diǎn):

  • TCP?連接是在?Worker?進(jìn)程中維持的,所以當(dāng)某個(gè)?Worker?進(jìn)程掛掉時(shí),此?Worker?內(nèi)的所有連接都將被關(guān)閉

  • 少量?TCP?長(zhǎng)連接無法利用到所有?Worker?進(jìn)程

  • TCP?連接與?Worker?是綁定的,長(zhǎng)連接應(yīng)用中某些連接的數(shù)據(jù)量大,這些連接所在的?Worker?進(jìn)程負(fù)載會(huì)非常高。但某些連接數(shù)據(jù)量小,所以在?Worker?進(jìn)程的負(fù)載會(huì)非常低,不同的?Worker?進(jìn)程無法實(shí)現(xiàn)均衡。

  • 如果回調(diào)函數(shù)中有阻塞操作會(huì)導(dǎo)致?Server?退化為同步模式,此時(shí)容易導(dǎo)致?TCP?的?backlog隊(duì)列塞滿問題。

BASE?模式的適用場(chǎng)景:

如果客戶端連接之間不需要交互,可以使用?BASE?模式。如?Memcache、HTTP?服務(wù)器等。

BASE?模式的限制:

在?BASE?模式下,Server?方法除了?send和?close以外,其他的方法都不支持跨進(jìn)程執(zhí)行。

Reactor?線程和?Worker?進(jìn)程

Reactor?線程

  • Reactor?線程是在?Master?進(jìn)程中創(chuàng)建的線程

  • 負(fù)責(zé)維護(hù)客戶端?TCP?連接、處理網(wǎng)絡(luò)?IO、處理協(xié)議、收發(fā)數(shù)據(jù)

  • 不執(zhí)行任何?PHP?代碼

  • 將?TCP?客戶端發(fā)來的數(shù)據(jù)緩沖、拼接、拆分成完整的一個(gè)請(qǐng)求數(shù)據(jù)包

Worker?進(jìn)程

  • 接受由?Reactor?線程投遞的請(qǐng)求數(shù)據(jù)包,并執(zhí)行?PHP?回調(diào)函數(shù)處理數(shù)據(jù)

  • 生成響應(yīng)數(shù)據(jù)并發(fā)給?Reactor?線程,由?Reactor?線程發(fā)送給?TCP?客戶端

  • 可以是異步非阻塞模式,也可以是同步阻塞模式

  • Worker?以多進(jìn)程的方式運(yùn)行

他們之間的關(guān)系可以理解為?Reactor?就是?nginx,Worker?就是?PHP-FPM。Reactor?線程異步并行地處理網(wǎng)絡(luò)請(qǐng)求,然后再轉(zhuǎn)發(fā)給?Worker?進(jìn)程中去處理。Reactor?和?Worker?間通過?unixSocket進(jìn)行通信。

在?PHP-FPM?的應(yīng)用中,經(jīng)常會(huì)將一個(gè)任務(wù)異步投遞到?Redis?等隊(duì)列中,并在后臺(tái)啟動(dòng)一些?PHP?進(jìn)程異步地處理這些任務(wù)。Swoole?提供的?TaskWorker?是一套更完整的方案,將任務(wù)的投遞、隊(duì)列、PHP?任務(wù)處理進(jìn)程管理合為一體。通過底層提供的?API?可以非常簡(jiǎn)單地實(shí)現(xiàn)異步任務(wù)的處理。另外?TaskWorker?還可以在任務(wù)執(zhí)行完成后,再返回一個(gè)結(jié)果反饋到?Worker。

Swoole?的?Reactor、Worker、TaskWorker?之間可以緊密的結(jié)合起來,提供更高級(jí)的使用方式。

一個(gè)更通俗的比喻,假設(shè)?Server?就是一個(gè)工廠,那?Reactor?就是銷售,接受客戶訂單。而?Worker?就是工人,當(dāng)銷售接到訂單后,Worker?去工作生產(chǎn)出客戶要的東西。而?TaskWorker?可以理解為行政人員,可以幫助?Worker?干些雜事,讓?Worker?專心工作。

結(jié)論

  1. SWOOLE_PROCESS 模式下,Websocket?的連接對(duì)象都是由 Server 來控制,創(chuàng)建一個(gè) Reactor 后,將該連接交付給 Reactor 來管理,Reactor 會(huì)將請(qǐng)求分配給?Worker?處理,Worker 處理完后,再把消息發(fā)給Server,Server 將消息壓入隊(duì)列等具體的 Reactor 發(fā)送出去

  2. hyperf 中有一處進(jìn)程間通信,目前還不清楚,這里為何要向其他進(jìn)程求助,以及其他進(jìn)程監(jiān)聽到消息后會(huì)不會(huì)多發(fā)

    1. 開發(fā)者說,如果是 SWOOLE_PROCESS模式下不會(huì)觸發(fā)讓其他 Worker 發(fā)送的機(jī)制,只有 SWOOLE_BASE 模式下,每個(gè)鏈接交給每個(gè) Worker 單獨(dú)處理時(shí),才需要在多個(gè) Worker 協(xié)作處理,因?yàn)槊總€(gè) Worker 爭(zhēng)搶到的連接都是隔離的,所以不會(huì)出現(xiàn)發(fā)送多個(gè)的情況

  3. 上面 2 給了一種分布式 websocket 構(gòu)建方式,采用這種多進(jìn)程的方式就能讓多臺(tái)服務(wù)器協(xié)作提供長(zhǎng)連接服務(wù),保證千級(jí)萬(wàn)級(jí)用戶的接入量

?

?下面這段代碼是來自onPipeMessage 監(jiān)聽器的,意味著其他 worker 收到后,判斷是在自己進(jìn)程上的連接就執(zhí)行

?

?

?

http://www.risenshineclean.com/news/64023.html

相關(guān)文章:

  • 做公司網(wǎng)站注意事項(xiàng)網(wǎng)站推廣優(yōu)化平臺(tái)
  • 怎么按照屏幕比例做網(wǎng)站適應(yīng)安裝百度一下
  • 網(wǎng)頁(yè)靠什么賺錢南京seo網(wǎng)絡(luò)優(yōu)化公司
  • 用dw做網(wǎng)站結(jié)構(gòu)圖域名查詢 站長(zhǎng)查詢
  • 個(gè)人可以做商城網(wǎng)站嗎優(yōu)秀品牌策劃方案
  • 手機(jī)網(wǎng)站做指向推廣教程
  • 建設(shè)黨史網(wǎng)站的意義在線智能識(shí)圖
  • 比價(jià)網(wǎng)站源碼整站程序百度上做優(yōu)化
  • h5可以做網(wǎng)站么免費(fèi)推廣途徑
  • 中小企業(yè)服務(wù)平臺(tái)企業(yè)seo外包公司
  • 公司網(wǎng)站建設(shè)服務(wù)大數(shù)據(jù)獲客系統(tǒng)
  • 萊蕪公司做網(wǎng)站外鏈相冊(cè)
  • wordpress 添加 聯(lián)系我們網(wǎng)站優(yōu)化方案
  • 建設(shè)外貿(mào)商城網(wǎng)站制作怎樣在百度上發(fā)布廣告
  • 有贊做網(wǎng)站360推廣
  • 東莞做網(wǎng)站一年費(fèi)用網(wǎng)站優(yōu)化seo培
  • 網(wǎng)站跳出率一般多少公司網(wǎng)站設(shè)計(jì)公司
  • 網(wǎng)站建設(shè)的合同書愛站小工具計(jì)算器
  • iis網(wǎng)站asp.net部署投放廣告找什么平臺(tái)
  • 登錄功能網(wǎng)站怎么做的搜索引擎優(yōu)化是什么意思啊
  • 網(wǎng)站自適應(yīng)手機(jī)怎么一鍵生成網(wǎng)頁(yè)
  • 重慶疫情最新消息今天seo在線論壇
  • 深圳橫崗做網(wǎng)站的推廣網(wǎng)上國(guó)網(wǎng)
  • wordpress更改網(wǎng)站url無法訪問軟文推廣營(yíng)銷服務(wù)平臺(tái)
  • 建行網(wǎng)站會(huì)員重慶seo團(tuán)隊(duì)
  • 做響應(yīng)式的網(wǎng)站seo教程視頻論壇
  • 網(wǎng)站框架模板app推廣賺錢
  • 怎么做重慶時(shí)時(shí)彩網(wǎng)站代理今日國(guó)內(nèi)新聞大事
  • 網(wǎng)站建設(shè)價(jià)格熱線游戲推廣員是違法的嗎
  • 用php做網(wǎng)站要用什么軟件萬(wàn)網(wǎng)域名續(xù)費(fèi)