WebServer和WebAPP
之前对于nginx的了解都只是听说,根本就不知道nginx对于整个网站的作用。经历了数个项目之后,我本人逐渐对nginx有了更深入的了解,也希望把这段经历拿出来分享给大家!
由于我本人之前接触的都是Python的Django后端开发,那么现在我也就以Django为例来说明Nginx的作用。
学过Django的人都知道,我们使用一条名叫
python manager.py runserver 8000
的指令来运行我们的Django项目,可是很多人都不知道这句话背后到底干了什么,我先把这个点讲明白。
- Django作为一个比较大型的框架,其内部集成了Web服务器,我们编写的Django呢就相当于是Web应用。我们想使用Web应用中提供的服务,必须有一个Web服务器来为我们“指路”,只有这样我们才能与Web应用连接,找到我们想要的服务。
他们之间的关系如下图所示https://img-blog.csdnimg.cn/2ddf8c3e64b34df0b6f11731b348276f.png" alt="请添加图片描述" />
我们使用指令打开的是Django内置的Web服务器。这个服务器呢,如果用来测试的话完全够用了,但是如果面对真正要上线的网站就完全不够用了,我们通常使用unicorn等WebServer来运行我们的web项目。
- 我们这里就能看见,一个基于python项目的WebServer仅仅只能运行在一个项目上。如果我们的项目真正面向大众了,同时几千万的访问对一台服务器来说是肯定吃不消的。但是如果这时候只使用uvicorn这种比较低级WebServer,那用户在访问的时候还要手动选择要访问的服务器,这显然是我们不愿意看到的情况。不仅仅用户体验非常差,而且服务器也有较大的风险。
如何解决这个问题呢?
如果我们在基层的WebServer上再套一层WebServer的话问题就能迎刃而解。
那么我们网络的拓扑结构就变成了:
https://img-blog.csdnimg.cn/b6611a55666743f49a24d2c53d261dc5.png" alt="请添加图片描述" />
这样做有很多优点:
- 用户不用挑选要访问的服务器,只需要访问第一级的WebServer就可以了
- 第一级的WebServer会根据用户访问的域名不同,分配到正确的Web服务器上
- 同一个网站可以部署在多个服务器上,一级服务器可以根据每台服务器的负载情况把请求分配合适的服务器处理
在Django+Nginx的项目中,拓扑结构是这样的:
https://img-blog.csdnimg.cn/20db77678ef84d659074140705a55d3f.png" alt="请添加图片描述" />
用户通过http/https协议访问Nginx服务器,Nginx会根据域名和负载情况的不同把请求传递给其下方的服务器。Nginx处理请求后会使用uwsgi协议把信息转移到子Server上,子Server内部使用wsgi协议或者uwsgi协议与WebApp进行交流。
从Nginx配置开始一整套部署
我们调节Nginx,主要就是对nginx.conf配置文件的调整,Nginx配置文件的结构如下
- 全局块
全局配置部分用来配置对整个server都有效的参数。主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以 及配置文件的引入等。
user nobody;
worker_processes 4;
error_log /data/nginx/logs/error.log notice;
- events块
events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
events {
#每个 work process 支持的最大连接数为 1024.
worker_connections 1024;
}
- http块(最重要)
这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。需要注意的是:http 块也可以包括 http全局块、server块。
细说配置文件的http块
1.http全局块
http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
2. server块(重中之重)
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
- 全局server块
server {
listen 80;
#server_name也支持通配符,*.example.com、www.example.*、.example.com
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
- location块(类似于Django的路由)
这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称 (也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
location 指令说明:
该指令用于匹配 URL。
语法如下:location [ = | ~ | ~* | ^~] uri{}
?> Tip 注意:如果 uri 包含正则表达式,则必须要有 ~ 或者 ~* 标识。
当一个请求进入时,URI将会被检测匹配一个最佳的location。
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location / {
#try_files指令将会按照给定的参数顺序进行匹配尝试
try_files $uri $uri/ /index.html;
}
项目的反向代理设置
# 配置http块内的server块
server {
listen 80; # 监听80端口的访问
server_name localhost; # 检测访问进来的域名(里边可以填入域名),符合server_name后进入该server
location / {
# location后边跟路由,/代表根目录
proxy_pass xxxxx # 把请求传递给某个server,xxxxx为子server的名称
}
}
Nginx会持续不断地监听(listen)80端口(http访问的默认端口),如果有符合条件的域名(server_name)和路由(location)命中规则,就会通过内部的转发(proxy_pass )转发到其子Server上。