zoukankan      html  css  js  c++  java
  • Python Web 服务

    Web 服务器

    用于完成和客户端建立链接,接受并解析请求,转发请求,调用 Web 框架处理业务并生成返回内容,组织并返回内容给客户端,关闭链接等工作,比如 Nginx,Gunicorn,uWSGI 等就是 Web 服务器

    Web 框架

    对 Web 服务的常用功能提取、组织、简化使用,令开发人员可以专注于业务逻辑,比如 Flask、Django 就是 Web 框架

    WSGI

    为了使得任意 Web 服务器都可以和任意 Web 框架搭配,设计出了 WSGI(Web Server Gateway Interface)接口协议,凡是符合 WSGI 协议的 Web 服务器和 Web 框架都可以搭配使用(注意:uWSGI 和 WSGI 是两个概念,uWSGI 是一个实现了 WSGI 协议的 Web 服务器)

    prefork

    prefork 是一种服务端编程模型,Gunicorn, uWSGI 都是这种模型的实现
    prefork 就是有一个 master 进程 fork 出多个 worker 子进程,由子进程处理请求,master 进程只负责监控worker 子进程状态,如果子进程出现问题,可以重启一个,子进程监听同一端口,可以配置 reuse_port 参数在worker 进程间负载均衡,为了避免多线程编程带来的问题,通常设置一个 worker 就一个线程用于处理请求,同时使用协程模块比如 gevent 使得一个线程可以高效地处理高并发 IO 请求

    Gunicorn

    Green Unicorn(绿色独角兽)是一个满足 WSGI 协议的、轻量的、简易的、由 Python 实现的、pre-fork 模型的 Web 服务器,支持 sync、eventlet、gevent、tornado、gthread、gaiohttp 等多种 worker 类型

    uWSGI

    uWSGI 是由 C 语言实现的、满足 WSGI 的、pre-fork 模型的 Web 服务器,支持 uGreen,Greenlet,Stackless,Gevent,Coro::AnyEvent,Tornado,Goroutines,Fibers 等技术,实际上 uWSGI 不仅是一个 Web 服务器,也可以作为 Web 框架,只不过一般都只是当 Web 服务器使用

    Nginx

    实际上 Gunicorn 或 uWSGI 搭配 Flask 或 Django 就可以提供 Web 服务了,但实际生产环境上经常会在前面再加一个 Nginx 服务器,哪怕 Nginx 和 Gunicorn/uWSGI 是一对一的关系,主要因为 Nginx 有一些其他服务器不具备的强大功能:

    • 负载均衡,Nginx 后面可以有多个节点处理同一个业务,可以在不同节点的服务器之间实现负载均衡
    • 地址映射和端口映射,对于处理不同业务的多个节点,Nginx 可以作为统一入口,通过地址映射隐藏后面的多个服务器
    • 静态文件支持,经过配置之后,Nginx 可以直接处理静态文件请求,不需要经过 Gunicorn/uWSGI 服务器,Gunicorn/uWSGI 服务器负责处理动态请求
    • 伪静态,通过 rewrite 配置实现伪静态,比如把 index.html 指向到一个 test.php?v=1 的动态请求,伪静态会增加性能损耗
    • 缓存静态和伪静态页面,对于静态页面,或是一定时间内不会变化的伪静态页面,可以缓存起来,设置一个超时时间,这样 Nginx 就可以不用每次都去读文件,或是每次都要动态生成页面
    • 缓冲请求和响应,如果由于网络问题,导致请求和响应比较慢,可能会占用 Web 服务器的资源,影响业务逻辑的处理,而 Nginx 可以做缓冲,等收到完整的连接、请求消息后,再发给后端处理,收到后端返回后,立刻响应后端,再将消息响应到前端,这样在后端的 Web 服务器看起来,网络的请求响应都非常快,自己主要时间都是在处理业务逻辑,而相应的缓冲请求响应的工作又是 Nginx 比较擅长的,这样就提高了性能
    • Nginx 的高可用性,高并发抗压能力,都比较强
    • 访问控制、限速等功能
    • 避免直接暴露 WSGI 服务器,可以同时作为防火墙防御网络攻击

    Supervisor

    为了防止 Gunicorn/uWSGI 等意外挂了,通常可以加一个 Supervisor 做监控 master 进程

    Flask

    一个 Python 的 Web 框架,主要基于 Werkzeug 和 jinja2

    Werkzeug 是一个 WSGI 工具包,它实现了请求,响应对象和实用函数,Flask 通过 Werkzeug 实现 WSGI 协议,同时 Werkzeug 还提供了一个 WSGI 服务器,Flask 默认就是使用 Werkzeug 服务器,但一般只是用于开发调式,生产环境还是用 Gunicorn 等服务器,因为 Werkzeug 服务器性能差一些

    jinja2 是 Python 的一个模板引擎,用于渲染生成 HTML 页面

    Flask + Gunicorn + Nginx 简例

    安装 flask

    pip install flask
    pip install flask_restplus     ## 方便实现 REST API 的扩展,不是必须的
    

    flask 代码 flask_test.py

    import time
    
    from flask import Flask
    from flask import request
    from flask import Response
    
    from flask_restplus import Api
    from flask_restplus import Resource
    
    from functools import wraps
    
    app = Flask(__name__)
    
    api = Api(app, version='1.0', doc='/doc', title='Test API', description='Test API')
    '''
    api = Api(None, version='1.0', doc='/doc', title='Test API', description='Test API')
    api.init_app(app)
    '''
    
    
    def time_it(func):
        @wraps(func)
        def time_it_decorated(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            print(f"time consumption : {end_time - start_time}
    ")
            return result
    
        return time_it_decorated
    
    
    count = {}
    
    
    def count_it(url_type):
        def count_it_decorated(func):
            @wraps(func)
            def new_func(*args, **kwargs):
                if url_type not in count:
                    count[url_type] = 0
    
                count[url_type] += 1
    
                print(f"receive {url_type} request : {count[url_type]}
    ")
                return func(*args, **kwargs)
    
            return new_func
    
        return count_it_decorated
    
    
    ns = api.namespace('api_v1', path='/api/v1/', description='Test Interface', decorators=[time_it])
    
    USE_NAMESPACE = False
    
    if USE_NAMESPACE:
        @ns.route('/test')
        class Test(Resource):
            @count_it("test_1")
            def get(self):
                return Response(f"Hello {request.remote_addr}
    current time is {time.time()}
    ")
    
            @count_it("test_2")
            def post(self):
                time.sleep(5)
                return Response(f"Hello {request.remote_addr}
    ")
    else:
        @app.route('/test/1', methods=['GET'])
        @time_it
        @count_it("test_1")
        def test():
            return f"Hello {request.remote_addr}
    current time is {time.time()}
    "
    
        @app.route('/test/2', methods=['POST'])
        @time_it
        @count_it("test_2")
        def test_2():
            time.sleep(5)
            return f"Hello {request.remote_addr}
    "
    
    
    if __name__ == '__main__':
        app.run()
    
    

    可以直接运行这个 flask 程序,这时用的是 Werkzeug 自带的服务器

    python3.6 flask_test.py
    

    安装 Gunicorn

    pip3.6 install gunicorn
    pip3.6 install gevent     # 使用 gevent 模式才需要,不是必须的
    

    创建 Gunicorn 配置文件 gunicorn_config.py (也可以通过 gunicorn 参数指定,但通过配置文件更方便)

    import gevent.monkey
    gevent.monkey.patch_all()       # 使用 gevent 模式才需要这步
    
    import multiprocessing
    
    debug = True
    loglevel = "debug"
    accesslog = "./access.log"
    errorlog = "./error.log"
    #daemon = True
    #capture_output = True
    
    bind = '127.0.0.1:8000'
    
    workers = multiprocessing.cpu_count() * 2 + 1
    worker_class = 'gevent'
    
    preload_app = True
    reload = True
    
    x_forwarded_for_header = 'X-FORWARDED-FOR'
    proxy_allow_ips = '*'
    
    

    启动 gunicorn 服务器

    sudo gunicorn -c gunicorn_config.py flask_test:app
    

    安装 Nginx

    sudo apt-get install nginx
    

    Nginx 配置

    /etc/nginx/nginx.conf
    

    这个配置文件会引入下面两个目录的配置文件

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
    

    创建 /etc/nginx/conf.d/flask_test.conf (配置文件可以有多个)

    server {
        listen       80;
        server_name  localhost;
    
        # location 的 URL 匹配语法
        # ~* 表示正则表达式,不区分大小写
        # ~  表示正则表达式,要区分大小写
        # =  表示精确匹配
        # 没有修饰符的,以指定模式开始,比如 location / 匹配所有以 / 开始的 URL
    
        # 静态页面,直接读取 html 文件
        location ~* .*.html$ {
            gzip on;
            root /usr/share/nginx/html;
        }
            
        # 动态页面,转发给 gunicorn
        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    

    检测配置

    sudo nginx -t
    

    启动

    sudo nginx
    

    sudo nginx -s reload
    

    如果需要负载均衡,配置如下

    upstream flask_test {
        server 192.168.1.2:8001;
        server 192.168.1.3:8002;
    }
    
    server {
        listen       80;
        server_name  localhost;
    
        # 动态页面,转发给 gunicorn
        location / {
            proxy_pass http://flask_test;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    


  • 相关阅读:
    openvas漏洞扫描
    MSF基础应用
    MS11-050安全漏洞
    MS08_067漏洞渗透攻击实践
    Adobe阅读器渗透攻击
    详解CentOS7安装配置vsftp搭建FTP
    zabbix英文切换成中文
    代理抛出异常 : java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException: 你的主机名: 你的主机名
    安装zabbix客户端
    Docker报错:“WARNING: IPv4 forwarding is disabled. Networking will not work.”解决。
  • 原文地址:https://www.cnblogs.com/moonlight-lin/p/12828452.html
Copyright © 2011-2022 走看看