flask+gunicorn+supervisor+nginx

这里写图片描述

五者之间的关系

  1. 客户端 (client):浏览器或者app。

  2. web服务器 (nginx):Web服务器是指驻留于因特网上某种类型计算机的程序。当Web浏览器(客户端)连到服务器上并请求文件时,服务器将处理该请求并将文件发送到该浏览器上,附带的信息会告诉浏览器如何查看该文件(即文件类型)。服务器使用HTTP(超文本传输协议)进行信息交流,这就是人们常把它们称为HTTP服务器的原因。

    严格意义上Web服务器只负责处理HTTP协议,用于处理静态页面的内容。而动态内容需要通过WSGI接口交给应用服务器去处理。
    Web服务器包括Nginx,Apache,IIS等。而优秀的web服务器在接收http请求时,还可以做负载均衡和反向代理等工作。

  3. WSGI容器 (如Gunicorn):常见的WSGI容器有Gunicorn,uWSGI等。web框架和web服务器之间需要通信,这时候需要设计一套双方都遵守的接口。**PEP3333指出,WSGI(Web Server Gateway Interface)是WEB服务器和web框架或web应用之间建立的一种简单通用的接口规范。有了wsgi这份接口规范,在web开发的过程中,能更加自由的选择服务器端和框架;在服务器端和框架的开发过程能够分离开来,不用过多的考虑双方具体的实现,使得服务器端和框架开发者能够专心自己领域的开发工作。而WSGI容器就是根据这套接口写出来的。**WSGI容器的作用就是根据web服务器传递而来的参数构建一个让WSGI应用成功执行的环境,例如request,而且还得把WSGI应用上处理好的结果返回给web服务器。此外WSGI容器也叫应用服务器。
    注: 一般应用服务器都集成了web服务器,主要是为了调试方便,出于性能和稳定性考虑,并不能在生产环境中使用。

  4. web框架 (如Flask):作用主要是方便我们开发 web应用程序,HTTP请求的动态数据就是由 web框架层来提供的。常见的 web框架有Flask,Django,Tornado等,而Tornado不光是一个web框架,还实现了WSGI容器的功能。单纯的flask 自带的web服务器做下测试,会看到压力大的时候出现socket的问题,因为他是单进程单线程的。使用gunicorn来启动,响应速度和能力提升显著。

  5. 守护进程 (如Supervisor):Supervisor是一个用 Python 写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是 Python 进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用 supervisor 同时启动所有应用程序而不是一个一个地敲命令启动。

例子

Flask

blog.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask, request
from flask.ext.restful import Resource, Api

app = Flask(__name__)
api = Api(app)

todos = {}

class TodoSimple(Resource):
    def get(self, todo_id):
        return {todo_id: todos[todo_id]}

    def put(self, todo_id):
        todos[todo_id] = request.form['data']
        return {todo_id: todos[todo_id]}


api.add_resource(TodoSimple, '/<string:todo_id>')

# 默认端口是localhost:5000
if __name__ == '__main__':
    app.run(debug=True)

运行服务器

python blog.py

向服务器请求

$ curl http://localhost:5000/todo1 -d "data=Remember the milk" -X PUT
{"todo1": "Remember the milk"}
$ curl http://localhost:5000/todo1
{"todo1": "Remember the milk"}
$ curl http://localhost:5000/todo2 -d "data=Change my brakepads" -X PUT
{"todo2": "Change my brakepads"}
$ curl http://localhost:5000/todo2
{"todo2": "Change my brakepads"}

Flask+Gunicorn+gevent

pip install gunicorn

配置文件(gunicorn.conf)

# 并行工作线程数
workers = 4
# 监听内网端口8000【按需要更改】
bind = '127.0.0.1:8000'
# 设置守护进程【关闭连接时,程序仍在运行】
daemon = True
# 设置超时时间120s,默认为30s。按自己的需求进行设置
timeout = 120
# 使用gevent模式,还可以使用sync 模式,默认的是sync模式
worker_class = 'gevent'
# 设置访问日志和错误信息日志路径
accesslog = './logs/acess.log'
errorlog = './logs/error.log'

运行

# gunicorn 运行模块名:应用名 -c 配置文件
gunicorn service:app -c gunicorn.conf
$ curl http://localhost:8000/todo1 -d "data=Remember the milk" -X PUT
{"todo1": "Remember the milk"}
$ curl http://localhost:8000/todo1
{"todo1": "Remember the milk"}
$ curl http://localhost:8000/todo2 -d "data=Change my brakepads" -X PUT
{"todo2": "Change my brakepads"}
$ curl http://localhost:8000/todo2
{"todo2": "Change my brakepads"}

Flask+Gunicorn+Supervisor

更多

Flask+Gunicorn+Supervisor+Nginx

Niginx

反向代理

反向代理,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息!
这里写图片描述

负载均衡

nginx支持的负载均衡调度算法方式如下:

  1. weight轮询(默认):接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,nginx会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。 这种方式下,可以给不同的后端服务器设置一个权重值(weight),用于调整不同的服务器上请求的分配率;权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。

  2. ip_hash:每个请求按照发起客户端的ip的hash结果进行匹配,这样的算法下一个固定ip地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下session共享的问题。

  3. fair:智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少;结合了前两者的优点的一种调度算法。但是需要注意的是nginx默认不支持fair算法,如果要使用这种调度算法,请安装upstream_fair模块

  4. url_hash:按照访问的url的hash结果分配请求,每个请求的url会指向后端固定的某个服务器,可以在nginx作为静态服务器的情况下提高缓存效率。同样要注意nginx默认不支持这种调度算法,要使用的话需要安装nginx的hash软件包

Nginx的配置使用

在我们的例子中,

server {
    # 监听80端口
    listen       80;
    # dnsname
    server_name  your_public_dnsname_here;

    location / {
        # /时,路由至http://127.0.0.1:8000
        proxy_pass http://127.0.0.1:8000;
    }
}

更多

main                                # 全局配置
events {                            # nginx工作模式配置
}
http {                                # http设置
    ....
    server {                        # 服务器主机配置
        ....
        location {                    # 路由配置
            ....
        }
        location path {
            ....
        }
        location otherpath {
            ....
        }
    }
    server {
        ....
        location {
            ....
        }
    }
    upstream name {                    # 负载均衡配置
        ....
    }
}

更多

猜你喜欢

转载自blog.csdn.net/jason_cuijiahui/article/details/80183372