网站架构--WSGI,Gunicorn,Nginx,数据库缓存

python的web框架比如Flask,Django自带的服务器的目的是用于开发的,那么在生产环境下我们使用什么样的服务器呢?

WSGI协议:

web框架和web服务器之间需要进行通信,WSGI规定了一种在web服务器与web应用程序/框架之间推荐的标准接口。

WSGI容器:

  1. Gunicorn
    易于配置,兼容性好,CPU消耗少,支持多种worker模式。
pip install gunicorn
gunicorn --worker=3 project.app:app -b 0.0.0.0:9000
# 这是启动应用的方式,第一个app是模块文件的名字,第二个是文件中flask实例的名字。
# 这里worker推荐值是CPUx2+1,
python -c 'import multiprocessing; print multiprocessing.cpu_count()'
# 虚拟机只有一个CPU,所以使用3
  1. uWSGI
    使用C编写,实现了自有的uwsgi协议的web服务器
pip install uwsgi
uwsgi --http 0.0.0.0:9000 .....

uwsgi的启动命令会复杂许多,如果需要使用可以仔细的阅读官网!

web服务器和应用服务器的区别:

上面说的就是应用服务器!!!!!
使用python开发的站点使用的主流web服务器有Nginx,Apache,Tengine。

  • web服务器主要负责处理HTTP协议,应用服务器还能处理其他协议
  • web服务器用于处理静态页面,对于动态内容,它通过WSGI借口交给应用服务器来处理
  • 一般应用服务器集成了web服务器,虽然集成了web服务器,但是只是为了调试方便,处于性能和稳定性的考虑,生产环境中不使用应用服务器。

选择Nginx

Nginx是一个开源高性能的HTTP服务器和反向代理。
sudo apt-get install nginx -yq 安装完后就启动了

部署Flask应用,通常都是使用一种WSGI应用服务器配合Nginx作为反向代理!!!!

正向代理: 作为一个媒介在互联网上获取资源然后返回给相关联的客户端,代理和客户端在一个局域网内,对于服务器是透明的。
反向代理: 根据客户端的需求,从后端的服务器上获取资源,再将资源返回给客户端,代理和服务器在一个局域网内,对客户端是透明的。Nginx是反向代理的最佳选择,反向代理的优点有:提高动态语言的IO处理能力,加密和SSL加速,安全,负载均衡,缓存静态内容,支持压缩。

Nginx的配置文件是block形式的,主要有6个:

block meaning
main 全局设置,基本控制功能,包含events和http两个block
events 事件设置,控制nginx处理连接的方式
http Http设置,下面包含了server和upstream两个block
server 主机设置
upstream 负载均衡设置
location URL模式设置,在server下面,可有多个

适用于Nginx和Gunicorn模式的Nginx配置,.conf文件

user  ubuntu ubuntu;
worker_processes  1;
worker_cpu_affinity auto;
worker_rlimit_nofile 65536;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  65536;
    accept_mutex off;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    keepalive_timeout  75 20;
    proxy_read_timeout 200;
    keepalive_requests 100000;

    client_header_timeout 10m;
    client_body_timeout 10m;
    client_max_body_size 20m;
    send_timeout 10m;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    gzip on;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_types text/plain text/css
               application/x-javascript application/xml
               application/atom+xml text/javascript;

    upstream frontends {
        server 127.0.0.1:8000;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
        # server unix:/tmp/gunicorn.sock;
    }

    server {
        listen 80;
        server_name localhost;
        keepalive_timeout 5;

        location ^~ /static/ {
            root /home/ubuntu/web_develop/static;
        }

        location ~* \.(woff|eot|ttf|svg|mp4|webm|jpg|jpeg|png|gif|ico|css|js)$ {
            expires 30d;
        }

        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_redirect off;
            proxy_pass http://frontends;

            # 如果开启keepalive需要指定如下2项
            # proxy_http_version 1.1;
            # proxy_set_header Connection "";
        }
    }
}

替换默认的Nginx配置:

sudo cp .../nginx_gunicorn.conf  /etc/nginx/nginx.conf
sudo /etc/init.d/nginx reload
# 上面的重启之前是可以来验证配置文件的语法
sudo /etc/init.d/nginx configtest

Nginx的负载均衡算法:

  • round-robin:轮询算法,按时间顺序逐一分配到不同的后端服务器。
  • least_conn:请求发送到活跃链接数最少的服务器
  • ip_hash:按访问IP的哈希结果表分配结果
  • hash:按某个键的哈希结果分配

通过Gunicorn启动flask应用:

上面的Nginx配置设置了8000-8002三个后端端口,为了演示,启动8000端口的Gunicorn实例:
gunicorn -w 3 project.app:app -b :8000
然后通过Nginx访问flask应用;
http http://localhost



缓存

缓存系统Memcached

频繁通过直接访问数据库获得数据的方式对数据库造成很大的负担Memcached是一个高性能的分布式内存对象缓存系统,它通过在内存中缓存数据来减少读取数据库的次数。目前最好用的Python客户端是Libmc
首先安装Memcached:
sudo apt-get install memcached 安装后就直接启动了,这是默认的启动方式
下面使用Memcached分布式处理缓存:
/usr/bin/memcached -m 64 -p 11212 -u memcache -l 127.0.0.1 -d

下面再安装libmc:
pip install libmc
Libmc的配置:

# coding=utf-8
from libmc import (
    Client, MC_HASH_MD5, MC_POLL_TIMEOUT, MC_CONNECT_TIMEOUT, MC_RETRY_TIMEOUT
)
from mc_decorator import create_decorators

mc = Client(
    [
        'localhost',  # 默认端口为11211, 所以和下面的一个是等价的
        'localhost:11212',
        'localhost:11213 mc_213'
    ],  # 第一个参数为Memcached服务器列表
    do_split=True,  # 默认值为false, 不接受大于1MB,设置为True,小于10MB的会被切片分段,但是不能存储大于10MB的数据
    comp_threshold=0,
    noreply=False,
    prefix=None,
    hash_fn=MC_HASH_MD5,
    failover=False
)

mc.config(MC_POLL_TIMEOUT, 100)  # 100 ms
mc.config(MC_CONNECT_TIMEOUT, 300)  # 300 ms
mc.config(MC_RETRY_TIMEOUT, 5)  # 5 s

globals().update(create_decorators(mc))

使用Memcached实例:
首先实现一个装饰器,可以在方法上定义缓存键和缓存时间。
具体方法省略,网上自行查找,我们重点介绍Redis

键值对数据库Redis

Redis详解



大型网站架构经验

缓存:
通常用户访问的热点数据只集中在一小部分数据上,这部分数据应该存储在缓存中,这样就减轻了后端应用的负担。一共有四种缓存方式:

  • 本地缓存:在应用服务器内缓存热点数据,当请求访问这些热点数据的时候,可以直接从本机的内存里面获取热点数据,而不用去访问数据库
  • 分布式缓存: 其实还是本地缓存,但是当数据量特别大的时候,单机无法承受,所以需要分布式缓存集群,即应用程序通过网络来访问缓存。
  • 反向代理: 代理服务器是位于网站的机房之内的,所以用户访问的网站地址其实是代理服务器地址,代理服务器会决定是从后端返回数据还是从缓存返回数据,还可以使用varnish来加速。
  • CDN: 内容发布网络缓存,即发布商出售缓存服务器给需要的网站,这些网站不用维护环从工作,只需要把内容提交到CDN发布商就行,所以在CDN上缓存网站的一些静态资源可以有效提升页面的加载速度。

负载均衡:
后端服务器的各种性能可能都不一样,所以较好的服务器理应负担更大的访问量,较差的服务器理应负担较小的访问量。通过负载均衡可以把用户的请求分发到多台后端设备上,这样就均衡了服务器的负担。
常见的负载均衡工具有LVS,HAProxy,Nginx:

  • Nginx仅仅能支持HTTP,HTTPS,还有email等协议,使用场景最少,而且仅有它不能支持MySQL进行负载均衡。但是对网络的依赖非常小。
  • LVS不支持正则
  • HAProxy配置选项很多,最灵活,使用场景也多。

高可用:
现在单个节点已经无法满足我们的业务要求,所以需要让服务运行在多个节点上面,系统要有可用性,即组成系统的某些设备或者组件失效或者宕机时,并不会中断服务。

集群:
使用集群时解决高并发,海量数据问题的常用手段,当单体服务器不能负担的时候,不要盲目想着提高服务器的性能,而是增加一台服务器来分担原来的压力。一般大型网站的大部分页面都不是一个单独的应用来提供服务,而是被分割成了多个部分,每个部分都由独立部署的一个服务器集群来提供服务。

不同用途的服务器对硬件资源的要求是不一样的:
应用服务器需要处理大量的业务逻辑,所以需要更快的CPU
文件服务器需要储存大量用户的文件,所以需要更大的硬盘
数据库服务器需要快速的写入数据和检索到要查询的数据缓存,所以需要更快的硬盘和更大的内存

你可能感兴趣的:(后端开发架构/部署/性能优化)