一、动静分离基本介绍
1.1 什么是动静分离
就是把动态请求和静态请求分离开来处理。
1.2 为何需要动静分离
拿Tomcat来说,Tomcat等应用服务器在处理静态资源时效率不高,但默认情况下无论 “动态、静态“ 资源都是由tomcat处理,而Tomcat在处理静态资源时需要进行逻辑运算,从而会导致应用响应慢,并且会占用不必要的系统资源。那么借助Nginx实现动态资源请求和静态资源请求分离后,可以减少系统不必要的消耗和延时。以便加快系统的处理性能。
1.3 如何实现动静分离
Nginx通过用户请求的 uri 来区分请求的类型,并转发给不同的服务端。如果请求的uri包含 png、jpg 等资源则由 Nginx 处理;如果请求的 uri 包含 php、jsp 等资源则代理至 Tomcat 处理;
二、动静分离实践
2.1 单台服务器实现动静分离(动态请求和静态请求处理的分离)
环境 nginx+tomact
1.下载tomcat tomcat官网
[root@web01 ~]# yum install java # 需要先安装java
[root@web01 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.0.10/bin/apache-tomcat-10.0.10.tar.gz
[root@web01 ~]# mkdir /soft
[root@web01 ~]# tar xf apache-tomcat-10.0.10.tar.gz -C /soft/
[root@web01 ~]# /soft/tomacat/bin/startup.sh # 启动tomcat
[root@web01 ~]# netstat -lntp
tcp6 0 0 :::8080 :::* LISTEN 3847/java
2.nginx配置
配置动静分离
[root@web01 conf.d]# cat java.bertwu.conf
server {
listen 80;
server_name java.bertwu.net;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $http_host;
}
location ~* .*\.(png|jpg|jpeg|svg)$ {
root /images;
expires 10d;
}
}
[root@web01 ~]# mkdir /images
[root@web01 ~]# mv /soft/tomacat/webapps/ROOT/*.png /images/
[root@web01 ~]# mv /soft/tomacat/webapps/ROOT/*.svg /images/
[root@web01 ~]#chown -R www.www /images/
2.2 集群动静分离
通过nginx负载均衡将动态请求和静态请求进行分离,基于用户请求URI实现路由功能;
1.环境准备
服务 | 地址 | 主机名称 |
---|---|---|
负载均衡 | 10.0.0.5 | lb01 |
动态资源 | 10.0.0.7 | web01 |
静态资源 | 10.0.0.8 | web02 |
2.配置静态节点
在10.0.0.8服务器上配置静态资源
[root@web02 ~]# cat /etc/nginx/conf.d/static.conf
server {
listen 80;
server_name java.bertwu.net;
root /images;
location / {
index index.html;
}
}
[root@web02 ~]# mkdir /images
[root@web02 ~]# chown -R www.www /images
[root@web02 ~]# wget -O /code/images/nginx.png http://nginx.org/nginx.png # 下载一张图片
3.配置动态节点
在10.0.0.7服务器上配置动态资源
[root@web01 ~]# rm -rf /soft/tomcat/webapps/ROOT/* # 删除原有的.jps
# 编写java配置
[root@web01 ROOT]# cat /soft/tomacat/webapps/ROOT/index.jsp
<%@ page language="java"
import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>Nginx+Tomcat动静分离</title>
</head>
<body>
<%
Random rand = new Random();
out.println("<h2>动态资源</h2>");
out.println(rand.nextInt(99)+100);
%>
<h2>静态图片</h2>
<img src="nginx.png" />
</body>
</html>
4.配置负载均衡
负载均衡10.0.0.5上配置调度,根据不同的url调度到不同的服务器
[root@lb01 conf.d]# cat proxy_ds.conf
upstream dynamic {
server 10.0.0.7:8080;
}
upstream static {
server 10.0.0.8:80;
}
server {
listen 80;
server_name java.bertwu.net;
location / {
proxy_pass http://dynamic;
include proxy_params;
}
location ~* .*\.(png|jpg)$ {
proxy_pass http://static;
include proxy_params;
}
}
4.浏览器刷新访问java.bertwu.net
模拟静态资源集群故障。动态内容依旧能正常访问, 静态内容则不会被请求到。
关闭nginx服务器
[root@web02 ~]# systemctl stop nginx
三、uWSGI代理基本概述
3.1 什么是WSGI
WSGI,全称 Web Server Gateway Interface 是为 Python 语言定义的 Web 服务器 和 Web 应用程序之间的一种简单通用的接口。WSGI 的官方定义,the Python Web Server Gateway Interface。从名字就可以看出来,这是一个 Gateway 网关。那么网关的作用就是在协议之间进行转换。也就是说,WSGI就像是一座桥梁,一边连着web服务器,另一边连着web应用程序。
很多框架都自带了 WSGI server ,比如 Flask,Django等等。当然性能都不好,自带的 Web Server 更多的是测试用途,发布时则使用生产环境的 WSGI server或者是联合 nginx 做 uwsgi 。
3.2 什么是uWSGI
uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。简单来说:我们将项目通过uwsgi方式运行,就可以直接对外提供服务,而无需依托于Nginx。uWSGI详解
- uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information)每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。
3.3 uWSGI结合nginx
通常情况下Python中的Django框架或Flask框架可以通过uwsgi方式对外提供服务。为什么还需要Nginx
1.安全:后端服务直接以http对外提供访问,往往会暴露后端的真实服务,如果使用nginx可以隐藏后端的服务,并且nginx能够实现安全限制、Rewrite、HTTPS等功能(这些都是uWSGI无法实现的。)
2.效率:nginx可以直接处理静态资源,然后将动态内容通过uwsgi协议转发给后端Django,实现动静分离,提供更好的请求与响应。
3.4 uWSGI代理
1. 安装python3环境
2. 安装Django框架及uwsgi
3. 配置Django工程
4. 配置uWsgi
5. 配置nginx
3.4.1 安装python3
[root@web01 ~]# yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel \sqlite-devel gcc gcc-c++ openssl-devel zlib zlib-devel python3 python3-devel -y
3.4.2 安装Django及uwsgi
永久修改pip源
# 找到~/.pip/pip.conf,如果不存在就创建
# 加入
[global]
timeout = 6000
index-url = http://mirrors.aliyun.com/pypi/simple
[install]
trusted-host=mirrors.aliyun.com
[root@web01 ~]# pip3 install django==2.1.8
[root@web01 ~]# pip3 install uwsgi
3.4.3创建django项目
[root@web01 ~]# mkdir /django
[root@web01 ~]# cd /django
[root@web01 django]# django-admin startproject demo
[root@web01 django]# tree /django/
/django/
└── demo
├── demo
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
[root@web01 demo]# python3 manage.py runserver 0.0.0.0:9999
3.4.3 访问
方式1.
如果出现ALLOWED_HOSTS报错,修改如下配置即可;
[root@web01 demo]# vim /django/demo/demo/settings.py
ALLOWED_HOSTS = ['*']
注:此方法启动是django自带的 WSGI server,适合本地测试调试访问。
方式2.
[root@web01 demo]# uwsgi --http 10.0.0.7:5555 --file demo/wsgi.py
--http 这个就和runserver一样指定IP 端口
--file 这个文件就里有一个反射,如果你在调用他的时候没有指定Web Server就使用默认的
-- static 指定静态文件
# 或者将配置写入一个文件aaa.ini,用 uwsgi --ini aaa.ini 运行
此方式完全可以作为web服务器对外提供服务,但是它不能处理动静分离,https、Rewrite等请求
方式3 使用uwsgi配置文件启动django项目,具体如下
3.5 配置uwsgi运行项目
配置Django工程以由uwsgi方式运行
[root@web01 demo]# vim /django/demo/uwsgi.ini
[uwsgi]
socket=127.0.0.1:8888 # uwsgi监听的端口
workers=2 ##uwsgi启动进程数
max-requests=1000 #最大接收的请求数
buffer-size = 30000 #buffer缓冲区大小
pidfile = /run/uwsgi.pid #进程pid存放路径
daemonize = /var/log/uwsgi.log #uwsgi日志存储路径
更详细的uwsig配置文件请参考如下:
[uwsgi]
# 项目目录
chdir=/opt/proj/teacher/
# 指定项目的application
module=teacher.wsgi:application
# 指定sock的文件路径
socket=/opt/proj/script/uwsgi.sock
# 进程个数
workers=5
pidfile=/opt/proj/script/uwsgi.pid
# 指定IP端口
http=192.168.2.108:8080
# 指定静态文件
static-map=/static=/opt/proj/teacher/static
# 启动uwsgi的用户名和用户组
uid=root
gid=root
# 启用主进程
master=true
# 自动移除unix Socket和pid文件当服务停止的时候
vacuum=true
# 序列化接受的内容,如果可能的话
thunder-lock=true
# 启用线程
enable-threads=true
# 设置自中断时间
harakiri=30
# 设置缓冲
post-buffering=4096
# 设置日志目录
daemonize=/opt/proj/script/uwsgi.log
3.6 nginx代理uwsgi
通过uwsgi方式启动django项目,默认监听127.0.0.1 外界是不能直接访问的,必须通过nginx代理
[root@web01 ~]# uwsgi --ini /django/demo/uwsgi.ini # 启动
[uWSGI] getting INI configuration from /django/demo/uwsgi.ini
[root@web01 ~]# netstat -lntp
tcp 0 0 127.0.0.1:8888 0.0.0.0:* LISTEN 6333/uwsgi
置Nginx,使用Nginx代理uwsgi应用
[root@web01 conf.d]# cat py.conf
server {
listen 80;
server_name python.bertwu.net;
client_max_body_size 100M;
location / {
index index.html;
uwsgi_pass 127.0.0.1:8888;
uwsgi_param UWSGI_CHDIR /django/demo;
uwsgi_param UWSGI_SCRIPT demo.wsgi;
include uwsgi_params;
}
}
四、Django+python+uwsgi+Nginx项目实战
环境
主机名 | 环境 | 内网ip | 外网ip |
---|---|---|---|
web01 | python+django_uwsgi+nginx | 172.16.1.7 | 10.0.0.7 |
db01(数据库) | mysql | 172.16.1.51 | 10.0.0.51 |
lb01 (负载均衡) | nginx | 172.16.1.5 | 10.0.0.5 |
1.安装python3环境
2.安装Django环境
3.下载博客系统、安装博客系统所需要的模块
4.配置博客链接的数据库、在数据上创建对应的库名;
5.导入博客的数据内容;
6.收集所有的静态资源文件到统一的一个目录中;
7.配置uwsgi运行
8.配置Nginx反向代理uwsgi
4.1 下载django博客系统
1.下载博客系统项目并解压
root@web01 ~]# mkdir -p /code && cd /code
[root@bgx code]# wget http://cdn.xuliangwei.com/pythonav.zip
[root@bgx code]# unzip pythonav.zip
2.安装该项目所需的依赖包软件
[root@web01 ~]# pip3 install -r /code/pythonav/requirements.txt
3.远程数据库10.0.0.51创建远程连接用户
MariaDB [(none)]> grant all privileges on *.* to 'app'@'172.16.1.%' identified by 'bertwu123';
4.创建数据库pythonav
MariaDB [(none)]> create database pythonav;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| pythonav |
+--------------------+
5.配置django连接数据库信息
[root@web01 ~]# vim /code/pythonav/pythonav/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'pythonav',
'USER': 'app',
'PASSWORD': 'bertwu123',
'HOST': '172.16.1.51',
'PORT': '3306',
}
}
6.初始化数据库并迁移
[root@web01 pythonav]# python3 manage.py makemigrations
[root@web01 pythonav]# python3 manage.py migrate
7.创建超级管理员用户
[root@web01 pythonav]# python3 manage.py createsuperuser
4.2 收集Django静态文件
收集静态资源至指定位置存储
[root@web01 pythonav]# python3 manage.py collectstatic
4.3 配置uwsgi运行项目
[root@web01 pythonav]# cat pythonav_uwsgi.ini
[uwsgi]
#uwsgi监听的端口
socket = 127.0.0.1:8811
chdir = /code/pythonav/
wsgi-file = pythonav/wsgi.py
#uwsgi启动进程数
processes = 4
threads = 10
#最大接收的请求数
max-requests = 1000
#buffer缓冲区大小
buffer-size = 30000
#进程pid存放路径
pidfile = /run/uwsgi-pythonav.pid
#uwsgi日志存储路径
daemonize = /var/log/uwsgi-pythonav.log
#启动uwsgi
[root@web01 ~]# uwsgi --ini /code/pythonav/pythonav_uwsgi.ini
4.4 配置Nginx代理uwsgi
[root@web01 conf.d]# cat pythonav.conf
server {
listen 80;
server_name avblog.bertwu.net;
client_max_body_size 100M;
location /static {
alias /code/pythonav/static;
}
location / {
uwsgi_pass 127.0.0.1:8811;
include uwsgi_params;
}
}
如果要做负载均衡,只需要在负载均衡服务器(10.0.0.5)加入如下配置:
[root@lb01 conf.d]# cat pythonav.conf
upstream python {
server 172.16.1.7:80;
}
server {
listen 80;
server_name avblog.bertwu.net;
location / {
proxy_pass http://python;
include proxy_params;
}
}