php并发优化

楚天乐 2248 0 条

服务器配置

  1. 8核e5-2630L 2.4ghz, 16g内存

QQ图片20200324163857.png
QQ图片20200324171525.png

  1. 20MB带宽

问题场景描述

  1. jemter 300并发开始出现502错误
  2. CPU利用率60%
  3. 内存利用率50%
  4. 网络流量1MB到1.5MB

分析

  1. cpu和内存利用率不高,网络也没有耗尽。肯定是卡在IO上了。
  2. netstat查看TIME_WAIT,数量正常
  3. opcache查看,已开启,没问题
  4. 详细查看压测错误,发现压测过程中出现"SQL Error 1040: Too Many Connection"。既然超过连接数,那就查看限制多少连接吧。
mysql参数

max_connections = 2000;  # 2000连接,没毛病,问题不在这
  1. 到底有多少连接。一看也是惊呆了,大量的sleep连接没有释放。好了这就是原因了。

解决

  1. 系统内同时使用了laravel orm,和pdo对象。系统二开,为了方便增加了laravel orm。
  2. 那就看看是谁没关闭连接吧。
  3. 去掉所有laraval orm的数据库操作,去掉laravel orm连接创建方法。运行测试,发现还是会保留大量sleep mysql connection
  4. 去翻pdo创建代码
// 目测就是这个ATTR_PERSISTENT => true了
$this->connection = new \PDO("mysql:host=" . $hostname . ";port=" . $port . ";dbname=" . $database, $username, $password, array(\PDO::ATTR_PERSISTENT => true));

修改为

// 目测就是这个ATTR_PERSISTENT => true了
$this->connection = new \PDO("mysql:host=" . $hostname . ";port=" . $port . ";dbname=" . $database, $username, $password, array(\PDO::ATTR_PERSISTENT => false));
  1. 再次测试,发现没有新的sleep connection了。采用短连接方式和mysql交互。再次压测,稳了1000无压力(晚上没人了再去跑更大的压测)。

  2. laravel orm会不会有这个问题呢?去掉laravel orm创建及查询代码的注释,再次压测。ok,依然没问题。好了解决了

再来压测

1000并发(每分钟60000限制)
QQ图片20200324172114.png

总结

  1. lnmp下php fpm实际上是没法复用mysql连接的,每次请求都重新初始化。开启ATTR_PERSISTENT => true之后,mysql认为php可以复用mysql连接,所以并没有关闭。这就产生了大量mysql sleep连接,在并发场景下,php会无法连接mysql,出现too many connection错误
  2. 使用短连接的话,又担心tcp连接关闭产生过多TIME_WAIT。
vim /etc/sysctl.conf

;增加
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_max_tw_buckets = 8000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 10

退出vim,重新加载
sysctl -p


发表我的评论
昵称 (必填)
邮箱 (必填)
网址
执行时间: 1714169868686.6 毫秒