在基于Pylons的服务器上测试使用DBUtils前后的性能对比
Sunday, September 30th, 2007在基于Pylons的服务器上测试使用DBUtils前后的性能
为了测试使用DBUtils实现的数据库连接池的性能,在Pylons写了一个测试服务,并将服务器架设在lab2服务器上,使用apache ab进行服务器压力测试。
1 测试环境
lab2服务器,MySQL 4.1.20,Pylons 0.9.4.1,apache ab 2.0.59。
为了确保测试的可靠性,每次测试之前都重启服务器。
在Pylons上假设的应用有3个URL用于测试,分别如下:
URL | 说明 |
---|---|
/testdb/test1 | 不使用连接池,每次访问都建立对数据库的连接 |
/testdb/test2 | 使用DBUtils.PersistentDB连接池,线程专用连接 |
/testdb/test3 | 使用DBUtils.PooledDB连接池,线程间共享连接 |
测试代码如下:
from helloworld.lib.base import * import time import random import MySQLdb import DBUtils.PersistentDB import DBUtils.PooledDB conn_kwargs={'host':'192.168.1.239','user':'ro','passwd':'','db':'test','port':3306} sql="""SELECT * FROM test_table WHERE id=%d""" persist=DBUtils.PersistentDB.PersistentDB(dbapi=MySQLdb,maxusage=1000,**conn_kwargs) pooled=DBUtils.PooledDB.PooledDB(dbapi=MySQLdb,maxusage=1000,**conn_kwargs) def query(conn): cur=conn.cursor() cur.execute(sql%(random.randint(1,1000))) data=cur.fetchall() cur.close() return data class TestdbController(BaseController): def index(self): return Response('index') def test1(self): conn=MySQLdb.connect(**conn_kwargs) data=query(conn) conn.close() return Response(str(data)) def test2(self): conn=persist.connection() data=query(conn) conn.close() return Response(str(data)) def test3(self): conn=pooled.connection() data=query(conn) conn.close() return Response(str(data))
2 10线程并发
一共10000次测试,测试所用命令如下:
./ab -n 10000 -c 10 http://192.168.1.239:5000/testdb/test*
测试结果如下:
测试目标 | 总时间 | 请求处理速度 | 平均处理时间 | 错误率 | 100% | 99% | 90% | 50% |
---|---|---|---|---|---|---|---|---|
/test1 | 32.764 | 305.22 | 32.764 ms | 10.32% | 776 | 237 | 40 | 29 |
/test2 | 27.895 | 358.49 | 27.895 ms | 10.00% | 3032 | 222 | 31 | 22 |
/test3 | 29.513 | 338.83 | 29.513 ms | 10.46% | 3037 | 58 | 36 | 27 |
3 50线程并发
一共10000次测试,测试所用命令如下:
./ab -n 10000 -c 50 http://192.168.1.239:5000/testdb/test*
测试结果如下:
测试目标 | 总时间 | 请求处理速度 | 平均处理时间 | 错误率 | 100% | 99% | 90% | 50% |
---|---|---|---|---|---|---|---|---|
/test1 | 32.786 | 305.00 | 163.932 ms | 9.48% | 21031 | 3048 | 49 | 31 |
/test2 | 27.884 | 358.62 | 139.424 ms | 9.65% | 9227 | 3032 | 33 | 22 |
/test3 | 29.256 | 341.81 | 146.281 ms | 9.88% | 3654 | 328 | 151 | 136 |
4 远程10线程并发
一共10000次测试,测试所用命令如下:
./ab -n 10000 -c 10 http://192.168.1.241:5000/testdb/test*
测试结果如下:
测试目标 | 总时间 | 请求处理速度 | 平均处理时间 | 错误率 | 100% | 99% | 90% | 50% |
---|---|---|---|---|---|---|---|---|
/test1 | 24.891 | 401.75 | 24.891 ms | 9.07% | 3035 | 44 | 31 | 22 |
/test2 | 21.652 | 461.85 | 21.652 ms | 9.86% | 256 | 59 | 26 | 19 |
/test3 | 23.952 | 432.99 | 23.095 ms | 9.59% | 239 | 38 | 28 | 22 |
5 远程50线程并发
一共10000次测试,测试命令如下:
./ab -n 10000 -c 50 http://192.168.1.241:5000/testdb/test*
测试结果如下:
测试目标 | 总时间 | 请求处理速度 | 平均处理时间 | 错误率 | 100% | 99% | 90% | 50% |
---|---|---|---|---|---|---|---|---|
/test1 | 24.915 | 401.36 | 124.575 ms | 9.82% | 9280 | 3033 | 53 | 27 |
/test2 | 21.521 | 464.66 | 107.607 ms | 9.47% | 9621 | 3022 | 32 | 20 |
/test3 | 22.808 | 438.45 | 114.038 ms | 9.11% | 9107 | 145 | 114 | 95 |
6 干扰因素
测试过程中发现,MySQL服务器的同时并发连接数一直没有超过10,所以在进行50线程并发操作时可能会出现一些干扰。
7 单线程测试
使用代码如下:
import time import random import MySQLdb import DBUtils.PersistentDB import DBUtils.PooledDB conn_kwargs={'host':'192.168.1.239','user':'ro','passwd':'','db':'test','port':3306} sql="""SELECT * FROM test_table WHERE id=%d""" persist=DBUtils.PersistentDB.PersistentDB(dbapi=MySQLdb,maxusage=1000,**conn_kwargs) pooled=DBUtils.PooledDB.PooledDB(dbapi=MySQLdb,maxusage=1000,**conn_kwargs) def query(conn): cur=conn.cursor() cur.execute(sql%(random.randint(1,1000))) data=cur.fetchall() cur.close() return data def print_now(): print time.strftime("%H:%M:%S") return def test1(times): print_now() for i in range(0,times): conn=MySQLdb.connect(**conn_kwargs) query(conn) conn.close() print_now() return def test2(times): print_now() for i in range(0,times): conn=persist.connection() query(conn) conn.close() print_now() return def test3(times): print_now() for i in range(0,times): conn=pooled.connection() query(conn) conn.close() print_now() return
8 单线程测试
执行10000次查询,进入Python交互模式,调用各个函数并传递执行次数,每次执行过后重启MySQL服务器:
# python -i ttss.py >>> test1(10000) 18:59:30 18:59:40 >>> test2(10000) 19:00:16 19:00:19 >>> test3(10000) 19:00:46 19:00:49
可见查询次数太少,以致难以精确测定时间,所以执行100000次查询,过程如下:
# python -i ttss.py >>> test1(100000) 19:01:57 _mysql_exceptions.OperationalError: (2003, "Can't connect to MySQL server on '192.168.1.239' (99)")
连续两次都出现异常,之后改为30000也是如此。出现这个异常之后数据库服务器不经过重启就无法再使用了。经过测试发生这种连接异常之后,还是可以使用mysql客户端登录本机的MySQL服务器的。所以改为20000次查询,过程如下:
# python -i ttss.py >>> test1(20000) 19:06:47 19:07:07 >>> test2(20000) 19:28:23 19:28:28 >>> test3(20000) 19:29:27 19:29:34
测试远程连接MySQL服务器:
# python -i ttss.py >>> test1(10000) 20:25:23 20:25:57 >>> test2(10000) 20:27:18 20:27:26 >>> test3(10000) 20:27:46 20:27:56
9 结论
总体上来看,使用了DBUtils之后数据库的访问性能有了很大的提高。