简单认识 Nginx
1. Nginx 是什么
Nginx 是一款高性能的 Web 服务器软件,主要用于提供网上信息浏览服务,为高并发网站的应用场景而设计,可以部署在 Linux、MacOS 和 Windows 等操作系统中,它的优点包括性能高、稳定性好、结构模块化、配置简单以及资源消耗非常低等。拥有 HTTPS 访问、gzip 压缩、虚拟主机和 URL 重写等功能,不但可以搭配 FastCGI 程序处理动态请求,还可以用于代理、反向代理、负载均衡和缓存服务等功能。
2. Nginx 主要功能
2.1 反向代理与负载均衡
-
正向代理
一个位于客户端和目标服务器之间的代理服务器,客户端将发送的请求和指定的目标服务器提交给代理服务器,然后代理服务器向目标服务器发起请求,并将获得的响应结果返回给客户端。
-
反向代理
反向代理对于客户端而言就是目标服务器,客户端反向代理服务器发送请求后,反向代理服务器将该请求转发给内部网络上的后端服务器,并从后端服务器上得到的响应结果返回给客户端。
-
负载均衡
负载均衡是基于反向代理实现的,也就是将负载分摊到多个操作单元上执行,从而提高服务 的可用性和响应速度,给用户更好的体验。
目前负载均衡有 4 中典型的配置方式,分别为轮询、权重、ip_hash 和利用第三方模块的方式。
配置方式 说明 轮询方式 负载均衡默认的设置方式,每个请求按照时间顺序逐一分配到不同的后端服务器进行处理,如果服务器宕机,会自动剔除。 权重方式 利用 weight 指定轮询的权重比率,与访问率成正比,用于后端服务器性能不均的情况。 ip_hash方式 每个请求按访问 IP 的 hash 结果分配,这样可以使每个访客固定访问一个后端服务器,可以解决 session 共享的问题。 第三方模块 第三方模块采用 fair 时,按每台服务器的响应时间进行分配请求,响应时间短的优先分配;若第三方模块采用 url_hash 时,按照访问 url 的 hash 值来分配请求。 1. 轮询方式
负载均衡默认的设置方式,每个请求按照时间顺序逐一分配到不同的后端服务器进行处理,如果服务器宕机,会自动剔除。
upstream test1 { server localhost:8080; server localhost:8081; } server { listen 80; server_name localhost; client_max_body_size 1024M; location / { proxy_pass http://test1; proxy_set_header Host $host:$server_port; } }
2.权重方式
利用 weight 指定轮询的权重比率,与访问率成正比,用于后端服务器性能不均的情况。
upstream test2 { server localhost:8080 weight=9; server localhost:8081 weight=1; } server { listen 80; server_name localhost; client_max_body_size 1024M; location / { proxy_pass http://test2; proxy_set_header Host $host:$server_port; } }
3.ip_hash 方式
每个请求按访问 IP 的 hash 结果分配,这样可以使每个访客固定访问一个后端服务器,可以解决 session 共享的问题。
upstream test3 { ip_hash; server localhost:8080; server localhost:8081; } server { listen 80; server_name localhost; client_max_body_size 1024M; location / { proxy_pass http://test3; proxy_set_header Host $host:$server_port; } }
4.第三方模块
第三方模块采用 fair 时,按每台服务器的响应时间进行分配请求,响应时间短的优先分配;若第三方模块采用 url_hash 时,按照访问 url 的 hash 值来分配请求。
upstream test4upstream test4 { fair; server localhost:8080; server localhost:8081; } server { listen 80; server_name localhost; client_max_body_size 1024M; location / { proxy_pass http://test4; proxy_set_header Host $host:$server_port; } }
2.2 动静分离
Nginx 提供的动静分离是指把动态请求和静态请求分开,合适的服务器处理响应的请求,是整个系统的性能、效率更高。
Nginx 可以根据配置对不同的请求进行不同转发,这是动静分离的基础。静态请求对应的静态资源可以直接放在 Nginx 上做缓冲,更好的做法是放在响应的缓冲服务器上。动态请求由响应的后端服务器处理。
upstream test {
server localhost:8080;
server localhost:8081;
}
server {
listen 80;
server_name localhost;
client_max_body_size 1024M;
location / {
root /usr/local/html/;
index index.html;
}
# 所有静态请求都由 Nginx 处理
location ~ \.(git|jpg|png|css|js)$ {
root /usr/local/html/;
}
location ~ \.(jsp|do)$ {
root /usr/local/html/;
}
error_page 500 502 503 504 /50x/html;
location = /50x.html {
root /usr/local/html/;
}
}
3. Nginx 配置详解
Nginx 的配置都写在 nginx.conf
的文件里,从 Nginx 的配置指令作用域来讲,分为 5 个作用于块,分别是:
- 全局作用于块
- event 作用域块
- http 指令作用域块
- server 指令作用域块
- location 指令作用域块
3.1 全局作用域块
在全局作用域块
中配置通用的 Nginx 配置,比如 Nginx 的用户组信息, Nginx 的并发进程数,日志存放位置等。
-
Nginx 的用户组信息配置,用来控制启动 Nginx 的权限;
-
服务并发一般情况下是越多越好,但当超过硬件的承受范围时会适得其反,所以一般我们会配置为 auto,这样 Nginx 会去检查硬件的信息,启用适当的进程数量。
# Nginx 用户及组: 用户 组。 windows 下不指定
user nginx nginx;
# 工作进程:数目。根据硬件调整,通常等于 CPU 数量或者 2 倍与 CPU。
worker_processes 8;
# 错误日志:存放路径
error_log logs/error.log
error_log logs/error.log notice;
error_log logs/error.log info;
# pid (进程标识符):存放路径
pid logs/nginx.pid;
3.2 event 作用域块
在event 作用域块
设置 Nginx 处理连接请求,在 event 模块通常会配置进程的连接数量,就是每一个 worker 进程能并发处理的最大连接数。
在server 指令作用域块
我们可以进行独立项目的代理配置。
events {
# 每个工作进程的最大连接数量。根据硬件调整,和前面工作进程配合使用,在不使得 CPU 满载(100%)情况下尽可能的大。每个进程允许的最多连接数,理论上每台 Nginx 服务器最大连接数为:worker_processes * worker_connctions
worker_connections 204800;
# 客户端请求头部的缓冲区大小。这个可以根据系统分页大小来设置,一般一个请求头的大小不会超过 1K,不过由于一般系统分页都要大于 1K,所以这里设置为分页大小。
# 分页大小可以用命令 getconf PAGESIZE 取得。假设从命令行得到的分页大小为 4096。
# 当 client_header_buffer_size 超过 4K 的情况,可以将该值设置为 4K 的整数倍数。
client_header_buffer_size 4K;
# 将为文件制定缓存,默认是没有启用,max 制定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没有被请求后删除缓存。
open_file_cache max=65535 inactive=60s;
# 多长时间检查一次缓存的有效信息
open_file_cache_valid 80s;
# 在 inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的。如果文件在 inactive 时间内一次都没有被使用过,则将其从缓存中移除。
open_file_cache_min_uses 1;
}
3.3 http 指令作用域块
Nginx 的 http 指令作用域块
用于控制 Nginx 的 HTTP 进程。
日志格式设置:
- remote_addr 与 $http_x_forwarded_for:记录客户端的 ip 地址;
- $remote_user:记录客户端的用户名称;
- $time_local:记录访问时间与时区;
- $request:记录请求的 url 与 http 协议;
- $status:记录请求状态,成功是200;
- $body_bytes_sent:记录发送给客户端文件主题内容大小;
- $http_referer:记录从哪个页面链接访问过来的;
- $http_user_agent:记录客户浏览器的相关信息;
通常 web 服务器放在反向代理的后面,这样就不能获取到客户端的 IP 地址,通过 $remote_addr 拿到的 IP 地址是反向代理服务器的 IP 地址。反向代理服务器在转发请求的 http 头信息中,可以增加 x_forwarded_for 信息,用以记录原有客户端的 IP 地址和原来客户端请求的服务器地址。
# 设定 http 服务器,利用它的反向代理功能提供负载均衡支持
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$htto_x_forwarded_for"';
log_format log404 '$status [$time_local] $remote_addr $host$request_uri $sent_http_location';
# 用了 log_format 指令设置了日志格式之后,需要用 access_log 指令指定日志文件的存放路径;
access_log logs/host.access.log main;
access_log logs/host.access.404.log log404;
# 客户端请求头部的缓冲区大小。可以参见 event 作用域块中的说明。
client_header_buffer_size 4k;
# 客户端请求头最大缓冲大小和数量。Nginx 默认会用 client_header_buffer_size 这个 buffer 来读取 header 值,如果 header 过大,则会使用 large_client_header_buffers 来读取。
large_client_header_buffers 8 128k;
# 指定缓存是否启用。
open_file_cache max=102400 inactive=20s;
# 何时需要检查 open_file_cache 中缓存项目的有效信息
open_file_cache_valid 30s;
# 在缓存参数 inactive 时间内文件使用的最少次数,若使用次数大于该值,则文件描述符在缓存中处于打开状态。
open_file_cache_min_uses 2;
# 指定是否在搜索一个文件时记录 cache 错误 [open_file_cache_errors on | off]
open_file_cache_errors on;
# 设定通过 Nginx 上传文件的大小
client_max_body_size 300m;
# 指定 Nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为 on。如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 IO 处理速度,降低系统 uptime。
sendfile on;
# 此选项允许或禁止使用 socket 的 TCP_CORK 的选项,此选项仅在 sendfile 的时候使用
tcp_nopush on;
# 后端服务器连接的超时时间(发起握手等候响应超时时间)
proxy_read_timeout 180;
# 后端服务器数据回传时间(在规定时间之内后端服务器必须传完所有的数据)
proxy_send_timeout 180;
# 设置从被代理服务器读取的第一部分应答的缓冲区大小
proxy_buffer_size 256k;
# 设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小
proxy_buffer 4 256k;
proxy_busy_buffer_size 256k;
# 设置在写入 proxy_temp_path 时数据的大小,预防一个工作进程在传递文件时阻塞太长
proxy_temp_file-write_size 256k;
# proxy_temp_path 和 proxy_cache_path 指定路径必须在同一分区
proxy_temp_path /data0/proxy_temp_dir;
# 设置内存缓存空间大小为 200MB,1天没有被访问的内容自动清除,硬盘缓存空间大小为 30GB
proxy_cache_path /data0/proxy_cache_dir levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
# 客户端请求服务器的最大允许大小
client_body_buffer_size 512k;
# 表示 Nginx 阻止 HTTP 应答代码为 400 或者更高的应答。
proxy_intercept_errors on;
# 负载均衡
upstream backend {
server server1;
server server2;
}
}
3.4 server 指令作用域块和 location 指令作用域块
# 配置虚拟机
server {
# 配置监听端口
listen 80;
# 配置访问域名
server_name image.***.com;
# 对以 mp3/exe 结尾的地址进行负载均衡
location ~* \.(mp3|exe)$ {
# 设置被代理服务器的端口或套接字,以及 URL
proxy_pass http://img_relay$request_uri;
# 将代理服务器收到的用户信息传到真实的服务器上
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /face {
if($http_user_agent ~* "xnp") {
rewrite ^(.*)$ http://127.0.0.1:8080/face.jpg redirect;
}
# 将代理服务器收到的用户信息传到真实的服务器上
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 404 502 = @fetch;
}
location @fetch {
access_log /data/logs/face.log log404;
rewrite ^(.*)$ http://127.0.0.1:8080/face.jpg redirect;
}
location /image {
if($http_user_agent ~* "xnp") {
rewrite ^(.*)$ http://127.0.0.1:8080/face.jpg redirect;
}
proxy_pass http://img_relay$request_uri;
# 将代理服务器收到的用户信息传到真实的服务器上
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 404 502 = @fetch;
}
}
location 匹配规则说明:
- ~:表示执行一个正则匹配,区分大小写
- ~*:表示执行一个正则匹配,不区分大小写
- ^~:表示普通字符串匹配,如果该选项匹配,只匹配该选项,不匹配别的选项(一般用来匹配目录)
- @:定义一个命名的 location,在内部定向时使用,例如 error_page,try_files
优先级顺序: 精确匹配 > 正则匹配 > 部分匹配 > 通用匹配
(location = ) > (location 完整路径) > (location ^~ 路径) > (location ~ | ~* 正则匹配) > (location 部分起始路径) > (location /)
# location =
location = / {
# 精确匹配 /,主机名后面不能带任何字符串
[ configuration A ]
}
# location /
location / {
# 所有地址都是以 / 开头,因此匹配所有请求
[ configuration B ]
}
# location 部分起始路径
location /documents/ {
# 匹配任何以 /documents/ 开头的地址
[ configuration C ]
}
#location ^~ 路径
location ^~ /images/ {
# 匹配任何以 /images/ 开头的地址
[ configuration D ]
}
#location ~ 正则匹配
location ~ /documents/Abc {
# 匹配包含 /documents/Abc 的地址(区分大小写)
[ configuration CC ]
}
# location ~* 正则匹配
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以 gif,jpg或jpeg 结尾的请求(不区分大小写)
[ configuration E ]
}
location /images/ {
[ configuration F ]
}
location /images/abc {
[ configuration G ]
}
# location ~* 正则匹配
location ~* /js/.*\.js {
# 匹配 /js/[anychars].js (不区分大小写)
[ configuration H ]
}