[提交缺陷]Swoole2.X版本提供PHP原生协程支持实践,Http请求部分的$httpclient-setDefer();该行出...

栏目: Java · 发布时间: 7年前

内容简介:[提交缺陷]Swoole2.X版本提供PHP原生协程支持实践,Http请求部分的$httpclient-setDefer();该行出...

背景:研究一下这个Swoole2.X(V2.0.8)的协程,于是试了一下Tcp/Mysql/Redis/Http(在一个以Http形式下,协程了:TcpServer配置、 Redis 配置、 Mysql 配置、Http,最后的接口返回时间以里面最长的那个为准,也就是一般是Mysql耗时最长,它就是最长的接口返回时间了。)一起上,Swoole顾问觉得要想性能高还得加上RPC,再就是在一些数据的Pack和Unpack性能上予以加强,以争取每个请求都非常快非常高效,一请求发现出现了段错误,最新版本出现小小的问题属于正常性况,关键是如何反馈问题,看了一下Swoole的Wiki是如何提Bug的连接,于是就试着提一个Bug吧,给其它用Swoole万一出现Coredump的兄弟们作一个示范,进行提Bug的和捕获相关的Coredump的输出,参考Swoole的Wiki,地址:https://wiki.swoole.com/wiki/page/10.html。

一、假如在你的项目中出现段错误,怎么办?重新编译打包Swoole的源码并打成RPm包,打开debug,参数是: --enable-debug ,如下:

swoole-php71-2.0.7.el7.x86_64.spec 打包./configure部分:

#./configure --with-php-config=%{php_bin}/php-config --enable-coroutine --enable-async-redis

./configure --with-php-config=%{php_bin}/php-config --enable-coroutine --enable-async-redis --enable-debug

二、Mysql部分做测试,加上用户权限,那个Tcp就用Swoole的示例打开9501端口,官网上有很简单的TcpServer样例(略),Mysql部分如下:

Mysql服务器上@101.200.*.135:

#mysql

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 93109

Server version: 8.0.0-dmr-log Source distribution

mysql> grant all privileges on test.* to swooleUser@10.51.*.34 identified by "test123";

Query OK, 0 rows affected, 1 warning (0.04 sec)

mysql> flush privileges;    

Query OK, 0 rows affected (0.01 sec)

@测试机器@123.57.*.183

#rpm -ql mysql-client-8.0.0-170523211353.el7.centos.x86_64

/usr/local/mysql/bin/mysql

#/usr/local/mysql/bin/mysql -h10.44.*.177 -uswooleUser -p

Enter password:

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| test               |

+--------------------+

2 rows in set (0.00 sec)

三、根据TcpServer配置、Redis配置、Mysql配置、Http(试着访问百度的Http页面),一般来讲都是Mysql慢,所以,它才是重点,代码如下:

coroutinemysql.php

<?php
$server = new Swoole\Http\Server("123.57.*.183", 9507, SWOOLE_BASE);
$server->set([
    'worker_num' => 1,
]);

$server->on('Request', function ($request, $response) {
    $tcpclient = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
    $tcpclient->connect('127.0.0.1', 9501,0.5);
    $tcpclient->send("hello world\n");

    $redis = new Swoole\Coroutine\Redis();
    $redis->connect('123.57.*.183', 6379);
    $redis->setDefer();
    $redis->get('key');

    $mysql = new Swoole\Coroutine\MySQL();
    $ret = $mysql->connect([
    'host' => '10.44.*.177',
    'port' => 3306,
        'user' => 'swooleUser',
        'password' => 'test123',
        'database' => 'test',
    ]);
    if ($ret == false) {
        $response->end("MySQL connect fail!");
        return;
    }
    $mysql->setDefer();
    $mysql->query('select sleep(1)');

    $httpclient = new Swoole\Coroutine\Http\Client('123.125.114.144', 80);
    $httpclient->setHeaders(['Host' => "baidu.com"]);
    $httpclient->set([ 'timeout' => 1]);
    $httpclient->setDefer();
    $httpclient->get('/');

    $tcp_res  = $tcpclient->recv();
    $redis_res = $redis->recv();
    $mysql_res = $mysql->recv();
    $http_res  = $httpclient->recv();

    $response->end('Test End');
});
$server->start();

四、按Swoole官方的Wiki教程,设置一下吐核,From: https://wiki.swoole.com/wiki/page/10.html :

#ulimit -c unlimited

五、启动对外提供的Http协议的9507端口访问进来后的多种协议并发的协程服务,如下:

#php  coroutinemysql.php

六、访问Http时再触发一下协程:

触发一下:http://123.57.*.183:9507/

七、生成了段错误的Coredump文件,如下:

#php  coroutinemysql.php

段错误(吐核)

#ls *core*              

core.8494

八、用GDB去跟进其堆栈,BT显示调用层级定位出现问题所在位置:

#gdb php /tmp/core.8494

(gdb) bt

#0  0x00007f146b33e9a5 in http_client_coro_send_http_request (zobject=0x7f147248d190)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/swoole_http_client_coro.c:501

#1  0x00007f146b383c93 in swClient_onWrite (reactor=<optimized out>, event=0x7ffd0c185a10)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/src/network/Client.c:1109

#2  0x00007f146b37d63c in swReactorEpoll_wait (reactor=0x1dfc338, timeo=<optimized out>)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/src/reactor/ReactorEpoll.c:270

#3  0x00007f146b389de9 in swReactorProcess_loop (pool=<optimized out>,

worker=worker@entry=0x7ffd0c185ae0)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/src/network/ReactorProcess.c:379

#4  0x00007f146b38a727 in swReactorProcess_start (serv=serv@entry=0x1dc7cf0)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/src/network/ReactorProcess.c:112

#5  0x00007f146b381538 in swServer_start (serv=serv@entry=0x1dc7cf0)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/src/network/Server.c:696

#6  0x00007f146b333730 in zim_swoole_http_server_start (execute_data=0x7f14724130a0,

return_value=0x7ffd0c185cb0)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/swoole_http_server.c:1567

#7  0x00000000008ad0c6 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER ()

#8  0x000000000085bd3b in execute_ex ()

#9  0x00000000008aee24 in zend_execute ()

#10 0x0000000000816fc4 in zend_execute_scripts ()

#11 0x00000000007b8520 in php_execute_script ()

#12 0x00000000008b0fbf in do_cli ()

#13 0x000000000043d450 in main ()

(gdb)f 1

#1  0x00007f146b383c93 in swClient_onWrite (reactor=<optimized out>, event=0x7ffd0c185a10)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/src/network/Client.c:1109

1109                cli->onConnect(cli);

(gdb)f 0

#0  0x00007f146b33e9a5 in http_client_coro_send_http_request (zobject=0x7f147248d190)

at /home/test/rpmbuild/BUILD/swoole-src-2.0.7-stable/swoole_http_client_coro.c:501

501         if (!http->cli || !http->cli->socket )

九、用valgrind大体排查一下是否有内存溢出等:

[root@测试服务器:/tmp]

#USE_ZEND_ALLOC=0 valgrind php coroutinemysql.php

==12833== Memcheck, a memory error detector

==12833== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.

==12833== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info

==12833== Command: php coroutinemysql.php

==12833==

==12833== Invalid read of size 8

==12833==    at 0x121249A5: http_client_coro_send_http_request (swoole_http_client_coro.c:501)

==12833==    by 0x12169C92: swClient_onWrite (Client.c:1109)

==12833==    by 0x1216363B: swReactorEpoll_wait (ReactorEpoll.c:270)

==12833==    by 0x1216FDE8: swReactorProcess_loop (ReactorProcess.c:379)

==12833==    by 0x12170726: swReactorProcess_start (ReactorProcess.c:112)

==12833==    by 0x12167537: swServer_start (Server.c:696)

==12833==    by 0x1211972F: zim_swoole_http_server_start (swoole_http_server.c:1567)

==12833==    by 0x8AD0C5: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (in /usr/local/php/bin/php)

==12833==    by 0x85BD3A: execute_ex (in /usr/local/php/bin/php)

==12833==    by 0x8AEE23: zend_execute (in /usr/local/php/bin/php)

==12833==    by 0x816FC3: zend_execute_scripts (in /usr/local/php/bin/php)

==12833==    by 0x7B851F: php_execute_script (in /usr/local/php/bin/php)

==12833==  Address 0x100000188 is not stack'd, malloc'd or (recently) free'd

==12833==

==12833==

==12833== Process terminating with default action of signal 11 (SIGSEGV): dumping core

==12833==  Access not within mapped region at address 0x100000188

==12833==    at 0x121249A5: http_client_coro_send_http_request (swoole_http_client_coro.c:501)

==12833==    by 0x12169C92: swClient_onWrite (Client.c:1109)

==12833==    by 0x1216363B: swReactorEpoll_wait (ReactorEpoll.c:270)

==12833==    by 0x1216FDE8: swReactorProcess_loop (ReactorProcess.c:379)

==12833==    by 0x12170726: swReactorProcess_start (ReactorProcess.c:112)

==12833==    by 0x12167537: swServer_start (Server.c:696)

==12833==    by 0x1211972F: zim_swoole_http_server_start (swoole_http_server.c:1567)

==12833==    by 0x8AD0C5: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (in /usr/local/php/bin/php)

==12833==    by 0x85BD3A: execute_ex (in /usr/local/php/bin/php)

==12833==    by 0x8AEE23: zend_execute (in /usr/local/php/bin/php)

==12833==    by 0x816FC3: zend_execute_scripts (in /usr/local/php/bin/php)

==12833==    by 0x7B851F: php_execute_script (in /usr/local/php/bin/php)

==12833==  If you believe this happened as a result of a stack

==12833==  overflow in your program's main thread (unlikely but

==12833==  possible), you can try to increase the size of the

==12833==  main thread stack using the --main-stacksize= flag.

==12833==  The main thread stack size used in this run was 8388608.

==12833==

==12833== HEAP SUMMARY:

==12833==     in use at exit: 22,357,752 bytes in 22,711 blocks

==12833==   total heap usage: 29,852 allocs, 7,141 frees, 23,257,973 bytes allocated

==12833==

==12833== LEAK SUMMARY:

==12833==    definitely lost: 64 bytes in 2 blocks

==12833==    indirectly lost: 4,096 bytes in 2 blocks

==12833==      possibly lost: 1,813,286 bytes in 18,399 blocks

==12833==    still reachable: 20,540,306 bytes in 4,308 blocks

==12833==         suppressed: 0 bytes in 0 blocks

==12833== Rerun with --leak-check=full to see details of leaked memory

==12833==

==12833== For counts of detected and suppressed errors, rerun with: -v

==12833== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

段错误

十、在 PHP 代码上加加减减,定位一下PHP这个协程是哪个协议出现问题,经定位发现是发起http这块的协程可能有问题,如下:

再细节一点:

#php coroutinemysql.php

段错误(吐核)

这一行引起的:$httpclient->setDefer();     #setDefer函数的Wiki地址:https://wiki.swoole.com/wiki/page/607.html

$httpclient = new Swoole\Coroutine\Http\Client('123.125.114.144', 80);

$httpclient->setHeaders(['Host' => "baidu.com"]);

$httpclient->set([ 'timeout' => 3]);

$httpclient->setDefer();            #注释这一行,就会报下面的警告,不会Coredump,如下:                                                                

$httpclient->get('/');

#php coroutinemysql.php   #浏览器访问一下:http://123.57.*.183:9507/

PHP Warning:  Swoole\Coroutine\Http\Client::recv(): you should not use recv without defer  in /tmp/coroutinemysql.php on line 40

PHP Warning:  Swoole\Coroutine\Http\Client::recv(): you should not use recv without defer  in /tmp/coroutinemysql.php on line 40

在服务器上CURL形式访问一下百度,没毛病:

curl -i -H"Host:baidu.com" http://123.125.114.144            

HTTP/1.1 200 OK  

<html>

<meta http-equiv=refresh content=0;url=http://www.baidu.com/>

</html>

十一、提交出现Coredump以及和环境相关的问题给Swoole的CoreTeam研发小组的兄弟:

请将上面的得到的信息,连同机器信息,包括php -v gcc -v uname -a 提交到Github Issues页面或者发送邮件到 team@swoole.com。

若确定是Swoole的问题,开发组会快速解决问题。

其它涉及到编译器和PHP版本、系统环境:

#php -v

PHP 7.1.5 (cli) (built: May 23 2017 10:35:57) ( NTS )

Copyright (c) 1997-2017 The PHP Group

Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

with Zend OPcache v7.1.5, Copyright (c) 1999-2017, by Zend Technologies

#gcc -v

使用内建 specs。

COLLECT_GCC=gcc

COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper

目标:x86_64-redhat-linux

配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux

线程模型:posix

gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)

#uname -a

Linux 测试服务器 4.11.2-1.el7.elrepo.x86_64 #1 SMP Sun May 21 19:31:34 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux

#php --ri swoole

swoole

swoole support => enabled

Version => 2.0.8

Author => tianfeng.han[email: mikan.tenny@gmail.com]

epoll => enabled

eventfd => enabled

timerfd => enabled

signalfd => enabled

cpu affinity => enabled

spinlock => enabled

rwlock => enabled

async redis client => enabled

async http/websocket client => enabled

Linux Native AIO => enabled

pcre => enabled

zlib => enabled

mutex_timedlock => enabled

pthread_barrier => enabled

Directive => Local Value => Master Value

swoole.aio_thread_num => 2 => 2

swoole.display_errors => On => On

swoole.use_namespace => On => On

swoole.fast_serialize => 1 => 1

swoole.unixsock_buffer_size => 8388608 => 8388608

EOF


以上所述就是小编给大家介绍的《[提交缺陷]Swoole2.X版本提供PHP原生协程支持实践,Http请求部分的$httpclient-setDefer();该行出...》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

创业头条

创业头条

[美]兰德尔•莱恩(Randall Lane)及《福布斯》杂志编辑部 / 孙莹莹 / 浙江人民出版社 / 2015-6 / 54.90

[内容简介] 全民创业的浪潮中,如何抓住共享经济带来的机遇?没有营收模式还一直烧钱的公司,如何赢得投资人的青睐?一轮死、二轮死、N轮死的魔咒下,怎样才能成功活下来?面对数十亿美元的收购要约,创始人究竟应该如何抉择?没有资金又不懂技术,是否就无法分享互联网创业的红利?《创业头条》一书将为你揭秘上述问题的答案。 阅读《创业头条》一书你会发现,在硅谷最新崛起的互联网亿万富豪身上,有这样一......一起来看看 《创业头条》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

html转js在线工具
html转js在线工具

html转js在线工具