日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

詳解PHP Swoole長連接常見問題

瀏覽:242日期:2022-09-07 10:53:49
目錄連接失效問題如何解決如何維持長連接結(jié)論連接失效問題

例子

其中,Redis常見的報錯就是:

配置項:timeout

報錯信息:

Error while reading line from the server

Redis可以配置如果客戶端經(jīng)過多少秒還不給Redis服務(wù)器發(fā)送數(shù)據(jù),那么就會把連接close掉。

MySQL常見的報錯:

配置項:wait_timeout & interactive_timeout

報錯信息:

has gone away

和Redis服務(wù)器一樣,MySQL也會定時的去清理掉沒用的連接。

如何解決

1、用的時候進行重連 。優(yōu)點是簡單,缺點是面臨短連接的問題。

2、定時發(fā)送心跳維持連接(推薦)。

如何維持長連接

tcp協(xié)議中實現(xiàn)的tcp_keepalive

操作系統(tǒng)底層提供了一組tcp的keepalive配置:

tcp_keepalive_time (integer; default: 7200; since Linux 2.2)The number of seconds a connection needs to be idle before TCPbegins sending out keep-alive probes. Keep-alives are sent onlywhen the SO_KEEPALIVE socket option is enabled. The defaultvalue is 7200 seconds (2 hours). An idle connection isterminated after approximately an additional 11 minutes (9probes an interval of 75 seconds apart) when keep-alive isenabled.Note that underlying connection tracking mechanisms andapplication timeouts may be much shorter.tcp_keepalive_intvl (integer; default: 75; since Linux 2.4)The number of seconds between TCP keep-alive probes.tcp_keepalive_probes (integer; default: 9; since Linux 2.2)The maximum number of TCP keep-alive probes to send beforegiving up and killing the connection if no response is obtainedfrom the other end.8

Swoole底層把這些配置開放出來了,例如:

?php$server = new SwooleServer(’127.0.0.1’, 6666, SWOOLE_PROCESS);$server->set([’worker_num’ => 1,’open_tcp_keepalive’ => 1,’tcp_keepidle’ => 4, // 對應(yīng)tcp_keepalive_time’tcp_keepinterval’ => 1, // 對應(yīng)tcp_keepalive_intvl’tcp_keepcount’ => 5, // 對應(yīng)tcp_keepalive_probes]);

其中:

’open_tcp_keepalive’ => 1, // 總開關(guān),用來開啟tcp_keepalive’tcp_keepidle’ => 4, // 4s沒有數(shù)據(jù)傳輸就進行檢測// 檢測的策略如下:’tcp_keepinterval’ => 1, // 1s探測一次,即每隔1s給客戶端發(fā)一個包(然后客戶端可能會回一個ack的包,如果服務(wù)端收到了這個ack包,那么說明這個連接是活著的)’tcp_keepcount’ => 5, // 探測的次數(shù),超過5次后客戶端還沒有回ack包,那么close此連接

我們來實戰(zhàn)測試體驗一下,服務(wù)端腳本如下:

<?php$server = new SwooleServer(’127.0.0.1’, 6666, SWOOLE_PROCESS);$server->set([’worker_num’ => 1,’open_tcp_keepalive’ => 1, // 開啟tcp_keepalive’tcp_keepidle’ => 4, // 4s沒有數(shù)據(jù)傳輸就進行檢測’tcp_keepinterval’ => 1, // 1s探測一次’tcp_keepcount’ => 5, // 探測的次數(shù),超過5次后還沒有回包close此連接]);$server->on(’connect’, function ($server, $fd) {var_dump('Client: Connect $fd');});$server->on(’receive’, function ($server, $fd, $reactor_id, $data) {var_dump($data);});$server->on(’close’, function ($server, $fd) {var_dump('close fd $fd');});$server->start();

我們啟動這個服務(wù)器:

~/codeDir/phpCode/hyperf-skeleton # php server.php

然后通過tcpdump進行抓包:

~/codeDir/phpCode/hyperf-skeleton # tcpdump -i lo port 6666tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

我們此時正在監(jiān)聽lo上的6666端口的數(shù)據(jù)包。

然后我們用客戶端去連接它:

~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666

此時服務(wù)端會打印出消息:

~/codeDir/phpCode/hyperf-skeleton # php server.php

string(17) 'Client: Connect 1'

tcpdump的輸出信息如下:

01:48:40.178439 IP localhost.33933 > localhost.6666: Flags [S], seq 43162537, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 0,nop,wscale 7], length 0

01:48:40.178484 IP localhost.6666 > localhost.33933: Flags [S.], seq 1327460565, ack 43162538, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 9833698,nop,wscale 7], length 0

01:48:40.178519 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9833698 ecr 9833698], length 0

01:48:44.229926 IP localhost.6666 > localhost.33933: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0

01:48:44.229951 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0

01:48:44.229926 IP localhost.6666 > localhost.33933: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0

01:48:44.229951 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0

01:48:44.229926 IP localhost.6666 > localhost.33933: Flags [.], ack 1, win 342, options [nop,nop,TS val 9834104 ecr 9833698], length 0

// 省略了其他的輸出

我們會發(fā)現(xiàn)最開始的時候,會打印三次握手的包:

01:48:40.178439 IP localhost.33933 > localhost.6666: Flags [S], seq 43162537, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 0,nop,wscale 7], length 0

01:48:40.178484 IP localhost.6666 > localhost.33933: Flags [S.], seq 1327460565, ack 43162538, win 43690, options [mss 65495,sackOK,TS val 9833698 ecr 9833698,nop,wscale 7], length 0

01:48:40.178519 IP localhost.33933 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9833698 ecr 9833698], length 0

然后,停留了4s沒有任何包的輸出。

之后,每隔1s左右就會打印出一組:

01:52:54.359341 IP localhost.6666 > localhost.43101: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9858736], length 0

01:52:54.359377 IP localhost.43101 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9855887], length 0

其實這就是我們配置的策略:

’tcp_keepinterval’ => 1, // 1s探測一次’tcp_keepcount’ => 5, // 探測的次數(shù),超過5次后還沒有回包close此連接

因為我們操作系統(tǒng)底層會自動的給客戶端回ack,所以這個連接不會在5次探測后被關(guān)閉。操作系統(tǒng)底層會持續(xù)不斷的發(fā)送這樣的一組包:

01:52:54.359341 IP localhost.6666 > localhost.43101: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9858736], length 0

01:52:54.359377 IP localhost.43101 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 9859144 ecr 9855887], length 0

如果我們要測試5次探測后關(guān)閉這個連接,可以禁掉6666端口的包:

~/codeDir/phpCode/hyperf-skeleton # iptables -A INPUT -p tcp --dport 6666 -j DROP

這樣會把所有從6666端口進來的包給禁掉,自然,服務(wù)器就接收不到從客戶端那一邊發(fā)來的ack包了。

然后服務(wù)器過5秒就會打印出close(服務(wù)端主動的調(diào)用了close方法,給客戶端發(fā)送了FIN包):

~/codeDir/phpCode/hyperf-skeleton # php server.php

string(17) 'Client: Connect 1'

string(10) 'close fd 1'

我們恢復(fù)一下iptables的規(guī)則:

~/codeDir/phpCode # iptables -D INPUT -p tcp -m tcp --dport 6666 -j DROP

即把我們設(shè)置的規(guī)則給刪除了。

通過tcp_keepalive的方式實現(xiàn)心跳的功能,優(yōu)點是簡單,不要寫代碼就可以完成這個功能,并且發(fā)送的心跳包小。缺點是依賴于系統(tǒng)的網(wǎng)絡(luò)環(huán)境,必須保證服務(wù)器和客戶端都實現(xiàn)了這樣的功能,需要客戶端配合發(fā)心跳包。還有一個更為嚴(yán)重的缺點是如果客戶端和服務(wù)器不是直連的,而是通過代理來進行連接的,例如socks5代理,它只會轉(zhuǎn)發(fā)應(yīng)用層的包,不會轉(zhuǎn)發(fā)更為底層的tcp探測包,那這個心跳功能就失效了。

所以,Swoole就提供了其他的解決方案,一組檢測死連接的配置。

’heartbeat_check_interval’ => 1, // 1s探測一次’heartbeat_idle_time’ => 5, // 5s未發(fā)送數(shù)據(jù)包就close此連接

swoole實現(xiàn)的heartbeat

我們來測試一下:

<?php$server = new SwooleServer(’127.0.0.1’, 6666, SWOOLE_PROCESS);$server->set([’worker_num’ => 1,’heartbeat_check_interval’ => 1, // 1s探測一次’heartbeat_idle_time’ => 5, // 5s未發(fā)送數(shù)據(jù)包就close此連接]);$server->on(’connect’, function ($server, $fd) {var_dump('Client: Connect $fd');});$server->on(’receive’, function ($server, $fd, $reactor_id, $data) {var_dump($data);});$server->on(’close’, function ($server, $fd) {var_dump('close fd $fd');});$server->start();

然后啟動服務(wù)器:

~/codeDir/phpCode/hyperf-skeleton # php server.php

然后啟動tcpdump:

~/codeDir/phpCode # tcpdump -i lo port 6666

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

然后再啟動客戶端:

~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666

此時服務(wù)器端打印:

~/codeDir/phpCode/hyperf-skeleton # php server.php

string(17) 'Client: Connect 1'

然后tcpdump打印:

02:48:32.516093 IP localhost.42123 > localhost.6666: Flags [S], seq 1088388248, win 43690, options [mss 65495,sackOK,TS val 10193342 ecr 0,nop,wscale 7], length 0

02:48:32.516133 IP localhost.6666 > localhost.42123: Flags [S.], seq 80508236, ack 1088388249, win 43690, options [mss 65495,sackOK,TS val 10193342 ecr 10193342,nop,wscale 7], length 0

02:48:32.516156 IP localhost.42123 > localhost.6666: Flags [.], ack 1, win 342, options [nop,nop,TS val 10193342 ecr 10193342], length 0

這是三次握手信息。

然后過了5s后,tcpdump會打印出:

02:48:36.985027 IP localhost.6666 > localhost.42123: Flags [F.], seq 1, ack 1, win 342, options [nop,nop,TS val 10193789 ecr 10193342], length 0

02:48:36.992172 IP localhost.42123 > localhost.6666: Flags [.], ack 2, win 342, options [nop,nop,TS val 10193790 ecr 10193789], length 0

也就是服務(wù)端發(fā)送了FIN包。因為客戶端沒有發(fā)送數(shù)據(jù),所以Swoole關(guān)閉了連接。

然后服務(wù)器端會打印:

~/codeDir/phpCode/hyperf-skeleton # php server.php

string(17) 'Client: Connect 1'

string(10) 'close fd 1'

所以,heartbeat和tcp keepalive還是有一定的區(qū)別的,tcp keepalive有保活連接的功能,但是heartbeat存粹是檢測沒有數(shù)據(jù)的連接,然后關(guān)閉它,并且只可以在服務(wù)端這邊配置,如果需要保活,也可以讓客戶端配合發(fā)送心跳。

如果我們不想讓服務(wù)端close掉連接,那么就得在應(yīng)用層里面不斷的發(fā)送數(shù)據(jù)包來進行保活,例如我在nc客戶端里面不斷的發(fā)送包:

~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666

ping

ping

ping

ping

ping

ping

ping

ping

ping

我發(fā)送了9個ping包給服務(wù)器,tcpdump的輸出如下:

// 省略了三次握手的包

02:57:53.697363 IP localhost.44195 > localhost.6666: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 10249525 ecr 10249307], length 5

02:57:53.697390 IP localhost.6666 > localhost.44195: Flags [.], ack 6, win 342, options [nop,nop,TS val 10249525 ecr 10249525], length 0

02:57:55.309532 IP localhost.44195 > localhost.6666: Flags [P.], seq 6:11, ack 1, win 342, options [nop,nop,TS val 10249686 ecr 10249525], length 5

02:57:55.309576 IP localhost.6666 > localhost.44195: Flags [.], ack 11, win 342, options [nop,nop,TS val 10249686 ecr 10249686], length 0

02:57:58.395206 IP localhost.44195 > localhost.6666: Flags [P.], seq 11:16, ack 1, win 342, options [nop,nop,TS val 10249994 ecr 10249686], length 5

02:57:58.395239 IP localhost.6666 > localhost.44195: Flags [.], ack 16, win 342, options [nop,nop,TS val 10249994 ecr 10249994], length 0

02:58:01.858094 IP localhost.44195 > localhost.6666: Flags [P.], seq 16:21, ack 1, win 342, options [nop,nop,TS val 10250341 ecr 10249994], length 5

02:58:01.858126 IP localhost.6666 > localhost.44195: Flags [.], ack 21, win 342, options [nop,nop,TS val 10250341 ecr 10250341], length 0

02:58:04.132584 IP localhost.44195 > localhost.6666: Flags [P.], seq 21:26, ack 1, win 342, options [nop,nop,TS val 10250568 ecr 10250341], length 5

02:58:04.132609 IP localhost.6666 > localhost.44195: Flags [.], ack 26, win 342, options [nop,nop,TS val 10250568 ecr 10250568], length 0

02:58:05.895704 IP localhost.44195 > localhost.6666: Flags [P.], seq 26:31, ack 1, win 342, options [nop,nop,TS val 10250744 ecr 10250568], length 5

02:58:05.895728 IP localhost.6666 > localhost.44195: Flags [.], ack 31, win 342, options [nop,nop,TS val 10250744 ecr 10250744], length 0

02:58:07.150265 IP localhost.44195 > localhost.6666: Flags [P.], seq 31:36, ack 1, win 342, options [nop,nop,TS val 10250870 ecr 10250744], length 5

02:58:07.150288 IP localhost.6666 > localhost.44195: Flags [.], ack 36, win 342, options [nop,nop,TS val 10250870 ecr 10250870], length 0

02:58:08.349124 IP localhost.44195 > localhost.6666: Flags [P.], seq 36:41, ack 1, win 342, options [nop,nop,TS val 10250990 ecr 10250870], length 5

02:58:08.349156 IP localhost.6666 > localhost.44195: Flags [.], ack 41, win 342, options [nop,nop,TS val 10250990 ecr 10250990], length 0

02:58:09.906223 IP localhost.44195 > localhost.6666: Flags [P.], seq 41:46, ack 1, win 342, options [nop,nop,TS val 10251145 ecr 10250990], length 5

02:58:09.906247 IP localhost.6666 > localhost.44195: Flags [.], ack 46, win 342, options [nop,nop,TS val 10251145 ecr 10251145], length 0

有9組數(shù)據(jù)包的發(fā)送。(這里的Flags [P.]代表Push的含義)

此時服務(wù)器還沒有close掉連接,實現(xiàn)了客戶端保活連接的功能。然后我們停止發(fā)送ping,過了5秒后tcpdump就會輸出一組:

02:58:14.811761 IP localhost.6666 > localhost.44195: Flags [F.], seq 1, ack 46, win 342, options [nop,nop,TS val 10251636 ecr 10251145], length 002:58:14.816420 IP localhost.44195 > localhost.6666: Flags [.], ack 2, win 342, options [nop,nop,TS val 10251637 ecr 10251636], length 0服務(wù)端那邊發(fā)送了FIN包,說明服務(wù)端close掉了連接。服務(wù)端的輸出如下:

~/codeDir/phpCode/hyperf-skeleton # php server.php

string(17) 'Client: Connect 1'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(5) 'ping

'

string(10) 'close fd 1'

然后我們在客戶端那邊ctrl + c來關(guān)閉連接:

~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666

ping

ping

ping

ping

ping

ping

ping

ping

ping

^Cpunt!

~/codeDir/phpCode/hyperf-skeleton #

此時,tcpdump的輸出如下:

03:03:02.257667 IP localhost.44195 > localhost.6666: Flags [F.], seq 46, ack 2, win 342, options [nop,nop,TS val 10280414 ecr 10251636], length 0

03:03:02.257734 IP localhost.6666 > localhost.44195: Flags [R], seq 2678621620, win 0, length 0

應(yīng)用層心跳

1、制定ping/pong協(xié)議(mysql等自帶ping協(xié)議)

2、客戶端靈活的發(fā)送ping心跳包

3、服務(wù)端OnRecive檢查可用性回復(fù)pong

例如:

$server->on(’receive’, function (SwooleServer $server, $fd, $reactor_id, $data){if ($data == ’ping’){checkDB();checkServiceA();checkRedis();$server->send(’pong’);}});結(jié)論

1、tcp的keepalive最簡單,但是有兼容性問題,不夠靈活

2、swoole提供的keepalive最實用,但是需要客戶端配合,復(fù)雜度適中

3、應(yīng)用層的keepalive最靈活但是最麻煩

以上就是詳解PHP Swoole長連接常見問題的詳細(xì)內(nèi)容,更多關(guān)于PHP Swoole長連接常見問題的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: PHP
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久精品高清| 日韩av影院| 一区二区不卡| 国产精品88久久久久久| 欧美va天堂在线| 婷婷国产精品| 婷婷国产精品| 视频一区二区三区在线| 免费看精品久久片| 国产综合色产| 免费精品国产| 欧美天堂亚洲电影院在线观看| 亚洲黄色免费av| 欧美日本不卡高清| 国产一区一一区高清不卡| 久久一区精品| 日韩激情视频网站| 亚洲欧美日韩专区| 日韩精品一区二区三区中文| 美女国产精品| 精品亚洲a∨一区二区三区18| 欧美91精品| 风间由美中文字幕在线看视频国产欧美| 激情亚洲影院在线观看| 91精品韩国| 午夜国产精品视频| 色狠狠一区二区三区| 国产精品久久久久久久久免费高清 | 亚洲精品91| 亚洲精品黄色| 麻豆91小视频| 欧美sss在线视频| 天堂成人免费av电影一区| 青青国产91久久久久久| 国产aⅴ精品一区二区四区| 中文字幕人成乱码在线观看| 欧美 日韩 国产一区二区在线视频| 亚洲综合丁香| 国产精品片aa在线观看| 电影天堂国产精品| 亚洲欧美久久精品| 国产成人久久| 在线亚洲欧美| 国产剧情在线观看一区| 久久久精品网| 国产偷自视频区视频一区二区| 日韩欧美在线精品| 中文字幕成在线观看| 日韩在线观看一区二区| 欧美精品福利| 9999国产精品| 午夜在线精品| 麻豆精品久久| 天堂成人国产精品一区| 美女免费视频一区| 国产高清久久| 久久激情五月婷婷| 久久久精品日韩| 日韩欧美中文字幕电影 | 97精品中文字幕| 日韩在线观看一区二区| 精品黄色一级片| 久久精品91| 日韩欧美美女在线观看| 福利在线免费视频| 亚洲三级在线| 国产一区二区三区不卡av | 亚洲高清激情| 日韩一区网站| 激情欧美国产欧美| 99久久精品网站| 亚洲精品婷婷| 石原莉奈一区二区三区在线观看| 国产99亚洲| 六月婷婷综合| 国产精品嫩草99av在线| 91久久久久| 欧美日韩精品一本二本三本 | 7m精品国产导航在线| 亚洲欧洲一区二区天堂久久| 欧美三区四区| 福利视频一区| 日韩一区三区| 国产在线观看91一区二区三区| 亚洲国内精品| 精品视频免费| 日韩精品欧美大片| 福利在线一区| 亚洲精品女人| 午夜日本精品| 日韩高清欧美| 国产日韩免费| av亚洲在线观看| 日韩成人a**站| 7777精品| 久久亚洲影院| 1024精品久久久久久久久| 日韩在线网址| 国产va在线视频| 99久久激情| 亚洲精品综合| 免费欧美一区| 性色一区二区| 日本a级不卡| 久久男女视频| 爽好多水快深点欧美视频| 欧美日韩国产免费观看视频| 国产精品一区二区av交换| 伊人久久视频| 国产一区二区中文| 国产精品一二| 天堂va在线高清一区| 欧美日韩日本国产亚洲在线| 不卡一二三区| 国产一区二区三区四区五区| 日韩**一区毛片| 热久久久久久久| 精精国产xxxx视频在线野外| 精品一区二区三区在线观看视频| 日本欧美在线| 综合五月婷婷| 日韩一区欧美二区| 欧美在线影院| 欧美一区二区三区激情视频| 日韩电影免费在线观看| 亚洲黄色免费看| 国产成人精品一区二区免费看京| 国产精品久久久久久久久久妞妞| 日本不卡中文字幕| 午夜亚洲福利| 亚洲三级国产| 中文字幕乱码亚洲无线精品一区| 在线国产一区二区| av一区二区高清| 在线国产一区二区| 亚洲一级在线| 老色鬼久久亚洲一区二区| 亚洲自啪免费| 综合一区二区三区| 日韩成人一级| 国产一区 二区| 国产精品久久| 精品亚洲精品| 成人免费电影网址| 99久久视频| 亚洲精品在线观看91| 亚洲成人免费| 国产一区成人| 三级一区在线视频先锋| 蜜桃视频在线观看一区二区| 丝瓜av网站精品一区二区| 日韩在线a电影| 亚洲tv在线| 国产精选久久| 国产一区精品福利| 欧美羞羞视频| 欧美天堂亚洲电影院在线观看| 亚洲一区观看| 日韩精品一区二区三区中文在线 | 欧美天堂一区| 麻豆成人综合网| 成人片免费看| 一区在线视频观看| 亚洲精品综合| 国产高清亚洲| 亚洲天堂资源| 91久久午夜| 日韩高清在线不卡| 免费看一区二区三区| 一区二区三区四区日本视频| 激情婷婷综合| 日本久久二区| a天堂资源在线| 国产91精品对白在线播放| 午夜在线精品| 欧美aⅴ一区二区三区视频| 日韩欧美二区| 蜜臀久久99精品久久久久宅男| 亚洲欧美久久精品| 精品一区91| 在线一区欧美| 国产精品巨作av| 亚洲a在线视频| 亚洲精品护士| 成人精品高清在线视频| 欧美精品九九| 国产欧美日韩影院| 日韩三区免费| 亚洲一区二区三区四区电影| 国产日韩欧美一区| 激情久久五月| 国产精品一区二区精品| 伊人精品一区| 日韩精品欧美成人高清一区二区| 国产一区2区在线观看| 中文精品在线| 精品九九在线| 亚洲日本欧美| 香蕉成人av| 日韩av在线播放中文字幕|