zoukankan      html  css  js  c++  java
  • 高性能框架gevent和gunicorn在web上的应用及性能测试

    WSGI Server有哪些:

    比如 Flask,webpy,Django、CherryPy 都带着 WSGI server 。当然性能都不好,自带的web server 更多的是测试用途, 发布时则使用生产环境的 WSGI server或者是联合nginx做uwsgi 。

    诚如那个WSGI的定义所说的,协议定义了一套接口来实现服务器端与应用端通信的规范化(或者说是统一化)。这是怎样的一套接口呢?很简单,尤其是对于应用端。

    源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

    神器 Gunicorn是一个Python WSGI UNIX的HTTP服务器。这是一个预先叉工人模式,从Ruby的独角兽(Unicorn)项目移植。该Gunicorn服务器与各种Web框架兼容,我们只要简单配置执行,轻量级的资源消耗,以及相当迅速。它的特点是与各个web结合紧密,部署特别方便。 缺点也很多,不支持HTTP 1.1,并发访问性能不高。

    安装 gunicorn  ~

    pip install gunicorn

    这里我们说下 gunicorn 的用法

    最简单的运行方式就是:

    gunicorn code:application

    其中code就是指code.py,application就是那个wsgifunc的名字。

    这样运行的话, gunicorn 默认作为一个监听 127.0.0.1:8000 的web server,可以在本机通过: http://127.0.0.1:8000 访问。

    如果要通过网络访问,则需要绑定不同的地址(也可以同时设置监听端口):

    gunicorn -b 10.2.20.66:8080 code:application
    #from http://rfyiamcool.blog.51cto.com

    在多核服务器上,为了支持更多的并发访问并充分利用资源,可以使用更多的 gunicorn 进程:

    gunicorn -w 8 code:application

    这样就可以启动8个进程同时处理HTTP请求,提高系统的使用效率及性能。

    另外, gunicorn 默认使用同步阻塞的网络模型(-k sync),对于大并发的访问可能表现不够好, 它还支持其它更好的模式,比如:gevent或meinheld。

    源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

    #  gevent

    gunicorn -k gevent code:application

    #  meinheld

    gunicorn -k egg:meinheld#gunicorn_worker code:application

    当然,要使用这两个东西需要另外安装,具体请参考各自的文档。

    以上设置还可以通过 -c 参数传入一个配置文件实现。

    gunicorn 的配置文件 

    [root@66 tmp]# cat gun.conf
    import os
    bind = '127.0.0.1:5000'
    workers = 4
    backlog = 2048
    worker_class = "sync"
    debug = True
    proc_name = 'gunicorn.proc'
    pidfile = '/tmp/gunicorn.pid'
    logfile = '/var/log/gunicorn/debug.log'
    loglevel = 'debug'

    python web 一个例子 

    [root@66 tmp]# cat xiaorui.py
    from flask import Flask
    from flask import render_template_string
    import os
    from werkzeug.contrib.fixers import ProxyFix
    app = Flask(__name__)
    @app.route('/')
    def index():
        return "worked!"
    app.wsgi_app = ProxyFix(app.wsgi_app)
    if __name__ == '__main__':
        app.run()

    先跑本身的demo ~ 

    源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

    结果是:

    结果还算可以~    当然跑的实例也简单~

    cpu的损耗,不小哈~

    其次的问题是,flask的web server在压力下出现回应的错误。。。 我以前测试 tornado web.py flask django botto的压力,让朋友写的cc工具做的测试。。。

    结果是  tornado确实很牛,然后是flask,接着是web.py,最烂的是django

    django本身的抗压确实让人蛋疼,还好大家在nginx做负载。

    单实例测试完了,咱们开始测试 高性能神器 gunicorn 做wsgi

    启动后会出现:

    2013-08-12 21:59:34 [2097] [INFO] Starting gunicorn 17.5
    2013-08-12 21:59:34 [2097] [DEBUG] Arbiter booted
    2013-08-12 21:59:34 [2097] [INFO] Listening at: http://127.0.0.1:5000 (2097)
    2013-08-12 21:59:34 [2097] [INFO] Using worker: sync
    2013-08-12 21:59:34 [2102] [INFO] Booting worker with pid: 2102
    2013-08-12 21:59:34 [2103] [INFO] Booting worker with pid: 2103
    2013-08-12 21:59:34 [2104] [INFO] Booting worker with pid: 2104
    2013-08-12 21:59:34 [2105] [INFO] Booting worker with pid: 2105

    我们再来测试下性能~

    上次用了6秒左右,这次用gunicorn达到了2.4秒左右。。。。。 这速度对比,已经很明了了~

    要是还想提高速度,可以改gun.conf配置文件中的worker数目。

    cpu的损耗是平均到各个进程,而不是独立在flask的web server上

    现在我们开始测试gevent 作为wsgi 网关接口的实力~ 

    flask的一个demo~

    gevent wsgi的配置,我先简单的做下配置。。。。

    大家想看实例的话,可以去gevent的官网的wsgi的demo   那边还附有编程的接口。。。

    from gevent.wsgi import WSGIServer
    from a import app
    http_server = WSGIServer(('', 11111), app)
    http_server.serve_forever()

    源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

    我们开始测试更牛逼的gevent的并发能力 。

    服务端:

    客户端:

    看到秒数了吧~    啥也不说了~    大家都懂了~

    我们稍微调节一下~ 

    事实上, gunicorn 调用 gevent workers 的代码类似这样的原理(uwsgi+gevent 也是差不多的做法).

    #!/usr/bin/env python
    # coding:utf-8
                                                                                                                                                       
    import sys
    import os
                                                                                                                                                       
    import gevent
    import gevent.monkey
    import gevent.wsgi
    import gevent.server
    gevent.monkey.patch_all()
                                                                                                                                                       
    import socket
    import multiprocessing
                                                                                                                                                       
    def app(environ, start_response):
        start_response('200 OK', [('Content-Type','text/plain')])
        yield str(socket.getaddrinfo('xiaorui.cc', 80))
                                                                                                                                                       
    def handle_signals():
        gevent.sleep(sys.maxint)
                                                                                                                                                       
    if __name__ == '__main__':
        listenner = gevent.server._tcp_listener(('', 8002), backlog=500, reuse_addr=True)
        for i in xrange(multiprocessing.cpu_count()*2):
            server = gevent.wsgi.WSGIServer(listenner, app, log=None)
            process = multiprocessing.Process(target=server.serve_forever)
            process.start()
        handle_signals()

    uwsgi现在也支持gevent的方式:

    uwsgi --plugins python,gevent --gevent 100 --socket :3031 --module myapp

    总之,gunicorn和gevent,或者是gunicorn+gevent的合体 都是很值得尝试的东西。

    源地址 http://rfyiamcool.blog.51cto.com/1030776/1276364

    下图是我推荐的网络框架~ 这个框架和uwsgi的方式很像的,都是在nginx pass_proxy到app的前端口,然后用uwsgi或者是gunicorn来协同处理 。

    server {
        listen 80;
        server_name xiaorui.cc;
                                                                                                                                                                                                                                                                                                                                                           
        root /www/xiaorui;
                                                                                                                                                                                                                                                                                                                                                           
        access_log xiaorui/access.log;
        error_log xiaorui/error.log;
                                                                                                                                                                                                                                                                                                                                                           
        location / {
            proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            if (!-f $request_filename) {
                proxy_pass http://127.0.0.1:8000;
                break;
            }
        }

    前端Nginx负载,几个核就跑几个Gunicorn进程,gunicorn相对后面的app又可以给出几个进程。

    比起 uWSGI 来说,Gunicorn对于“协程”也就是Gevent的支持会更好更完美。

    方便以后业务的扩展和运营精细化。性能上Gunicorn+Gevent不会比uWSGI弱多少,毕竟后者纯C能只有这么点性能也不容易,比起WSGI Server里面最强的Bjoern而言,Gunicorn也有对应的Meinheld这种利器,况且后者对于HTTP协议的支持比Bjoern更完善。Gevent虽然不是异步框架里面性能最好的,但是绝对是最完善的,社区活跃度也非常高,加上方便的monkey_patch,使得大多数应用不用改代码就能方便地平移过来。这2者结合可以就保证了稳定性,又能有较好性能的组合。

    想简单扩展就用 Gunicorn+Gevent,想麻烦折腾就用nginx 做uwsgi或gunicorn的组合 。

  • 相关阅读:
    Java 的垃圾回收机制
    Java 变参函数的实现
    对已知有限集合中缺失或重复元素的查找
    Java 旋转数组查找旋转点和任意元素(元素可重复)
    第三章 磁盘分区
    第二章 一切都是对象
    发布 AutoRssReceiver Console 机器人! 兼讲: .Net 中的 Attribute (特性)
    .Net/C#/VB/TSQL/Java 实现: 将天文数字转换成中文大写 (2000 年前的思路,打劫的,一点儿技术含量都没有)
    .Net/C#/VB/TSQL/Java/Script 实现: 将天文数字转换成中文大写 (2000 年前的思路,打劫的,一点儿技术含量都没有)
    利用"委托"实现类的对象实例按"多字段嵌套"排序
  • 原文地址:https://www.cnblogs.com/ExMan/p/10152638.html
Copyright © 2011-2022 走看看