searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享

利用Gunicorn提高Django的并发性能

2023-07-05 01:00:10
62
0

前提说明

  • 环境说明:
    • 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://xxx:8080/t POST appid=111'
    • ysab: ysab -n 900 -m POST -u 'http://xxx:8080/t -d '{"appid": "111", "other": "other"}'

本次实验业务场景

lc

一些配置

settings部分

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'ce',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '192.168.96.95',
        'PORT': '3306',
    }
}

models部分

class Test(models.Model):
    url = models.CharField(max_length=228, blank=True, null=True)
    img_url = models.CharField(max_length=228, blank=True, null=True)
    title = models.CharField(max_length=228, blank=True, null=True)
    content = models.CharField(max_length=228, blank=True, null=True)

    class Meta:
        db_table = 'test'
        verbose_name = "test表"

    def __unicode__(self):
        return self.id

views部分

class Test(APIView):

    def post(self, requsts):
        Test.objects.create(
            **{'url': str(1000000 * time.time())})
        return Response({"status": 200})

压测

数据说明

MySQL [ce]> select id from test order by id desc limit 2;
+--------+
| id             |
+--------+
| 627775     |
| 627774     |
+--------+

runserver方式压测结果

Lifting the server siege... done.
 
Transactions: 24041 hits
Availability: 99.93 %
Elapsed time: 99.60 secs
Data transferred: 0.32 MB
Response time: 1.03 secs
Transaction rate: 241.38 trans/sec# 并发量只有241
Throughput: 0.00 MB/sec
Concurrency: 248.94
Successful transactions: 24041
Failed transactions: 16
Longest transaction: 32.55
Shortest transaction: 0.05

gunicorn + gevent (4个worker)

Lifting the server siege... done.

Transactions: 23056 hits
Availability: 100.00 %
Elapsed time: 99.49 secs
Data transferred: 0.31 MB
Response time: 1.09 secs
Transaction rate: 231.74 trans/sec # 并发量只有231
Throughput: 0.00 MB/sec
Concurrency: 252.95
Successful transactions: 23056
Failed transactions: 0
Longest transaction: 8.21
Shortest transaction: 0.01

gunicorn + gthread (4个worker, –threads=50)

启动方式

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

压测结果

Transactions: 28231 hits
Availability: 95.67 %
Elapsed time: 30.71 secs
Data transferred: 0.41 MB
Response time: 0.27 secs
Transaction rate: 919.28 trans/sec # 提高了不少吧,能不能在提高?
Throughput: 0.01 MB/sec
Concurrency: 251.06
Successful transactions: 28231
Failed transactions: 1278 # 但是失败的有些多
Longest transaction: 8.06
Shortest transaction: 0.01

gunicorn + gthread + CONN_MAX_AGE(4个worker, –threads=50)

CONN_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做负载

nginx负载

去掉自增主键

原因很简单,因为自增主键的存在写库存在抢锁, 可以利用全局id生成器提前生成id直接写入数据库

换成异步任务去写库

如果数据只是存在mysql中做备份,建议使用异步的方式写入库,先把数据写到缓存下发给用户,之后在
利用后台异步任务一点点的写入,例如聊天系统可以这样干

换成更高效的框架或者语言

可以试试tornado, 如果tornado依然无法满足,可以尝试使用golango,毕竟golang是以高并发著称,
而且是编译语言,而且基于它的web框架也很容易上手,性能很可观,例如Gin

0条评论
作者已关闭评论
yunson
9文章数
0粉丝数
yunson
9 文章 | 0 粉丝

利用Gunicorn提高Django的并发性能

2023-07-05 01:00:10
62
0

前提说明

  • 环境说明:
    • 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://xxx:8080/t POST appid=111'
    • ysab: ysab -n 900 -m POST -u 'http://xxx:8080/t -d '{"appid": "111", "other": "other"}'

本次实验业务场景

lc

一些配置

settings部分

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'ce',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '192.168.96.95',
        'PORT': '3306',
    }
}

models部分

class Test(models.Model):
    url = models.CharField(max_length=228, blank=True, null=True)
    img_url = models.CharField(max_length=228, blank=True, null=True)
    title = models.CharField(max_length=228, blank=True, null=True)
    content = models.CharField(max_length=228, blank=True, null=True)

    class Meta:
        db_table = 'test'
        verbose_name = "test表"

    def __unicode__(self):
        return self.id

views部分

class Test(APIView):

    def post(self, requsts):
        Test.objects.create(
            **{'url': str(1000000 * time.time())})
        return Response({"status": 200})

压测

数据说明

MySQL [ce]> select id from test order by id desc limit 2;
+--------+
| id             |
+--------+
| 627775     |
| 627774     |
+--------+

runserver方式压测结果

Lifting the server siege... done.
 
Transactions: 24041 hits
Availability: 99.93 %
Elapsed time: 99.60 secs
Data transferred: 0.32 MB
Response time: 1.03 secs
Transaction rate: 241.38 trans/sec# 并发量只有241
Throughput: 0.00 MB/sec
Concurrency: 248.94
Successful transactions: 24041
Failed transactions: 16
Longest transaction: 32.55
Shortest transaction: 0.05

gunicorn + gevent (4个worker)

Lifting the server siege... done.

Transactions: 23056 hits
Availability: 100.00 %
Elapsed time: 99.49 secs
Data transferred: 0.31 MB
Response time: 1.09 secs
Transaction rate: 231.74 trans/sec # 并发量只有231
Throughput: 0.00 MB/sec
Concurrency: 252.95
Successful transactions: 23056
Failed transactions: 0
Longest transaction: 8.21
Shortest transaction: 0.01

gunicorn + gthread (4个worker, –threads=50)

启动方式

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

压测结果

Transactions: 28231 hits
Availability: 95.67 %
Elapsed time: 30.71 secs
Data transferred: 0.41 MB
Response time: 0.27 secs
Transaction rate: 919.28 trans/sec # 提高了不少吧,能不能在提高?
Throughput: 0.01 MB/sec
Concurrency: 251.06
Successful transactions: 28231
Failed transactions: 1278 # 但是失败的有些多
Longest transaction: 8.06
Shortest transaction: 0.01

gunicorn + gthread + CONN_MAX_AGE(4个worker, –threads=50)

CONN_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做负载

nginx负载

去掉自增主键

原因很简单,因为自增主键的存在写库存在抢锁, 可以利用全局id生成器提前生成id直接写入数据库

换成异步任务去写库

如果数据只是存在mysql中做备份,建议使用异步的方式写入库,先把数据写到缓存下发给用户,之后在
利用后台异步任务一点点的写入,例如聊天系统可以这样干

换成更高效的框架或者语言

可以试试tornado, 如果tornado依然无法满足,可以尝试使用golango,毕竟golang是以高并发著称,
而且是编译语言,而且基于它的web框架也很容易上手,性能很可观,例如Gin

文章来自个人专栏
技术与生活
9 文章 | 1 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0