zoukankan      html  css  js  c++  java
  • 如何理解Nginx、uWSGI和Flask之间的关系

    参考链接,参考链接nginx比较好讲解, 示例

    1. flask 是 python 编写的轻量级 Web 应用框架。单独Flask也可以启动并提供web服务,demo但是Flask毕竟只是一个web框架,它的web服务只能用于开发环境,不能用于生产环境 ,因此还需要和uWSGI及nginx一起整合

    总括来说,客户端从发送一个 HTTP 请求到 Flask 处理请求,分别经过了 web 服务器层,WSGI层,web框架层,这三个层次。不同不 同的层次其作用也不同,下面简要介绍各层的作用。

    输入图片说明

    Web服务器层

    对于传统的客户端 - 服务器架构 c/s,其请求的处理过程是,客户端向服务器发送请求,服务器接收请求并处理请求,然后给客户端返回响应。在这个过程中,服务器的作用是:

    • 接收请求
    • 处理请求
    • 返回响应

    Web服务器是一类特殊的服务器,其作用是主要是接收 HTTP 请求并返回响应。提起 web服务器大家都不会陌生,常见的 web服务器有 Nginx,Apache,IIS等。在上图1的三层结构中,web服务器是最先接收用户请求的,并将响应结果返回给用户

    Web框架层(应用层)

    Web框架的作用主要是方便我们开发 web应用程序,HTTP请求的动态数据就是由 web框架层来提供的。常见的 web框架有Flask,Django等,我们以 Flask 框架为例子,展示 web框架的作用:

    from flask import Flask
    app = Flask(__name__)
    @app.route('/hello')
    def hello_world():
        return 'Hello World!'
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=8080)

    以上简单的几行代码,就创建了一个 web应用程序对象 app。 app 监听机器所有 ip 的 8080 端口,接受用户的请求连接。我们知道,HTTP 协议使用 URL 来定位资源,上面的程序会将路径 /hello 的请求交由 hello_world 方法处理, hello_world 返回 'Hello World!' 字符串。对于 web框架的使用者来说,他们并不关心如何接收 HTTP 请求,也不关心如何将请求路由到具体方法处理并将响应结果返回给用户。Web框架的使用者在大部分情况下,只需要关心如何实现业务的逻辑即可

    WSGI层

    WSGI 不是服务器,也不是用于与程序交互的API,更不是真实的代码,WSGI 只是一种接口,它只适用于 Python 语言 (是一个Web服务器,实现WSGI协议,Http协议。把 HTTP 协议转化成语言支持的网络协议。比如把 HTTP 协议转化成 WSGI 协议,让 Python 可以直接使用),其全称为 Web Server Gateway Interface,定义了 web服务器和 web应用 之间的接口规范。也就是说,只要 web服务器和 web应用 都遵守WSGI协议,那么 web服务器和 web应用就可以随意的组合。

    下面的代码展示了 web服务器 是如何与 web应用组合在一起的

    def application(env, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b"Hello World"]

    方法 application 由 web服务器调用,参数 env, start_response 由 web服务器实现并传入。其中, env是一个字典,包含了类似 HTTPHOST,HOSTUSERAGENT,SERVERPROTOCO 等环境变量。 start_response则是一个方法,该方法接受两个参数,分别是 status, response_headers。 application方法的主要作用是,设置 http 响应的状态码和 Content-Type 等头部信息,并返回响应的具体结果。

    上述代码就是一个完整的 WSGI 应用,当一个支持 WSGI 的 web服务器接收到客户端的请求后,便会调用这个 application 方法。WSGI 层并不需要关心 env, start_response 这两个变量是如何实现的,就像在 application 里面所做的,直接使用这两个变量即可。

    值得指出的是,WSGI 是一种协议,需要区分几个相近的名词:

    • uwsgi:同 wsgi 一样也是一种协议,uWSGI服务器正是使用了 uwsgi 协议

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

    • CGI:通用网关接口,并不限于 Python 语言,定义了 web服务器是如何向客户端提供动态的内容。例如,规定了客户端如何将参数传递给 web服务器,web服务器如何将参数传递给 web应用,web应用如何将它的输出如何发送给客户端,等等。

    生产环境下的 web应用都不使用 CGI 了,CGI进程(类似 Python 解释器)针对每个请求创建,用完就抛弃,效率低下。WSGI 正是为了替代 CGI 而出现的。

    说到这,我们基本理清了 WSGI 在 web服务器与 web框架之间作用:WSGI 就像一条纽带,将 web服务器与 web框架连接起来。回到本文的题目,Nginx 属于一种 web服务器,Flask属于一种 web框架,因此,WSGI 与 Nginx、Flask 的作用就不明而喻了

    Nginx,WSGI,Flask 之间的对话

    • Nginx:Hey,WSGI,我刚收到了一个请求,我需要你作些准备,然后由Flask来处理这个请求。
    • WSGI:OK,Nginx。我会设置好环境变量,然后将这个请求传递给Flask处理。
    • Flask:Thanks WSGI!给我一些时间,我将会把请求的响应返回给你。
    • WSGI:Alright,那我等你。
    • Flask:Okay,我完成了,这里是请求的响应结果,请求把结果传递给Nginx。 WSGI:Good job!
    • Nginx,这里是响应结果,已经按照要求给你传递回来了。
    • Nginx:Cool,我收到了,我把响应结果返回给客户端。大家合作愉快

    简单的demo历程如下:

    docker pull tiangolo/uwsgi-nginx-flask:python3.6 该images
    然后  docker run -d tiangolo/uwsgi-nginx-flask:python3.6 实现运行一个container
    接下来重新一个main.py 如下

    from flask import Flask, request
    from flask import jsonify
    app = Flask(__name__)
    @app.route("/",methods=['POST','GET'])
    def hello():
        filepath = ''
        if request.method == 'GET':
            filepath = request.args.get("filepath")
        else:
            filepath = request.form.get('filepath')
    
        return 'get filepwd by liujinjie'
    if __name__ == "__main__":
        # Only for debugging while developing
        app.run(host='0.0.0.0', debug=True, port=5000)

    然后执行 docker cp main.py c793c4c0f393:/app/main.py
    docker commit c793c4c0f393 liujinjie/uwsgi-nginx-flask-python3.6:v1
    docker run --name ljj_container_1 -p 1412:80 liujinjie/uwsgi-nginx-flask-python3.6:v1
    然后 运行如下代码

    import requests
    from glob import glob
    data = {'filepath':'/data/liujinjie'}
    try:
        resp = requests.post('http://10.100.34.15:1412',data,timeout=10)
    except Exception:
        print('error')
    else:
        print(str(resp.text))


    会输出文字信息:get filepwd by liujinjie

    结论:也就是说 uwsgi-nginx-flask 替换好main.py 后系统会自动将flask 服务跑起来。工程化web服务中 需要nginx+uwsgi+flask,

    关注公众号 海量干货等你
  • 相关阅读:
    OpenCV (十二)阈值操作
    OpenCV (十一)图像金字塔
    OpenCV (十)提取水平线与垂直线
    OpenCV (九)形态学操作:开操作,闭操作,形态学梯度,顶帽,黑帽
    电商平台资料学习
    四、eslint配置rules
    三、export和export default区别
    二、安装国际化
    一、vue安装
    vue执行命令时提示错误——vue : 无法加载文件 C:UsersAdministratorAppDataRoaming pmvue.ps1,因为在此系统上禁止运行脚本
  • 原文地址:https://www.cnblogs.com/sowhat1412/p/12734300.html
Copyright © 2011-2022 走看看