• Python服务部署 Flask/Django + uWSGI/Gunicorn


    一. flask、django项目不推荐使用自带run/runserver方法部署

    • run/runserver方式是flask/django调试模式,使用的是自带WSGI服务器运行,开启的方式为单进程,性能低
    • flask的run方法默认开启方式是单进程且单线程,通过设置threaded=True可开启多线程,设置processes=10可开启多进程,但多进程和多线程不能同时开启,且需要关闭debug模式,且设置多进程在windows系统下不支持
    • 在官方描述中也声明,flask/django自带的server只能用于开发调试,并不适合用于生产环境
    • 推荐使用专业的web server进行部署,如:uWSGI、Gunicorn,本质原因是uWSGI、Gunicorn在配置:多线程可以绕过IO阻塞 + 多进程充分利用多核

    二. Web服务器、WSGI、Flask/Django框架关系

    1. WSGI简介

    WSGI(Web Server Gateway Interface),既不是服务器,也不是应用,而是一种接口(规范),描述web server如何与web application通信的规范:

    1. 服务器的请求处理要调用符合WSGI规范的网关接口;
    2. 由网关接口来调用应用程序,并且其要定义start_response(status, headers)函数,用于返回响应;
    3. 应用程序须是一个可调用对象(函数/类),webapp(environ, start_response)。接受两个参数,environ是环境设置的字典,由服务器和WSGI网关接口设置,start_response是由网关接口定义的函数。
    
    • 1
    • 2
    • 3
    • web server:实现了WSGI server协议的服务器,如uWSGI、Gunicorn
    • Gateway Interface:网关接口,如CGI、WSGI
    • application:实现了WSGI application协议的框架,如Django、Flask

    网络通信的完整流程:

    先创建一个web服务器,监听端口,接收请求,并将请求路由转发给对应的应用程序。
    再创建一个web应用程序,用于接收到请求,经过必要的处理,返回响应给服务器。
    服务器接收响应,返回给客户端(浏览器)
    
    • 1
    • 2
    • 3

    WSGI 只适用于 Python 语言,定义了 web服务器和 web应用之间的接口规范。解耦了服务器类与应用程序类,只要 web服务器和 web应用都遵守WSGI协议,那么 web服务器和 web应用就可以随意的组合

    2. Application实现

    WSGI规范规定,Application 必须是一个可调用的对象,它可以是函数,可以实现了__call__的类的实例对象,也可以是实现了__iter__的类对象。

    不管是哪种方式的可调用对象,都要遵循两个原则:
    1. 必须接收environ(WSGI环境信息), start_response(响应请求函数)两个参数;(这两个参数都由Web Server来定义的)
    2. 必须返回可迭代的对象。
    • 其中传入的start_response方法接收两个参数:
      1. status:HTTP状态,譬如:“200 OK”
      2. response_headers:响应消息的头,譬如:[(‘Content-Type’, ‘text/plain’)],以list的形式,每个元素是一个tuple,而每一个tuple里有两个元素,key和value
    同理,Web Server也必须实现这两个对象,定义完成后,要调用application,将两个参数传入

    3. Web框架层协议体现

    Web框架的作用主要是方便我们开发 web应用程序,也遵循WSGI协议,以flask为例,遵循WSGI协议体现的源码:

    class Flask(_PackageBoundObject):
        .....
        def wsgi_app(self, environ, start_response):
            ctx = self.request_context(environ)
            error = None
            try:
                try:
                    ctx.push()
                    response = self.full_dispatch_request()
                except Exception as e:
                    error = e
                    response = self.handle_exception(e)
                except:
                    error = sys.exc_info()[1]
                    raise
                return response(environ, start_response)
            finally:
                if self.should_ignore_error(error):
                    error = None
                ctx.auto_pop(error)
    
        def __call__(self, environ, start_response):
             return self.wsgi_app(environ, start_response)
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在Flask中处理请求的入口__call__方法, 又调用了另一个方法wsgi_app,所有的请求将会在这几行代码中处理完成, 并且最终返回

    • 补充:在Web Server和应用之间还存在中间件middleware,中间件也必须满足两方的WSGI协议

    4. uwsgi协议、uWSGI服务器

    • uwsgi同wsgi 一样也是一种协议,uWSGI服务器正是使用了 uwsgi 协议
    • uWSGI实现了 uwsgi 和 WSGI 两种协议的web服务器。注意 uWSGI 本质上也是一种 web服务器,处于上面描述的三层结构中的Web Server层。

    三. Gunicorn

    1. 简介
    • gunicorn-绿色独角兽,python的WSGI HTTP Server,WSGI的实现,同时也自带Web Server,能直接对外提供web服务。既支持eventlet也支持greenlet。
    • 只支持在Unix系统上运行,所在位置通常在反向代理(如:Nginx)和一个Web应用(如Flask)之间
    2. Gunicorn工作模式
    • gunicorn支持使用不同的worker进程类型,可通过worker-class参数配置。
      启动后,gunicorn的所有worker共用一组listener(Gunicorn支持绑定多个socket,所以说是一组)。在启动worker时,worker内为每个listener创建一个WSGI server,接收HTTP请求,并调用app对象去处理请求。
    • Gunicorn启动项目后会有一个主进程Master和一个或多个工作进程。工作进程的数量可以指定。工作进程是实际处理请求的进程。主进程维护服务器的运行
    • gunicorn的工作模式一般分为同步worker使用和异步worker使用(默认是异步,异步worker有Gevent和Eventlet两种,都是基于Greenlet实现的),例如在单核机器上运行的gevent:
    gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 main:app
    
    • 1

    worker-connection 是对于 gevent worker 类的特殊设置。(2CPU)+1 是建议的worker数量。因为这里是单核,我们设置的是3个worker。在这种情况下,最大的并发请求数是3000(3个worker1000个连接数/worker)

    3. Gunicorn实现高并发
    • Gunicorn在启动时就已经把worker进程预先fork出来了,当多个请求到来的时候,会轮流复用这些worker进程,从而提高服务器并发负载能力
    • 对于worker数量配置,推荐2CPU数+1;这样在任何时间,都有大概一半worker在做I/O,剩下一半才是需要CPU的;如果在开多进程的同时,也开多线程(即选择gthread类型的worker),那么,配置总的并发数(worker进程线程数),仍然建议2CPU数+1
  • 相关阅读:
    [附源码]SSM计算机毕业设计医学季节性疾病筛查系统JAVA
    C#程序中很多ntdll.dll、clr.dll的线程
    python学习笔记-09
    如何处理前端响应式图片?
    盘点2022初级Java笔试题,选择题,简答题(右滑查看答案)
    不敢置信,某位神秘大佬上传Mybatis学习笔记,让你轻松从入门到精通
    torch.multiprocesssing
    百度文心一率先言向全社会开放 应用商店搜“文心一言”可直接下载
    软考中级软件设计师--3.知识产权
    springboot整合solr,solr设置登录用户密码连接
  • 原文地址:https://blog.csdn.net/lijianping962464/article/details/126299643