成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

詳解PHP Swoole長連接常見問題

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

例子

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

配置項:timeout

報錯信息:

Error while reading line from the server

Redis可以配置如果客戶端經過多少秒還不給Redis服務器發送數據,那么就會把連接close掉。

MySQL常見的報錯:

配置項:wait_timeout & interactive_timeout

報錯信息:

has gone away

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

如何解決

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

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

如何維持長連接

tcp協議中實現的tcp_keepalive

操作系統底層提供了一組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, // 對應tcp_keepalive_time’tcp_keepinterval’ => 1, // 對應tcp_keepalive_intvl’tcp_keepcount’ => 5, // 對應tcp_keepalive_probes]);

其中:

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

我們來實戰測試體驗一下,服務端腳本如下:

<?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沒有數據傳輸就進行檢測’tcp_keepinterval’ => 1, // 1s探測一次’tcp_keepcount’ => 5, // 探測的次數,超過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();

我們啟動這個服務器:

~/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

我們此時正在監聽lo上的6666端口的數據包。

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

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

此時服務端會打印出消息:

~/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

// 省略了其他的輸出

我們會發現最開始的時候,會打印三次握手的包:

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, // 探測的次數,超過5次后還沒有回包close此連接

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

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次探測后關閉這個連接,可以禁掉6666端口的包:

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

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

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

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

string(17) 'Client: Connect 1'

string(10) 'close fd 1'

我們恢復一下iptables的規則:

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

即把我們設置的規則給刪除了。

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

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

’heartbeat_check_interval’ => 1, // 1s探測一次’heartbeat_idle_time’ => 5, // 5s未發送數據包就close此連接

swoole實現的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未發送數據包就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();

然后啟動服務器:

~/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

此時服務器端打印:

~/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

也就是服務端發送了FIN包。因為客戶端沒有發送數據,所以Swoole關閉了連接。

然后服務器端會打印:

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

string(17) 'Client: Connect 1'

string(10) 'close fd 1'

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

如果我們不想讓服務端close掉連接,那么就得在應用層里面不斷的發送數據包來進行保活,例如我在nc客戶端里面不斷的發送包:

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

ping

ping

ping

ping

ping

ping

ping

ping

ping

我發送了9個ping包給服務器,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組數據包的發送。(這里的Flags [P.]代表Push的含義)

此時服務器還沒有close掉連接,實現了客戶端保活連接的功能。然后我們停止發送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服務端那邊發送了FIN包,說明服務端close掉了連接。服務端的輸出如下:

~/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來關閉連接:

~/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

應用層心跳

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

2、客戶端靈活的發送ping心跳包

3、服務端OnRecive檢查可用性回復pong

例如:

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

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

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

3、應用層的keepalive最靈活但是最麻煩

以上就是詳解PHP Swoole長連接常見問題的詳細內容,更多關于PHP Swoole長連接常見問題的資料請關注好吧啦網其它相關文章!

標簽: PHP
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
99国产精品一区| 亚洲欧美日韩一区二区| 中文字幕一区av| 91在线播放网址| 6080国产精品一区二区| 日产国产欧美视频一区精品| 亚洲欧美春色| 亚洲图片有声小说| 午夜一区在线| 午夜精品影院在线观看| 一本色道久久综合| 亚洲视频免费在线| 91久久极品少妇xxxxⅹ软件| 综合亚洲深深色噜噜狠狠网站| 亚洲小说区图片区| 亚洲欧美成人一区二区三区| 日韩视频精品在线观看| 中文字幕一区视频| 一区二区亚洲精品| 国产精品久久99| 在线成人h网| 亚洲精品日韩专区silk| 亚洲精品影院| 亚洲国产裸拍裸体视频在线观看乱了 | 99久久99精品久久久久久 | 欧美久久久久久久久久| 国产高清精品在线| 日韩欧美在线一区二区三区| 99久久免费精品高清特色大片| 国产日韩高清在线| 伊人久久大香线蕉综合热线| 亚洲色图在线视频| 国产麻豆综合| 肉色丝袜一区二区| 欧美美女网站色| 成人国产精品免费| 日本一区二区三级电影在线观看 | 成人国产精品免费观看| 久久蜜臀中文字幕| 今天的高清视频免费播放成人| 亚洲激情图片qvod| 91成人在线观看喷潮| 国产麻豆午夜三级精品| 精品国产一区二区三区四区四 | 精品理论电影在线| 欧美日韩免费观看一区| 亚洲精品国产第一综合99久久| 久久久777| 精品一区二区三区免费视频| 精品日韩欧美一区二区| 亚洲夜间福利| 日韩黄色一级片| 制服丝袜一区二区三区| 99久精品国产| 亚洲女与黑人做爰| 色综合久久久久综合体| 国产成人av自拍| 国产精品久久久久天堂| 久久天堂国产精品| 国产精品小仙女| 亚洲国产成人私人影院tom| 国产欧美日韩综合精品二区| 麻豆国产精品一区二区三区 | 亚洲激情一区| 视频一区在线播放| 日韩欧美色综合网站| 伊人影院久久| 免费成人美女在线观看| 亚洲精品一线二线三线无人区| 影音先锋久久资源网| 日本美女视频一区二区| 2023国产一二三区日本精品2022| 在线视频国内自拍亚洲视频| 男人的j进女人的j一区| 久久久精品国产99久久精品芒果 | 国产精品久久久久桃色tv| 久久三级视频| 白白色亚洲国产精品| 亚洲一区二区三区中文字幕 | 国产亚洲成年网址在线观看| 亚洲欧美日韩一区在线观看| 国产99久久久国产精品免费看 | 欧美成人一区二区三区片免费 | 蜜桃精品视频在线| 久久日一线二线三线suv| 国产一区二区精品| 国产乱码字幕精品高清av | 韩国成人在线视频| 中文字幕第一区| 色婷婷av一区二区| 欧美伊人影院| 蜜臀va亚洲va欧美va天堂 | 亚洲综合色丁香婷婷六月图片| 欧美日韩1区2区| 精品不卡在线| 国产久卡久卡久卡久卡视频精品| 国产精品国产a级| 91精品国产福利在线观看| 一区二区自拍| 国产传媒欧美日韩成人| 亚洲综合丁香婷婷六月香| 精品国产三级电影在线观看| 国产精品日韩一区二区| 懂色av一区二区三区蜜臀| 亚洲国产精品久久久久秋霞影院 | 国产精品理论在线观看| 欧美日韩一区二区三区在线| 亚洲视频在线二区| 国产精品一线二线三线| 亚洲精品日韩专区silk| 精品国产sm最大网站免费看| 日本乱人伦一区| 激情综合网址| 成人一区二区三区在线观看| 天天av天天翘天天综合网| 国产人伦精品一区二区| 欧美午夜精品久久久| 亚洲人成高清| 99久久er热在这里只有精品15| 久久99精品久久久| 亚洲成人手机在线| 中文字幕一区二区三区视频| 精品国产成人系列| 欧美三级电影一区| 亚洲综合激情| 激情久久婷婷| 牛夜精品久久久久久久99黑人| 国产一区二区三区香蕉| 日韩有码一区二区三区| 亚洲黄色小说网站| 欧美国产日韩在线观看| 欧美一级免费大片| 在线亚洲免费视频| 亚洲综合国产激情另类一区| 韩国精品一区二区三区| 成人黄色网址在线观看| 久久成人18免费观看| 亚洲第一av色| 亚洲免费在线观看| 国产三级久久久| 精品奇米国产一区二区三区| 3d动漫精品啪啪一区二区竹菊 | 亚洲一区二区精品在线观看| 欧美激情1区2区| 成人丝袜视频网| 国产又黄又大久久| 美腿丝袜亚洲色图| 石原莉奈在线亚洲三区| 亚洲综合激情另类小说区| 亚洲欧美日韩成人高清在线一区| 国产清纯在线一区二区www| 欧美成人r级一区二区三区| 欧美美女激情18p| 欧美午夜理伦三级在线观看| 久久精品中文字幕一区二区三区| 国产欧美一区二区三区国产幕精品| 欧美日韩国产精品一卡| 99精品久久免费看蜜臀剧情介绍| 国产精品一区二区在线播放| 免费国产亚洲视频| 水野朝阳av一区二区三区| 亚洲高清在线精品| 亚洲午夜视频在线| 亚洲国产精品一区二区www| 亚洲一区二区偷拍精品| 亚洲最新视频在线观看| 亚洲精品国产精品乱码不99| 亚洲男人天堂av网| 亚洲色图制服丝袜| 日韩一区日韩二区| 日韩伦理免费电影| 亚洲欧洲性图库| 日韩理论电影院| 亚洲欧美一区二区三区孕妇| 亚洲欧美乱综合| 亚洲一区二区三区中文字幕在线 | 自拍偷拍欧美激情| 中文字幕佐山爱一区二区免费| 国产精品天美传媒沈樵| 日韩一区日韩二区| 亚洲欧美二区三区| 一区二区三区资源| 香港成人在线视频| 日韩—二三区免费观看av| 天天综合色天天综合| 亚洲18色成人| 奇米亚洲午夜久久精品| 日韩电影在线看| 精品综合免费视频观看| 国产高清一区日本| 色综合天天狠狠| 亚洲黄色三级| 久久精品日韩| 欧美色区777第一页| 5858s免费视频成人| 欧美大片一区二区| 国产蜜臀av在线一区二区三区| 亚洲日本护士毛茸茸| 亚洲动漫第一页| 麻豆freexxxx性91精品|