gunicorn

 gunicorn 

1.      简介

官网:https://gunicorn.org/#docs

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.

它是一个pythonWSGI HTTP Server,运行于UNIX平台。pre-fork worker model。

 

Gunicorn是一个unix上被广泛使用的高性能的Python WSGI UNIX HTTP Server。

和大多数的web框架兼容,并具有实现简单,轻量级,高性能等特点。

 

1.1.    相关概念

架构

服务模型(Server Model)

Gunicorn是基于pre-fork模型的。也就意味着有一个中心管理进程(masterprocess)用来管理worker进程集合。Master从不知道任何关于客户端的信息。所有的请求和响应处理都是由worker进程来处理的。

Master(管理者)

主程序是一个简单的循环,监听各种信号以及相应的响应进程。master管理着正在运行的worker集合,通过监听各种信号比如TTIN,TTOU,andCHLD.TTINandTTOU响应的增加和减少worker的数目。CHLD信号表明一个子进程已经结束了,在这种情况下master会自动的重启失败的worker。

worker

woker有很多种,包括:ggevent、geventlet、gtornado等等。这里主要分析ggevent。

每个ggeventworker启动的时候会启动多个server对象:worker首先为每个listener创建一个server对象(注:为什么是一组listener,因为gunicorn可以绑定一组地址,每个地址对于一个listener),每个server对象都有运行在一个单独的geventpool对象中。真正等待链接和处理链接的操作是在server对象中进行的。

 

1.2.    gunicorn安装

pip install gunicorn

 

示例:

wsgi_my.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from app import create_app

application = app = create_app()

 

1.2.1.   测试运行

gunicorn wsgi_my:app

默认绑定127.0.0.1,所以不能在其它ip访问

测试结果:

[root@soft ~]# curl http://localhost:8000

Index.

[root@soft ~]# curl http://localhost:8000/hello

Hello. number: 1

[root@soft ~]# curl http://localhost:8000/hello

Hello. number: 2

 

1.3.    使用及配置

 

doc: https://docs.gunicorn.org/en/stable/run.html

gunicorn

最简单的运行方式:gunicorn code:application

 

Gunicorn从三个不同地方获取配置:

框架设置(通常只影响到Paster应用)

配置文件(python文件):配置文件中的配置会覆盖框架的设置。

命令行

框架设置只跟Paster(一个Web框架)有关,不讨论;命令行配置如上部分所示;

 

1.3.1.   命令行常用配置参数:

-c CONFIG, --config=CONFIG - Specify a config file in the form $(PATH), file:$(PATH), or python:$(MODULE_NAME).指定配置文件

-b BIND, --bind=BIND - Specify a server socket to bind. Server sockets can be any of $(HOST), $(HOST):$(PORT)指定监听端口.

-w WORKERS, --workers=WORKERS - The number of worker processes. This number should generally be between 2-4 workers per core in the server. Check the FAQ for ideas on tuning this parameter.指定进程数,一般建议数量设置为2*CPU+1

-k WORKERCLASS, --worker-class=WORKERCLASS - The type of worker process to run. You’ll definitely want to read the production page for the implications of this parameter. You can set this to $(NAME) where $(NAME) is one of sync, eventlet, gevent, tornado, gthread, gaiohttp (deprecated). sync is the default. See the worker_class documentation for more information.

工作模式,有多种,默认sync,一般gevent,tornado。

 

--backlog INT 指定最大挂起的连接数;

--log-level LEVEL:debug,info,warning,error,critical

--access-logfile FILE 日志文件,-表示输出到标准输出

--error-logfile FILE 错误日志文件

典型启动命令:

gunicorn -w 1 -k gevent wsgi_my  -b 0.0.0.0:9000

 

1.3.2.   配置文件启动

生产中通常通过配置文件指定参数,它必须是一个python文件,只是将命令行中的参数写进py文件中而已,如果需要设置哪个参数,则在py文件中为该参数赋值即可。

配置文件案例:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

 # gunicorn 配置文件

 import multiprocessing

 

debug = True

loglevel = 'debug'

bind = "0.0.0.0:9000"

# 最大挂起连接数

backlog = 512

 

# 日志

pidfile = "log/gunicorn.pid"

accesslog = "log/access.log"

errorlog = "log/debug.log"

#daemon = True

daemon = False

 

 

# 启动的进程数

workers = multiprocessing.cpu_count()

worker_class = 'gevent'

# 进程沉默限制时间,超过会重启该worker,单位秒,通常设为30

timeout = 30

 

x_forwarded_for_header = 'X-FORWARDED-FOR'

 

启动server

gunicorn -c gunicorn_conf.py wsgi_my:app

注意:指定app时不要有后缀名(例如wsgi_my.py),否则会找不到app

日志文件需要手动创建

 

2.      测试

2.1.    并发模式测试1-验证可用性

测试环境准备:

  1. 在路由函数中添加阻塞代码time.sleep(2)
  2. 请求使用deferred模拟并发,具体代码见下文;

 

flask自带server及uWSGI是不支持并发的;

直接运行app:python run.py

测试结果:

测试并发请求数:5 测试耗时:10.08759880065918

 

使用gvent模式

[root@soft website]# gunicorn -w 1 -k gevent wsgi_my  -b 0.0.0.0:9000

测试并发请求数:5 测试耗时:2.1450159549713135

 

结果释义:

阻塞模式下不能同时处理多个请求,所以耗时为2*5,最终大约为10;

协程模式下可以同时处理多个请求,所以耗时为2*1,最终大约为2;

 

2.1.1.   并发测试代码

import time
from twisted.internet import defer, reactor
from twisted.web.client import getPage

# 测试url
url = b"http://192.168.199.129:9000/hello"

def time_count(*args, **kw):
    print('测试结束。')
    t = time.time()
    print("测试并发请求数:{} 测试耗时:{}".format(kw['req_nums'], t - kw['t_start']))

t_start = time.time()
d = defer.DeferredList([getPage(url) for x in range(5)])
#d = getPage(url)
d.addCallbacks(time_count, lambda x:print('error'), callbackKeywords={'req_nums':5, 't_start':t_start})
 

reactor.callLater(20, reactor.stop)

reactor.run()

 

2.2.    性能测试

主要测试flask+ gunicorn与werkzurg的性能。

 

2.2.1.   python自带web server

E:\Apache24\bin>ab -n 3000 -c 50 http://192.168.199.129:9000/req_test

This is ApacheBench, Version 2.3 <$Revision: 1843412 $>

 

Benchmarking 192.168.199.129 (be patient)

Completed 3000 requests

Finished 3000 requests

 

Server Software:        Werkzeug/0.14.1

Server Hostname:        192.168.199.129

Server Port:            9000

 

Document Path:          /req_test

Document Length:        27 bytes

 

Concurrency Level:      50

Time taken for tests:   27.518 seconds

Complete requests:      3000

Failed requests:        2951

   (Connect: 0, Receive: 0, Length: 2951, Exceptions: 0)

Total transferred:      548002 bytes

HTML transferred:       86002 bytes

Requests per second:    109.02 [#/sec] (mean)

Time per request:       458.632 [ms] (mean)

Time per request:       9.173 [ms] (mean, across all concurrent requests)

Transfer rate:          19.45 [Kbytes/sec] received

 

Connection Times (ms)

              min  mean[+/-sd] median   max

Connect:        0    1   3.0      1      73

Processing:    35  454  72.2    429     683

Waiting:        4  453  72.1    427     680

Total:         35  455  72.4    430     684

 

Percentage of the requests served within a certain time (ms)

  50%    430

  66%    457

  75%    499

  80%    518

  90%    569

  95%    592

  98%    613

  99%    628

 100%    684 (longest request)

 

2.2.2.   gunicorn gevent模式

gunicorn -w 1 -k gevent wsgi_my  -b 0.0.0.0:9000

E:\Apache24\bin>ab -n 3000 -c 50 http://192.168.199.129:9000/req_test

This is ApacheBench, Version 2.3 <$Revision: 1843412 $>

Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Licensed to The Apache Software Foundation, http://www.apache.org/

 

Benchmarking 192.168.199.129 (be patient)

Finished 3000 requests

 

Concurrency Level:      50

Time taken for tests:   10.541 seconds

Complete requests:      3000

Failed requests:        2991

   (Connect: 0, Receive: 0, Length: 2991, Exceptions: 0)

Total transferred:      565893 bytes

HTML transferred:       85893 bytes

Requests per second:    284.60 [#/sec] (mean)

Time per request:       175.688 [ms] (mean)

Time per request:       3.514 [ms] (mean, across all concurrent requests)

Transfer rate:          52.43 [Kbytes/sec] received

 

Connection Times (ms)

              min  mean[+/-sd] median   max

Connect:        0    1   0.4      1       3

Processing:    32  174  16.6    171     277

Waiting:        2  173  16.7    170     277

Total:         32  174  16.6    172     278

 

Percentage of the requests served within a certain time (ms)

  50%    172

  66%    174

  75%    176

  80%    177

  90%    184

  95%    190

  98%    217

  99%    276

 100%    278 (longest request)

 

2.2.3.   测试结果解析

 

无论是从任务总时长,单个任务耗时各项指标上看,gevent模式是大大优于同步阻塞模式的。至于说具体优化比例要取决于各项因素了,这里的实验环境只是一台虚拟机,不具有实际应用意义。

 

3.      总结

常用命令

gunicorn -w 1 -k gevent wsgi_my  -b 0.0.0.0:9000

gunicorn -c gunicorn_conf.py wsgi_my

 

posted @ 2019-08-30 20:50  木林森__𣛧  阅读(507)  评论(0编辑  收藏  举报