PHP-FPM与mysqlnd卡在连接上而不是超时(gdb回溯内部)

前端之家收集整理的这篇文章主要介绍了PHP-FPM与mysqlnd卡在连接上而不是超时(gdb回溯内部)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在运行 PHP-FPM,并且在极高负载时会出现问题,导致PHP进程永远陷入困境.我做了一个GDB回溯的运行进程被卡住了,得到了这个(删除了无关的帧):
#0  0x00007ff51704bb90 in __poll_nocancel () at ../sysdeps/unix/syscall-template.S:81

#1  0x0000000000694694 in poll (__timeout=<optimized out>,__nfds=1,__fds=0x7fff18a2c800) at /usr/include/x86_64-linux-gnu/bits/poll2.h:46

#2  PHP_pollfd_for (timeouttv=0x2c18a30,events=25,fd=<optimized out>) at /build/buildd/PHP5-5.5.19+dfsg/main/PHP_network.h:165

#3  PHP_sock_stream_wait_for_data (stream=0x2df2b88,sock=0x2c18a28) at /build/buildd/PHP5-5.5.19+dfsg/main/streams/xp_socket.c:131

#4  PHP_sockop_read (stream=0x2df2b88,buf=0x2e03628 "X\221\340\002",count=4) at /build/buildd/PHP5-5.5.19+dfsg/main/streams/xp_socket.c:154

#5  0x00000000004a629a in PHP_openssl_sockop_read (stream=0x2df2b88,count=<optimized out>) at /build/buildd/PHP5-5.5.19+dfsg/ext/openssl/xp_ssl.c:234

#6  0x0000000000688926 in _PHP_stream_fill_read_buffer (stream=stream@entry=0x2df2b88,size=size@entry=4) at /build/buildd/PHP5-5.5.19+dfsg/main/streams/streams.c:691

#7  0x0000000000688a87 in _PHP_stream_read (stream=stream@entry=0x2df2b88,buf=buf@entry=0x7fff18a2c9e0 "",size=size@entry=4) at /build/buildd/PHP5-5.5.19+dfsg/main/streams/streams.c:738

#8  0x00007ff5164b83a6 in PHP_MysqLnd_net_network_read_ex_pub (net=<optimized out>,buffer=<optimized out>,count=4,stats=0x2add010,error_info=<optimized out>)
    at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd_net.c:80

#9  0x00007ff5164b7cb6 in PHP_MysqLnd_net_receive_ex_pub (net=0x2e04238,buffer=0x7fff18a2c9e0 "",conn_stats=0x2add010,error_info=0x2e13860)
    at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd_net.c:682

#10 0x00007ff5164b118b in MysqLnd_read_header (net=0x2e04238,error_info=<optimized out>,header=<optimized out>,header=<optimized out>)
    at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd_wireprotocol.c:287

#11 0x00007ff5164b1d46 in PHP_MysqLnd_greet_read (_packet=0x2e14e98,conn=0x2e13728) at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd_wireprotocol.c:333

#12 0x00007ff5164ab8ad in PHP_MysqLnd_conn_data_connect_handshake_pub (conn=0x2e13728,host=<optimized out>,user=0x2b49d70 "testuser",passwd=0x2b49c40 "<PASSWORD REMOVED>",passwd_len=7,db=0x2b43c18 "testuser",db_len=7,MysqL_flags=959117) at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd.c:774

#13 0x00007ff5164a9e71 in PHP_MysqLnd_conn_data_connect_pub (conn=0x2e13728,host=0x2e13558 "localhost",port=3306,socket_or_pipe=0x7ff50a563b4c "/var/run/MysqLd/MysqLd.sock",MysqL_flags=959117)
    at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd.c:958

#14 0x00007ff5164a6430 in PHP_MysqLnd_conn_connect_pub (conn_handle=0x2e136d8,MysqL_flags=131072)
    at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd.c:1098

#15 0x00007ff5164adc07 in MysqLnd_connect (conn_handle=0x2e136d8,user=<optimized out>,passwd=<optimized out>,passwd_len=<optimized out>,db=<optimized out>,MysqL_flags=131072) at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLnd/MysqLnd.c:1131

#16 0x00007ff50a55fe82 in MysqLi_common_connect (ht=<optimized out>,return_value=0x2e05978,return_value_ptr=<optimized out>,this_ptr=<optimized out>,return_value_used=<optimized out>,is_real_connect=is_real_connect@entry=0 '\000',in_ctor=in_ctor@entry=1 '\001') at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLi/MysqLi_nonapi.c:242

#17 0x00007ff50a560633 in zif_MysqLi_link_construct (ht=<optimized out>,return_value=<optimized out>,return_value_used=<optimized out>)
    at /build/buildd/PHP5-5.5.19+dfsg/ext/MysqLi/MysqLi_nonapi.c:320

所以我可以看到的是,我正在尝试连接到MysqL,然后PHP卡住轮询插件. MysqL可能会丢弃或拒绝连接(数据库处于100%cpu负载).

但是,我将MysqL.connect_timeout设置为60,所以我希望连接不会持续很长时间(超过20分钟). default_socket_timeout也设置为300秒.

而且我会预先考虑升级MysqLi的任何建议,说我已经尝试过(我们使用的是DBAL),并且遇到了与MysqLi使用相同连接功能相同的问题.

我在Ubuntu上运行PHP 5.5.19,并使用MysqLnd驱动程序.

知道什么可能导致PHP没有超时吗?

我认为你正在打我称之为“死亡可用性乐队”.这意味着你在你的行动完全失败(它会超时)和不起作用之间陷入困境.事情就是这样

>您调用PHP脚本
> PHP尝试打开与MysqL的连接
> MysqL(100%负载)响应缓慢但在分配的超时内打开连接
> PHP发送sql
> MysqL(仍然处于100%负载)现在可能会卡住.查询最终会执行,但现在您遇到了实际返回响应的问题.所以PHP得到……一些东西.说涓涓细流. MysqL不会超时(它有一个它正在响应的有效请求),PHP也不会(它以非常慢的速度获取数据).所以这两个程序都陷入了这个“死区”,只是发生了足够的事情以避免超时,但还不足以解决死锁问题.你有时可以在做SHOW PROCESSLIST时看到这个;

我意识到你不是在发送sql,但我认为相同的原则会发挥作用.您有时可以看到这种情况发生在使用MysqL Workbench(执行查询但无法返回结果)的远程数据库中.因此,Workbench会挂起来等待永远不会发生的响应.

那么如何解决这个问题呢?实际上,你不能在PHP的编程层面. PHP API不会暴露足够的底层调用,以允许您识别出您陷入死区并终止连接.编写一个查找死区的脚本将始终存在终止其他良好进程的风险.你最好的选择(尽管我不愿意这么说)是支持你的MysqL并确保它有足够的资源来达不到100%.如果您与PHP / Apache共享一个服务器,那就是这种事情的配方.我注意到它很少发生在我们更大更好的系统上,因为我们将MysqL移动到它自己的实例.另外,请查看mysqltuner.它可以查看您的MysqL实例并建议配置调整以提高性能.

猜你在找的PHP相关文章