引言
手头上的项目有一些采用django框架编写, 如果说并发量比较小的时候简单的runserver是可以应对的.
那么当并发达到一两千的时候,该怎么提高django的并发能力呢?
Overview
- 环境说明:
- python: 3.5
- django: 1.8.2
- gunicorn: 19.7.1
- 系统:
- 服务器: centos 4核
- 压测机器: centos 4核
- 压测环境
- siege/ysab
- 4核centos测试机
- 为什么用django
- 开发效率高
- 好上手
- 关于gunicorn
- Gunicorn ‘Green Unicorn’ is a Python WSGI HTTP Server for UNIX.It’s a pre-fork worker model. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy.(这是官方给出的回答)
压测方式及命令
- 压测方式:
- 压测命令:
- siege: siege -c255 -t200S -v -b ‘http://B_ip:8080/test POST appid=111’
- ysab: ysab -n 900 -m POST -u http://B_ip:8080/test -d ‘{“appid”: “111”, “other”: “other”}’
- 备注: 欢迎使用ysab, ysab文档
本次实验业务场景
代码展示
settings部分
1 | # 这里我们用mysql,其他配置都是默认 |
models部分
1 | class Test(models.Model): |
views部分
1 | class Test(APIView): |
开始压测
数据说明
1 | 目前数据库test表的数据量是, 其中id是自增主键 |
runserver 方式压测结果
1 | Lifting the server siege... done. |
gunicorn + gevent (4个worker)
1 | Lifting the server siege... done. |
gunicorn + gthread (4个worker, –threads=50)
启动方式
官方有相应说明1
gunicorn --env DJANGO_SETTINGS_MODULE=ce.settings ce.wsgi:application -w 4 -b 0.0.0.0:8080 -k gthread --threads 40 --max-requests 4096 --max-requests-jitter 512
压测结果
1 | 启动方式: |
gunicorn + gthread + CONN_MAX_AGE(4个worker, –threads=50)
关于CONN_MAX_AGE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16CONN_MAX_AGE: 复用数据库链接
Lifting the server siege... done.
Transactions: 110289 hits
Availability: 99.62 %
Elapsed time: 99.65 secs
Data transferred: 1.47 MB
Response time: 0.23 secs
Transaction rate: 1106.76 trans/sec # 这次又提升了不少啊
Throughput: 0.01 MB/sec
Concurrency: 253.84
Successful transactions: 110289
Failed transactions: 422
Longest transaction: 3.85
Shortest transaction: 0.01
能不能gunicorn+gevent+CONN_MAX_AGE(4个worker)
这里我不建议使用,这样的话你的数据库连接数会飚的很高,服务会挂的很惨, 毕竟数据库是不会允许
无休止的建立连接的。前边的提高手段无非用的多线程,如果一定要用协程(gevent)的方式呢,能不
能解决数据库连接数过高的问题,而且还能有不错的性能呢?可以看一下这篇文章:
gunicorn+gevent+django解决mysql高连接数问题
如何再次增加并发量
采用nginx做负载
去掉自增主键
原因很简单,因为自增主键的存在写库存在抢锁, 可以利用全局id生成器提前生成id直接写入数据库
换成异步任务去写库
如果数据只是存在mysql中做备份,建议使用异步的方式写入库,先把数据写到缓存下发给用户,之后在
利用后台异步任务一点点的写入,例如聊天系统可以这样干
换成更高效的框架或者语言
可以试试tornado, 如果tornado依然无法满足,可以尝试使用golango,毕竟golang是以高并发著称,
而且是编译语言,而且基于它的web框架也很容易上手,性能很可观,例如Gin
Gin
文章推荐
关于gunicorn的worker调度
gunicorn+gevent+django解决mysql高连接数并提高性能
nginx+tornado折腾笔记(较gunicorn+django进一步提升服务并发量)
Golang高性能框架gin(更高qps解决办法)