Home PHP Framework Swoole Summary of common problems with PHP Swoole long connections

Summary of common problems with PHP Swoole long connections

Jan 26, 2020 pm 01:48 PM
php swoole

Summary of common problems with PHP Swoole long connections

Connection failure problem

Example

Among them, Redis is common The error report is:

Configuration item: timeout

Error message: Error while reading line from the server

Redis can Configure if the client does not send data to the Redis server after a certain number of seconds, the connection will be closed.

Recommended learning: swoole tutorial

MySQL common errors:

Configuration items: wait_timeout & interactive_timeout

Error message: has gone away

Like the Redis server, MySQL will also clean up useless connections regularly.

How to solve

1. Reconnect when using

2. Send heartbeats regularly to maintain the connection

When using Reconnecting

The advantage is that it is simple, but the disadvantage is that it faces the problem of short connections.

Send heartbeat regularly to maintain connection

Recommended.

How to maintain a long connection

tcp_keepalive implemented in the tcp protocol

The bottom layer of the operating system provides a set of tcpkeepaliveConfiguration:

tcp_keepalive_time (integer; default: 7200; since Linux 2.2)
The number of seconds a connection needs to be idle before TCP
begins sending out keep-alive probes. Keep-alives are sent only
when the SO_KEEPALIVE socket option is enabled. The default
value is 7200 seconds (2 hours). An idle connection is
terminated after approximately an additional 11 minutes (9
probes an interval of 75 seconds apart) when keep-alive is
enabled.
 
Note that underlying connection tracking mechanisms and
application 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 before
giving up and killing the connection if no response is obtained
from the other end.
8
Copy after login

The bottom layer of Swoole has opened up these configurations, for example:

?php
 
$server = new \Swoole\Server('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
]);
Copy after login

Among them:

'open_tcp_keepalive' => 1, // 总开关,用来开启tcp_keepalive
'tcp_keepidle' => 4, // 4s没有数据传输就进行检测
// 检测的策略如下:
'tcp_keepinterval' => 1, // 1s探测一次,即每隔1s给客户端发一个包(然后客户端可能会回一个ack的包,如果服务端收到了这个ack包,那么说明这个连接是活着的)
'tcp_keepcount' => 5, // 探测的次数,超过5次后客户端还没有回ack包,那么close此连接
Copy after login

Let’s Let’s experience the actual test. The server script is as follows:

<?php
 
$server = new \Swoole\Server(&#39;127.0.0.1&#39;, 6666, SWOOLE_PROCESS);
 
$server->set([
&#39;worker_num&#39; => 1,
&#39;open_tcp_keepalive&#39; => 1, // 开启tcp_keepalive
&#39;tcp_keepidle&#39; => 4, // 4s没有数据传输就进行检测
&#39;tcp_keepinterval&#39; => 1, // 1s探测一次
&#39;tcp_keepcount&#39; => 5, // 探测的次数,超过5次后还没有回包close此连接
]);
 
$server->on(&#39;connect&#39;, function ($server, $fd) {
var_dump("Client: Connect $fd");
});
 
$server->on(&#39;receive&#39;, function ($server, $fd, $reactor_id, $data) {
var_dump($data);
});
 
$server->on(&#39;close&#39;, function ($server, $fd) {
var_dump("close fd $fd");
});
 
$server->start();
Copy after login

Let’s start this server:

 ~/codeDir/phpCode/hyperf-skeleton # php server.php
Copy after login

Then capture the packet through tcpdump:

~/codeDir/phpCode /hyperf-skeleton # 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

We are listening for data packets on port 6666 on lo at this time.

Then we use the client to connect to it:

~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666
Copy after login

At this time, the server will print out the message:

~/codeDir/phpCode/hyperf-skeleton # php server.php
string(17) "Client: Connect 1"
Copy after login

The output information of tcpdump is as follows:

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
// 省略了其他的输出
Copy after login

We will find that at the beginning, the three-way handshake packet will be printed:

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
Copy after login

Then, it will stay for 4s without any packet output.

After that, a group will be printed out every 1 second or so:

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
Copy after login
Copy after login

In fact, this is the strategy we configured:

 &#39;tcp_keepinterval&#39; => 1, // 1s探测一次
 &#39;tcp_keepcount&#39; => 5, // 探测的次数,超过5次后还没有回包close此连接
Copy after login

Because the bottom layer of our operating system will automatically The client responds with ack, so the connection will not be closed after 5 probes. The bottom layer of the operating system will continuously send a group of packets like this:

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
Copy after login
Copy after login

If we want to close the connection after testing 5 times, we can disable the packets on port 6666:

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

This will Disable all packets coming from port 6666. Naturally, the server will not be able to receive ack packets sent from the client.

Then the server will print out close after 5 seconds (the server actively calls the close method and sends a FIN packet to the client):

 ~/codeDir/phpCode/hyperf-skeleton # php server.php
 string(17) "Client: Connect 1"
 string(10) "close fd 1"
Copy after login
Copy after login

Let’s restore the iptables rules:

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

That is, the rules we set are deleted.

The heartbeat function is implemented through tcp_keepalive. The advantage is that it is simple. You can complete this function without writing code, and the heartbeat packet sent is small. The disadvantage is that it depends on the network environment of the system. It must be ensured that both the server and the client implement such functions, and the client needs to cooperate in sending heartbeat packets.

Another more serious shortcoming is that if the client and the server are not directly connected, but are connected through a proxy, such as the socks5 proxy, it will only forward application layer packets and not forward them. For lower-level TCP detection packets, the heartbeat function will be invalid.

So, Swoole provides other solutions, a set of configurations for detecting dead connections.

 &#39;heartbeat_check_interval&#39; => 1, // 1s探测一次
 &#39;heartbeat_idle_time&#39; => 5, // 5s未发送数据包就close此连接
Copy after login

heartbeat implemented by swoole

Let’s test it:

<?php
 
$server = new \Swoole\Server(&#39;127.0.0.1&#39;, 6666, SWOOLE_PROCESS);
 
$server->set([
&#39;worker_num&#39; => 1,
&#39;heartbeat_check_interval&#39; => 1, // 1s探测一次
&#39;heartbeat_idle_time&#39; => 5, // 5s未发送数据包就close此连接
]);
 
$server->on(&#39;connect&#39;, function ($server, $fd) {
var_dump("Client: Connect $fd");
});
 
$server->on(&#39;receive&#39;, function ($server, $fd, $reactor_id, $data) {
var_dump($data);
});
 
$server->on(&#39;close&#39;, function ($server, $fd) {
var_dump("close fd $fd");
});
 
$server->start();
Copy after login

Then start the server:

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

Then start 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
Copy after login

Then start the client:

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

At this time, the server prints:

~/codeDir/phpCode/hyperf-skeleton # php server.php
 string(17) "Client: Connect 1"
Copy after login

Then tcpdump prints:

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
Copy after login

This is the three-way handshake information.

Then after 5 seconds, tcpdump will print out:

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

That is, the server sent a FIN packet. Because the client sent no data, Swoole closed the connection.

Then the server will print:

 ~/codeDir/phpCode/hyperf-skeleton # php server.php
 string(17) "Client: Connect 1"
 string(10) "close fd 1"
Copy after login
Copy after login

So, there are certain differences between heartbeat and tcp keepalive. Tcp keepalive has the function of keeping the connection alive, but heartbeat saves It simply detects a connection without data and then closes it. It can only be configured on the server side. If it needs to be kept alive, the client can also cooperate to send heartbeats.

如果我们不想让服务端close掉连接,那么就得在应用层里面不断的发送数据包来进行保活,例如我在nc客户端里面不断的发送包:

~/codeDir/phpCode/hyperf-skeleton # nc 127.0.0.1 6666
ping
ping
ping
ping
ping
ping
ping
ping
ping
Copy after login

我发送了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
Copy after login

有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 0

02: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"
Copy after login

然后我们在客户端那边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 #
Copy after login

此时,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
Copy after login

应用层心跳

1、制定ping/pong协议(mysql等自带ping协议)

2、客户端灵活的发送ping心跳包

3、服务端OnRecive检查可用性回复pong

例如:

$server->on(&#39;receive&#39;, function (\Swoole\Server $server, $fd, $reactor_id, $data)
{
if ($data == &#39;ping&#39;)
{
checkDB();
checkServiceA();
checkRedis();
$server->send(&#39;pong&#39;);
}
});
Copy after login

 

结论

1、tcp的keepalive最简单,但是有兼容性问题,不够灵活

2、swoole提供的keepalive最实用,但是需要客户端配合,复杂度适中

3、应用层的keepalive最灵活但是最麻烦

The above is the detailed content of Summary of common problems with PHP Swoole long connections. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1670
14
PHP Tutorial
1274
29
C# Tutorial
1256
24
PHP: A Key Language for Web Development PHP: A Key Language for Web Development Apr 13, 2025 am 12:08 AM

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

PHP vs. Python: Understanding the Differences PHP vs. Python: Understanding the Differences Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP and Python: Comparing Two Popular Programming Languages PHP and Python: Comparing Two Popular Programming Languages Apr 14, 2025 am 12:13 AM

PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

PHP in Action: Real-World Examples and Applications PHP in Action: Real-World Examples and Applications Apr 14, 2025 am 12:19 AM

PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.

The Enduring Relevance of PHP: Is It Still Alive? The Enduring Relevance of PHP: Is It Still Alive? Apr 14, 2025 am 12:12 AM

PHP is still dynamic and still occupies an important position in the field of modern programming. 1) PHP's simplicity and powerful community support make it widely used in web development; 2) Its flexibility and stability make it outstanding in handling web forms, database operations and file processing; 3) PHP is constantly evolving and optimizing, suitable for beginners and experienced developers.

PHP and Python: Different Paradigms Explained PHP and Python: Different Paradigms Explained Apr 18, 2025 am 12:26 AM

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

PHP vs. Other Languages: A Comparison PHP vs. Other Languages: A Comparison Apr 13, 2025 am 12:19 AM

PHP is suitable for web development, especially in rapid development and processing dynamic content, but is not good at data science and enterprise-level applications. Compared with Python, PHP has more advantages in web development, but is not as good as Python in the field of data science; compared with Java, PHP performs worse in enterprise-level applications, but is more flexible in web development; compared with JavaScript, PHP is more concise in back-end development, but is not as good as JavaScript in front-end development.

PHP and Python: Code Examples and Comparison PHP and Python: Code Examples and Comparison Apr 15, 2025 am 12:07 AM

PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

See all articles