PHP-MySQLi连接随机失败,并显示"无法分配请求的地址"

Nen*_*nov 5 php mysql debian

从大约2周开始,我正在处理LAMP堆栈中最奇怪的问题之一.与MySQL服务器的长连接短连接失败,并显示错误消息:

Warning:  mysqli::real_connect(): (HY000/2002): Cannot assign requested address in ..
Run Code Online (Sandbox Code Playgroud)

MySQL是在不同的"盒子"上,托管在Rackspace Cloud今天我们将它的版本降级为

Ver 14.14 Distrib 5.1.42, for debian-linux-gnu (x86_64).
Run Code Online (Sandbox Code Playgroud)

根据它的状态变量,数据库服务器非常忙于处理每秒查询平均值:5327.957.

MySQL处于log-warnings = 9但没有记录连接拒绝的争用.站点和齿轮工作者脚本都会因为错误而失败,假设概率为1%.没有服务器负载似乎不是我们监控的因素.(CPU负载,IO负载或MySQL负载)最大数据库连接数(max_connections)设置为200但我们从未处理过与数据库的100多个同时连接

它有和没有防火墙软件.

我怀疑TCP网络问题而不是PHP/MySQL配置问题.

任何人都可以告诉我如何找到它?

更新:

连接代码是:

$this->_mysqli = mysqli_init(); 
$this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 120); 
$this->_mysqli->real_connect($dbHost,$dbUserName, $dbPassword, $dbName); 

if (!is_null($this->_mysqli->connect_error)) {
    $ping = $this->_mysqli->ping(); 

    if(!$ping){
        $error = 'HOST: {'.$dbHost.'};MESSAGE: '. $this->_mysqli->connect_error ."\n"; 
        DataStoreException::raiseHostUnreachable($error);
    }
} 
Run Code Online (Sandbox Code Playgroud)

Nak*_*lda 17

MySQL:使用巨大数量的连接

频繁连接有什么危险?
它运作良好,除了一些极端情况.如果从同一个盒子中每秒获得数百个连接,则可能会耗尽本地端口号.修复它的方法可能是 - 在linux上减少"/ proc/sys/net/ipv4/tcp_fin_timeout"(这会破坏TCP/IP标准但你可能不关心你的本地网络),增加"/ proc/sys/net/ipv4/ip_local_port_range"在客户端上.其他OS有类似的设置.您也可以为同一个数据库主机使用更多Web框或多个IP来解决此问题.我在制作中真的看到了这一点.

有关此问题的一些背景知识:
TCP/IP连接由localip:localport remoteip:remote port标识.在这种情况下,我们有MySQL IP和端口以及客户端IP固定,所以我们只能改变有限范围的本地端口.注意,即使在关闭连接后,TCP/IP堆栈必须保留端口保留一段时间,这是tcp_fin_timeout来自的地方.


yee*_*ing 10

我有这个问题,并使用持久连接模式解决了它,可以通过使用'p:'预先修复数据库主机名在mysqli中激活它

$link = mysqli_connect('p:localhost', 'fake_user', 'my_password', 'my_db');
Run Code Online (Sandbox Code Playgroud)

来自: http://php.net/manual/en/mysqli.persistconns.php:

持久连接背后的想法是客户端进程和数据库之间的连接可以由客户端进程重用,而不是多次创建和销毁.这样可以减少每次需要时创建新连接的开销,因为未使用的连接已缓存并可以重复使用....

要打开持久连接,必须在连接时将p:添加到主机名.


fgw*_*ler 8

使用Vicidial我经常遇到同样的问题,由于所使用的编程类型,必须(非常)频繁地从许多vicidial组件建立新的MYSQL连接,我们有系统锤击数据库服务器每秒超过10000个连接,其中大部分都在几毫秒内完成服务,并在一秒或更短的时间内关闭.根据经验,我可以告诉您,在本地网络中,几乎没有丢失的软件包,tcp_fin_timeout可以一直降低到3而不会出现任何问题.

用于诊断等待关闭的连接是否是您的问题的典型linux命令是:

netstat -anlp | grep :3306 | grep TIME_WAIT -wc
Run Code Online (Sandbox Code Playgroud)

这将显示等待完全关闭的连接数.

netstat -nat | awk {'print $5'} | cut -d ":" -f1 | sort | uniq -c | sort -n
Run Code Online (Sandbox Code Playgroud)

它将显示每个连接主机的连接,如果有多个候选,您可以识别哪个主机正在折叠您的系统.

要测试修复,你可以

cat /proc/sys/net/ipv4/tcp_fin_timeout
echo "3" > /proc/sys/net/ipv4/tcp_fin_timeout
Run Code Online (Sandbox Code Playgroud)

这将暂时将tcp_fin_timeout设置为3秒并告诉您它之前的秒数,因此您可以恢复到旧值进行测试.

作为永久性修复,我建议您将以下行添加到/etc/sysctl.conf中

net.ipv4.tcp_fin_timeout=3
Run Code Online (Sandbox Code Playgroud)

在一个良好的本地网络内不应该造成任何麻烦,如果你遇到问题,例如因为丢包,你可以试试

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_fin_timeout=10
Run Code Online (Sandbox Code Playgroud)

Wiche允许更多时间连接关闭并尝试重用相同的ip:端口组合,以便与同一主机:服务组合的新连接.

要么

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout=10
Run Code Online (Sandbox Code Playgroud)

哪个会更积极地尝试重用连接,但是可以通过您的网络服务器为其他应用程序创建新问题.所以你应该首先尝试简单的解决方案,在大多数情况下,它已经解决了你的问题没有任何不良副作用!

祝好运!