为什么我测试的结果表明,似乎php连接mysql每个线程单位的效率更高?

151 views
Skip to first unread message

Barbery

unread,
May 17, 2013, 10:05:39 AM5/17/13
to open...@googlegroups.com
我是一个新手,如果有什么说错的,请大家多多包涵。也希望大家解答下我的疑问,满足我这个小小的好奇心。。。
我的疑问是,我测试的时候打开了 活动监视器 查看mysqld的线程情况,使用php连接mysql的测试,只有16个线程操作,CPU使用率在10%~12%之间,而使用lua_resty_mysql 100个poll线程操作,CPU占有率是10%~13%之间。。。CPU使用效率差不多,但是如果用成功数除以线程数,php的线程似乎更高效。。。我怎么觉得有点毁三观的感觉。。。。


测试情况如下:

原生php连接mysql的测试情况
$ webbench -c 500 -t 30  http://localhost/mysql_test.php
    Speed=17566 pages/min, 135435 bytes/sec.
    Requests: 6327 susceed, 2456 failed.

测试脚本
$con = mysql_connect('127.0.0.1','root','');
mysql_select_db('aicaike_test', $con);
$result = mysql_query('SELECT * FROM `user` WHERE `id`=555555', $con);

print_r(mysql_fetch_array($result, MYSQL_ASSOC));


用lua_resty_mysql的测试情况
Speed=36100 pages/min, 306836 bytes/sec.
Requests: 14979 susceed, 3071 failed.
        location /api/users
        {
            content_by_lua '
                local mysql = require "resty.mysql"
                local db,err = mysql:new()
                if not db then
                    ngx.say("get mysql instance false")
                    return
                end

                db:set_timeout(1000)

                local ok, err = db:connect{
                    host = "127.0.0.1",
                    port = 3306,
                    database = "aicaike_test",
                    user = "root",
                    password = "" }

                if not ok then
                    ngx.say("connect error:",err)
                    return
                end

                local sql = "";

                if ngx.var.arg_userid then
                    sql = "SELECT * FROM user WHERE id = " .. tonumber(ngx.var.arg_userid)
                else
                    sql = "SELECT * FROM user LIMIT 30"
                end

                local res, err = db:query(sql);

                if not res then
                    ngx.say("query error: ", err)
                    return
                end

                local cjson = require "cjson"
                ngx.say(cjson.encode(res))

                local ok, err = db:set_keepalive(0, 100)
                if not ok then
                    ngx.say("failed to set keepalive: ", err)
                    return
                end

            ';
        }


agentzh

unread,
May 17, 2013, 2:53:23 PM5/17/13
to openresty
Hello!

2013/5/17 Barbery:
> 我是一个新手,如果有什么说错的,请大家多多包涵。也希望大家解答下我的疑问,满足我这个小小的好奇心。。。
> 我的疑问是,我测试的时候打开了 活动监视器
> 查看mysqld的线程情况,使用php连接mysql的测试,只有16个线程操作,CPU使用率在10%~12%之间,而使用lua_resty_mysql
> 100个poll线程操作,CPU占有率是10%~13%之间。。。CPU使用效率差不多,但是如果用成功数除以线程数,php的线程似乎更高效。。。我怎么觉得有点毁三观的感觉。。。。
> 测试情况如下:
> 原生php连接mysql的测试情况
> $ webbench -c 500 -t 30 http://localhost/mysql_test.php
> Speed=17566 pages/min, 135435 bytes/sec.
[...]
> 用lua_resty_mysql的测试情况
> $ webbench -c 500 -t 30 http://localhost/api/users?userid=555555
> Speed=36100 pages/min, 306836 bytes/sec.

根据你的测试结果,lua-resty-mysql 每秒处理的请求数和数据吞吐量是你的原生 php 的一倍以上,对应到
mysqld,其请求处理速度也是一样的。在这种情况下比较 CPU 占用不太公平吧?

这就好比是张三以 1 米每秒的速度漫步,而李四以 5 米每秒的速度狂奔,此时你如果比较二人的能量消耗水平,其实并没太大意义一样。

同时,拿 mysqld 服务器的性能去衡量 mysql 驱动的效率也是比较奇怪的事情。毕竟 mysql 驱动使用 mysql
服务器的方式一般都是相同的(mysql 定义了统一的通信协议)。

另外,你应当研究一下为什么会有那些失败的请求,比如查看 nginx 的错误日志。(同时,我注意到你的 php 代码未设置查询超时保护,而
lua-resty-mysql 中设置了 1 秒的超时,即那一句“db:set_timeout(1000)”。)

还有就是,像压测 30 秒这么长的时间(如果你的 webbench 命令行的 -t 选项是秒为单位的话),应当启用 http
keepalive(我没用过 webbench,但我知道在 ab 和 weighttp 工具中可以指定 -k
选项),否则很容易把你系统的动态端口用尽。

Best regards,
-agentzh

Barbery

unread,
May 18, 2013, 7:48:05 AM5/18/13
to open...@googlegroups.com
谢谢春哥的详细回复。。。我再仔细思考思考~~~

在 2013年5月18日星期六UTC+8上午2时53分23秒,agentzh写道:

Barbery

unread,
May 18, 2013, 8:27:15 AM5/18/13
to open...@googlegroups.com
我看了下日志,请求lua_resty_mysql 的话,失败的请求报这个错误
2013/05/18 20:07:26 [error] 2616#0: *92494 kevent() reported that connect() failed, client: 127.0.0.1, server: localhost, request: "GET /api/users?userid=555555 HTTP/1.0", host: "localhost"
请问上面这个错误说的connect failed是指连接nginx还是lua连接mysql的失败?我把worker 从1024提升到10240似乎没效果,这说明是lua连接mysql失败?这个瓶颈应该是调哪个参数解决呢?

而请求PHP的话,失败报错误
2013/05/18 20:08:13 [error] 3124#0: *95539 kevent() reported about an closed connection (54: Connection reset by peer) while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /mysql_test.php HTTP/1.0", upstream: "fastcgi://127.0.0.1:9000", host: "localhost"
这个错误是指nginx连接php时被重置?瓶颈在php这边??

上面这2个错误,我google许久,都还是迷迷糊糊的,不了解这2个错误是什么意思,有懂的同学,希望不吝赐教!!!谢谢!!!



在 2013年5月18日星期六UTC+8上午2时53分23秒,agentzh写道:

agentzh

unread,
May 18, 2013, 1:30:05 PM5/18/13
to openresty
Hello!

2013/5/18 Barbery:
> 我看了下日志,请求lua_resty_mysql 的话,失败的请求报这个错误
> 2013/05/18 20:07:26 [error] 2616#0: *92494 kevent() reported that connect()
> failed, client: 127.0.0.1, server: localhost, request: "GET
> /api/users?userid=555555 HTTP/1.0", host: "localhost"
> 请问上面这个错误说的connect failed是指连接nginx还是lua连接mysql的失败?

看起来应是 nginx 连接后端时失败。

建议把你的 Lua 代码中的下面这几行代码

if not ok then
ngx.say("connect error:",err)
return
end

替换为

if not ok then
ngx.log(ngx.ERR, "connect error:",err)
return ngx.exit(500)
end

你应该就可以在错误日志文件里看到具体的错误消息了。

> 我把worker
> 从1024提升到10240似乎没效果,这说明是lua连接mysql失败?这个瓶颈应该是调哪个参数解决呢?
>

瓶颈很可能在 mysqld 服务一侧。典型的情形是 mysqld 的监听 socket 的 accept 队列溢出。貌似你是在 BSD
家族的系统上,如果你的系统上有 dtrace 的话,应当可以使用 dtrace 进行实时分析,就像我们在 Linux 系统上基于
systemtap 的工具 ngx-accept-queue 所做的那样:

https://github.com/agentzh/nginx-systemtap-toolkit#ngx-accept-queue

或许你的系统上有现成的工具可以直接使用。

> 而请求PHP的话,失败报错误
> 2013/05/18 20:08:13 [error] 3124#0: *95539 kevent() reported about an closed
> connection (54: Connection reset by peer) while reading response header from
> upstream, client: 127.0.0.1, server: localhost, request: "GET
> /mysql_test.php HTTP/1.0", upstream: "fastcgi://127.0.0.1:9000", host:
> "localhost"
> 这个错误是指nginx连接php时被重置?瓶颈在php这边??
>

是的,问题很可能在 php 一侧。我不觉得你的 php 服务能处理较高的并发。不过你还是需要使用系统分析工具加以确认 :)

Best regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages