一.uWSGI服务器
要注意 WSGI / uwsgi / uWSGI 这三个概念的区分。
- WSGI是一种通信协议。
- uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。
- 而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。
uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。
Nginx: 和uWSGI一样也是一个Web服务器, Nginx在处理静态内容方面具有强大的能力(Nginx也可以实现负载均衡),uWSGI负责Python这样的动态内容,二者配合共同提供Web服务以实现提高效率和负载均衡等目的, 请求和响应的流程如下:
Request > Nginx > uWSGI > Django > uWSGI > Nginx > Response
请求先交由Nginx,如果是静态内容就自己处理了,如果是动态内容就交给uWSGI服务器,uWSGI服务器处理整个Django项目的Python代码,响应请求,原路返回,Nginx、uWSGI和Django可以独立部署,然后整合。
二.Django 项目代码部署
一个django项目最基本的目录结构如下 /root/blog/
blog
├── manage.py
├── blog
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps
├── static
└── templates
apps 目录为应用目录,如果需要将该目录下的应用在配置文件中进行有效的注册,以及在项目下的urls.py中路由到应用需要在settings.py中进行路径的配置
使用django自带的服务器进行项目的测试 ,进入manage.py文件所在目录下:
python ./manage.py runserver 127.0.0.1:8080
如果项目的运行还需要启动其他服务,也先将其进行启动, 如celery, redis, mysql, kafka,rabbitmq等项目中使用到的各种服务器
然后请求项目中的某个API,测试部署是否成功
二. 部署uWSGI服务器
1.在虚拟环境下安装uWSGI服务器
pip install uwsgi。
2.创建保存uWSGI服务器配置文件的目录和文件
/root/blog/uWSGI_setting_file/uwsgi.ini
在 uwsgi.ini 文件内 定义以下内容:
uwsgi
uwsgi.pid
uswgi.log
注意:
uwsgi.ini 这个文件是uwsgi服务器的配置文件
用uwsgi服务器,需要先在settings.py设置:
DEBUG=FALSE
ALLOWED_HOSTS=[‘*’]
3.启动uwsgi
进入目录: /root/blog/uWSGI_setting_file/
uwsgi
在哪个目录启动,就会在哪个目录生成uwsgi.pid
和uswgi.log
文件。
# 启动:(先将django自带的server服务器停止运行)
uwsgi --ini uwsgi.ini
# 停止:
uwsgi --stop uwsgi.pid
# 重启:
uwsgi --reload uwsgi.pid
# 强制停止:
killall -9 uwsgi
这里我们启动uwsgi服务,可以通过 ps -ef | grep uwsgi
看到已经有四个uwsgi服务启动。
访问项目中的某个API,测试服务器是否运行成功
三. 安装和配置Nginx
1. Ubuntu系统下安装:
sudo apt-get install nginx
在服务器上创建目录结构:/root/var/blog
修改目录权限:sudo chmod 777 /root/var/blog
进入目录: /root/var/blog/,
然后创建static
目录: mkdir static
在配置文件setttings.py中进行配置
# 如果DEBUG=True -> 使用项目目录下static内的静态文件 也就是STATIC_URL 所指向的路径
# 如果DEBUG=False -> 使用STATIC_ROOT指定目录下的静态文件
STATIC_URL = '/static/'
STATIC_ROOT = '/root/var/blog/static/'
# 设置静态文件查找目录,在终端使用命令收集到项目的静态文件后,再去配置nginx服务器寻找静态文件的路径
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
# 如果是home路径下则需要先设置目录权限
# 在模板中使用 fileObj.fileFieldName.url 代表网络可访问的资源路径
MEDIA_URL = '/media/' # 代表访问media的url路径,例如 127.0.0.1/media/1.png
# 无论是否debug,都会访问此路径下的media资源(包括上传和访问)
MEDIA_ROOT = '/var/www/NickBlog/media/'
在manage.py文件所在目录下,输入以下命令收集静态文件.
python manage.py collectstatic
2.配置
进入目录/etc/nginx/sites-enabled/
中可以看到一个default
文件,修改default
文件为如下内容
# site_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
# 设置本地服务的端口
server 127.0.0.1:8000; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
# 监听主机的端口
listen 80;
# the domain name it will serve for
# server_name .liqian.ink; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# 设置媒体文件目录
# Django media
location /media {
alias /root/var/blog/media; # your Django project's media files - amend as required
}
# 设置静态文件目录
location /static {
alias /root/var/blog/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include uwsgi_params; # the uwsgi_params file you installed
}
}
3.启动服务
启动服务:nginx
查看版本:nginx -v
重启服务:nginx -s reload
停止服务:nginx -s stop
后续
发现一个问题,在另外一台机器上部署的时候无法成功进入django进程。
将/etc/nginx/nginx.conf
内容设置为如下内容后,重启成功
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
4.使用nginx实现负载均衡
一、负载均衡的作用
1、转发功能
按照一定的算法【权重、轮询】,将客户端请求转发到不同应用服务器上,减轻单个服务器压力,提高系统并发量。
2、故障移除
通过心跳检测的方式,判断应用服务器当前是否可以正常工作,如果服务器期宕掉,自动将请求发送到其他应用服务器。
3、恢复添加
如检测到发生故障的应用服务器恢复工作,自动将其添加到处理用户请求队伍中。
二、Nginx实现负载均衡
同样使用两个tomcat模拟两台应用服务器,端口号分别为8080 和8081
1、Nginx的负载分发策略
Nginx 的 upstream目前支持的分配算法:
1)、轮询 ——1:1 轮流处理请求(默认)
每个请求按时间顺序逐一分配到不同的应用服务器,如果应用服务器down掉,自动剔除,剩下的继续轮询。
2)、权重 ——you can you up
通过配置权重,指定轮询几率,权重和访问比率成正比,用于应用服务器性能不均的情况。
3)、ip_哈希算法
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个应用服务器,可以解决session共享的问题。
2、配置Nginx的负载均衡与分发策略
通过在upstream参数中添加的应用服务器IP后添加指定参数即可实现,如:
/etc/nginx/nginx.conf
upstream tomcatserver1 { # tomcatserver1 这参数需要和 proxy_pass 定义的变量保持一致
server 192.168.72.49:8080 weight=3; 权重3
server 192.168.72.49:8081;
}
server {
listen 80;
server_name 8080.max.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://tomcatserver1;
index index.html index.htm; 访问主页时请求的静态文件
}
}
复制代码
通过以上配置,便可以实现,在访问8080.max.com这个网站时,由于配置了proxy_pass地址,所有请求都会先通过nginx反向代理服务器,在服务器将请求转发给目的主机时,读取upstream为 tomcatsever1的地址,读取分发策略,配置tomcat1权重为3,所以nginx会将大部分请求发送给49服务器上的tomcat1,也就是8080端口;较少部分给tomcat2来实现有条件的负载均衡,当然这个条件就是服务器1、2的硬件指数处理请求能力。
3、nginx其他配置
upstream myServer {
server 192.168.72.49:9090 down;
server 192.168.72.49:8080 weight=2;
server 192.168.72.49:6060;
server 192.168.72.49:7070 backup;
}
1)down
表示单前的server暂时不参与负载
2)Weight
默认为1.weight越大,负载的权重就越大。
3)max_fails
允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
4)fail_timeout
max_fails 次失败后,暂停的时间。
5)Backup
其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
三、使用Nginx的高可用
除了要实现网站的高可用,也就是提供n多台服务器用于发布相同的服务,添加负载均衡服务器分发请求以保证在高并发下各台服务器能相对饱和的处理请求。同样,负载均衡服务器也需要高可用,以防如果负载均衡服务器挂掉了,后面的应用服务器也紊乱无法工作。
实现高可用的方案:添加冗余。添加n台nginx服务器以避免发生上述单点故障。具体方案详见下文:keepalive+nginx实现负载均衡高可用
四、总结
总结一点,负载均衡不论是各种软件或硬件上的解决方案,主要还是将大量的并发请求按照一定的规律分发给不同的服务器处理,从而减少某台服务器的瞬时压力,提高网站的抗并发能力。nginx在负载均衡的应用之所以广泛,笔者认为这归功于它的灵活配置,一个nginx.conf文件解决大部分问题,不论是nignx创建虚拟服务器、nginx的反向代理服务器,还是本文介绍的nginx的负载均衡,几乎都在这个配置文件中进行。服务器上只负责把nginx搭好,跑起来即可。而且它本身轻量级,不需要占用服务器太多资源就可以达到较好的效果
注意:
- 每次修改了Django项目中的
模板/视图/URL/配置
文件,都需要重启uwsgi
服务。 - 修改
Nginx
配置文件,都需要重启Nginx
服务。