在基于Pylons的服务器上测试使用DBUtils前后的性能对比

在基于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之后数据库的访问性能有了很大的提高。

Leave a Reply