今天,我要一举拿下Nginx!
关注公众号后台回复pay或mall获取实战项目资料+视频
作者:Lion 出处:juejin.cn/post/6942607113118023710
作为一名前端开发人员,你是不是经常碰到领导让你上服务器去修改 Nginx 配置,然而你会以“我是前端,这个我不会”为理由搪塞过去呢!今天就让我们一起告别这种尴尬,向“真正”的程序员迈进!
01
Nginx 概述
02
Nginx 特点
高并发、高性能。
模块化架构使得它的扩展性非常好。
异步非阻塞的事件驱动模型这点和 Node.js 相似。
相对于其它服务器来说它可以连续几个月甚至更长而不需要重启服务器使得它具有高可靠性。
热部署、平滑升级。
完全开源,生态繁荣。
03
Nginx 作用
静态资源服务,通过本地文件系统提供服务。
反向代理服务,延伸出包括缓存、负载均衡等。
API 服务,OpenResty。
对于前端来说 Node.js 并不陌生,Nginx 和 Node.js 的很多理念类似,HTTP 服务器、事件驱动、异步非阻塞等,且 Nginx 的大部分功能使用 Node.js 也可以实现,但 Nginx 和 Node.js 并不冲突,都有自己擅长的领域。
Nginx 擅长于底层服务器端资源的处理(静态资源处理转发、反向代理,负载均衡等),Node.js 更擅长上层具体业务逻辑的处理,两者可以完美组合。
用一张图表示:
04
Nginx 安装
使用 yum 安装 Nginx:
yum install nginx -y
安装完成后,通过 rpm -ql nginx 命令查看 Nginx 的安装信息:
# Nginx 配置文件
/etc/nginx/nginx.conf # Nginx 主配置文件
/etc/nginx/nginx.conf.default
# 可执行程序文件
/usr/bin/nginx-upgrade
/usr/sbin/nginx
# Nginx 库文件
/usr/lib/systemd/system/nginx.service # 用于配置系统守护进程
/usr/lib64/nginx/modules # Nginx 模块目录
# 帮助文档
/usr/share/doc/nginx-1.16.1
/usr/share/doc/nginx-1.16.1/CHANGES
/usr/share/doc/nginx-1.16.1/README
/usr/share/doc/nginx-1.16.1/README.dynamic
/usr/share/doc/nginx-1.16.1/UPGRADE-NOTES-1.6-to-1.10
# 静态资源目录
/usr/share/nginx/html/404.html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
# 存放 Nginx 日志文件
/var/log/nginx
/etc/nginx/conf.d/ 是子配置项存放处,/etc/nginx/nginx.conf 主配置文件会默认把这个文件夹中所有子配置项都引入。
/usr/share/nginx/html/ 静态文件都放在这个文件夹,也可以根据你自己的习惯放在其他地方。
05
Nginx 常用命令
systemctl 系统命令:
# 开机配置
systemctl enable nginx # 开机自动启动
systemctl disable nginx # 关闭开机自动启动
# 启动 Nginx
systemctl start nginx # 启动Nginx成功后,可以直接访问主机IP,此时会展示Nginx默认页面
# 停止 Nginx
systemctl stop nginx
# 重启 Nginx
systemctl restart nginx
# 重新加载 Nginx
systemctl reload nginx
# 查看 Nginx 运行状态
systemctl status nginx
# 查看 Nginx 进程
ps -ef | grep nginx
# 杀死 Nginx 进程
kill -9 pid # 根据上面查看到的 Nginx 进程号,杀死 Nginx 进程,-9 表示强制结束进程
Nginx 应用程序命令:
nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启
nginx -s reopen # 重启 Nginx
nginx -s stop # 快速关闭
nginx -s quit # 等待工作进程处理完成后关闭
nginx -T # 查看当前 Nginx 最终的配置
nginx -t # 检查配置是否有问题
06
Nginx 核心配置
Nginx 的典型配置示例:
main 全局配置,对全局生效。
events 配置影响 Nginx 服务器与用户的网络连接。
http 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
server 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块。
location 用于配置匹配的 uri。
upstream 配置后端服务器具体地址,负载均衡配置不可或缺的部分。
# main 段配置信息
user nginx; # 运行用户,默认即是 Nginx,可以不进行设置
worker_processes auto; # Nginx 进程数,一般设置为和 CPU 核数一样
error_log /var/log/nginx/error.log warn; # Nginx 的错误日志存放目录
pid /var/run/nginx.pid; # Nginx 服务启动时的 pid 存放位置
# events 段配置信息
events {
use epoll; # 使用 epoll 的 I/O 模型(如果你不知道 Nginx 该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
worker_connections 1024; # 每个进程允许最大并发数
}
# http 段配置信息
# 配置使用最频繁的部分,代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里设置
http {
# 设置日志模式
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; # Nginx 访问日志存放位置
sendfile on; # 开启高效传输模式
tcp_nopush on; # 减少网络报文段的数量
tcp_nodelay on;
keepalive_timeout 65; # 保持连接的时间,也叫超时时间,单位秒
types_hash_max_size 2048;
include /etc/nginx/mime.types; # 文件扩展名与类型映射表
default_type application/octet-stream; # 默认文件类型
include /etc/nginx/conf.d/*.conf; # 加载子配置项
# server段配置信息
server {
listen 80; # 配置监听的端口
server_name localhost; # 配置的域名
# location段配置信息
location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认首页文件
deny 172.168.22.11; # 禁止访问的 ip 地址,可以为 all
allow 172.168.33.44;# 允许访问的 ip 地址,可以为 all
}
error_page 500 502 503 504 /50x.html; # 默认 50x 对应的访问页面
error_page 400 404 error.html; # 同上
}
}
用一张图清晰的展示它的层级结构:
user:指定运行 Nginx 的 woker 子进程的属主和属组,其中组可以不指定。
user USERNAME [GROUP]
user nginx lion; # 用户是 Nginx;组是 lion
pid:指定运行 Nginx master 主进程的 pid 文件存放路径。
pid /opt/nginx/logs/nginx.pid # master主进程的的 pid 存放在 nginx.pid 的文件
worker_rlimit_nofile_number:指定 worker 子进程可以打开的最大文件句柄数。
worker_rlimit_nofile 20480; # 可以理解成每个 worker 子进程的最大连接数量。
worker_rlimit_core:指定 worker 子进程异常终止后的 core 文件,用于记录分析问题。
worker_rlimit_core 50M; # 存放大小限制
working_directory /opt/nginx/tmp; # 存放目录
worker_processes 4; # 指定具体子进程数量
worker_processes auto; # 与当前 CPU 物理核心数一致
worker_cpu_affinity:将每个 worker 子进程与我们的 CPU 物理核心绑定。
worker_cpu_affinity 0001 0010 0100 1000; # 4个物理核心,4个 worker 子进程
worker_priority:指定 worker 子进程的 nice 值,以调整运行 Nginx 的优先级,通常设定为负值,以优先调用 Nginx 。
worker_priority -10; # 120-10=110,110 就是最终的优先级
worker_shutdown_timeout:指定 worker 子进程优雅退出时的超时时间。
worker_shutdown_timeout 5s;
timer_resolution:worker 子进程内部使用的计时器精度,调整时间间隔越大,系统调用越少,有利于性能提升;反之,系统调用越多,性能下降。
timer_resolution 100ms;
daemon:指定 Nginx 的运行方式,前台还是后台,前台用于调试,后台用于生产。
daemon off; # 默认是 on,后台运行模式
use:Nginx 使用何种事件驱动模型。
use method; # 不推荐配置它,让 Nginx 自己选择
method 可选值为:select、poll、kqueue、epoll、/dev/poll、eventport
worker_connections:worker 子进程能够处理的最大并发连接数。
worker_connections 1024 # 每个子进程的最大连接数为 1024
accept_mutex:是否打开负载均衡互斥锁。
accept_mutex on # 默认是 off 关闭的,这里推荐打开
server_name 指令:指定虚拟主机域名。
server_name name1 name2 name3
# 示例:
server_name www.nginx.com;
精确匹配:server_name www.nginx.com
左侧通配:server_name *.nginx.com
右侧统配:server_name www.nginx.*
正则匹配:server_name ~^www\.nginx\.*$
配置本地 DNS 解析 vim /etc/hosts (macOS 系统):
# 添加如下内容,其中 121.42.11.34 是阿里云服务器 IP 地址
121.42.11.34 www.nginx-test.com
121.42.11.34 mail.nginx-test.com
121.42.11.34 www.nginx-test.org
121.42.11.34 doc.nginx-test.com
121.42.11.34 www.nginx-test.cn
121.42.11.34 fe.nginx-test.club
# 这里只列举了 http 端中的 sever 端配置
# 左匹配
server {
listen 80;
server_name *.nginx-test.com;
root /usr/share/nginx/html/nginx-test/left-match/;
location / {
index index.html;
}
}
# 正则匹配
server {
listen 80;
server_name ~^.*\.nginx-test\..*$;
root /usr/share/nginx/html/nginx-test/reg-match/;
location / {
index index.html;
}
}
# 右匹配
server {
listen 80;
server_name www.nginx-test.*;
root /usr/share/nginx/html/nginx-test/right-match/;
location / {
index index.html;
}
}
# 完全匹配
server {
listen 80;
server_name www.nginx-test.com;
root /usr/share/nginx/html/nginx-test/all-match/;
location / {
index index.html;
}
}
当访问 www.nginx-test.com 时,都可以被匹配上,因此选择优先级最高的“完全匹配”。
当访问 mail.nginx-test.com 时,会进行“左匹配”。
当访问 www.nginx-test.org 时,会进行“右匹配”。
当访问 doc.nginx-test.com 时,会进行“左匹配”。
当访问 www.nginx-test.cn 时,会进行“右匹配”。
当访问 fe.nginx-test.club 时,会进行“正则匹配”。
指定静态资源目录位置,它可以写在 http、server、location 等配置中。
root path
例如:
location /image {
root /opt/nginx/static;
}
当用户访问 www.test.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
它也是指定静态资源目录位置,它只能写在 location 中。
location /image {
alias /opt/nginx/static/image/;
}
当用户访问 www.test.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
配置路径:
location [ = | ~ | ~* | ^~ ] uri {
...
}
= 精确匹配
~ 正则匹配,区分大小写
~* 正则匹配,不区分大小写
^~ 匹配到即停止搜索
实例:
server {
listen 80;
server_name www.nginx-test.com;
# 只有当访问 www.nginx-test.com/match_all/ 时才会匹配到/usr/share/nginx/html/match_all/index.html
location = /match_all/ {
root /usr/share/nginx/html
index index.html
}
# 当访问 www.nginx-test.com/1.jpg 等路径时会去 /usr/share/nginx/images/1.jpg 找对应的资源
location ~ \.(jpeg|jpg|png|svg)$ {
root /usr/share/nginx/images;
}
# 当访问 www.nginx-test.com/bbs/ 时会匹配上 /usr/share/nginx/html/bbs/index.html
location ^~ /bbs/ {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
不带 / 当访问 www.nginx-test.com/test 时, Nginx 先找是否有 test 目录,如果有则找 test 目录下的 index.html;如果没有 test 目录,Nginx 则会找是否有 test 文件。
带 / 当访问 www.nginx-test.com/test 时,Nginx 先找是否有 test 目录,如果有则找 test 目录下的 index.html,如果没有它也不会去找是否存在 test 文件。
location /test {
...
}
location /test/ {
...
}
return code [text];
return code URL;
return URL;
例如:
location / {
return 404; # 直接返回状态码
}
location / {
return 404 "pages not found"; # 返回状态码 + 一段文本
}
location / {
return 302 /bbs ; # 返回状态码 + 重定向地址
}
location / {
return https://www.baidu.com ; # 返回重定向地址
}
rewrite:根据指定正则表达式匹配规则,重写 URL。
语法:rewrite 正则表达式 要替换的内容 [flag];
上下文:server、location、if
示例:rewirte /images/(.*\.jpg)$ /pic/$1; # $1是前面括号(.*\.jpg)的反向引用
last 重写后的 URL 发起新请求,再次进入 server 段,重试 location 的中的匹配。
break 直接使用重写后的 URL ,不再匹配其它 location 中语句。
redirect 返回 302 临时重定向。
permanent 返回 301 永久重定向。
server{
listen 80;
server_name fe.lion.club; # 要在本地 hosts 文件进行配置
root html;
location /search {
rewrite ^/(.*) https://www.baidu.com redirect;
}
location /images {
rewrite /images/(.*) /pics/$1;
}
location /pics {
rewrite /pics/(.*) /photos/$1;
}
location /photos {
}
}
按照这个配置我们来分析:
当访问 fe.lion.club/search 时,会自动帮我们重定向到 https://www.baidu.com。
当访问 fe.lion.club/images/1.jpg 时,第一步重写 URL 为 fe.lion.club/pics/1.jpg,找到 pics 的 location,继续重写 URL 为 fe.lion.club/photos/1.jpg,找到 /photos 的 location 后,去 html/photos 目录下寻找 1.jpg 静态资源。
语法:if (condition) {...}
上下文:server、location
示例:
if($http_user_agent ~ Chrome){
rewrite /(.*)/browser/$1 break;
}
$variable 仅为变量时,值为空或以 0 开头字符串都会被当做 false 处理。
= 或 != 相等或不等。
~ 正则匹配。
! ~ 非正则匹配。
~* 正则匹配,不区分大小写。
-f 或 ! -f 检测文件存在或不存在。
-d 或 ! -d 检测目录存在或不存在。
-e 或 ! -e 检测文件、目录、符号链接等存在或不存在。
-x 或 ! -x 检测文件可以执行或不可执行。
实例:
server {
listen 8080;
server_name localhost;
root html;
location / {
if ( $uri = "/images/" ){
rewrite (.*) /pics/ break;
}
}
}
⑧autoindex
用户请求以 / 结尾时,列出目录结构,可以用于快速搭建静态资源下载网站。autoindex.conf 配置信息:
server {
listen 80;
server_name fe.lion-test.club;
location /download/ {
root /opt/source;
autoindex on; # 打开 autoindex,,可选参数有 on | off
autoindex_exact_size on; # 修改为 off,以 KB、MB、GB 显示文件大小,默认为 on,以 bytes 显示出⽂件的确切⼤⼩
autoindex_format html; # 以 html 的方式进行格式化,可选参数有 html | json | xml
autoindex_localtime off; # 显示的⽂件时间为⽂件的服务器时间。默认为 off,显示的⽂件时间为GMT时间
}
}
当访问 fe.lion.com/download/ 时,会把服务器 /opt/source/download/ 路径下的文件展示出来,如下图所示:
下面列举些项目中常用的变量:
实例演示 var.conf:
server{
listen 8081;
server_name var.lion-test.club;
root /usr/share/nginx/html;
location / {
return 200 "
remote_addr: $remote_addr
remote_port: $remote_port
server_addr: $server_addr
server_port: $server_port
server_protocol: $server_protocol
binary_remote_addr: $binary_remote_addr
connection: $connection
uri: $uri
request_uri: $request_uri
scheme: $scheme
request_method: $request_method
request_length: $request_length
args: $args
arg_pid: $arg_pid
is_args: $is_args
query_string: $query_string
host: $host
http_user_agent: $http_user_agent
http_referer: $http_referer
http_via: $http_via
request_time: $request_time
https: $https
request_filename: $request_filename
document_root: $document_root
";
}
}
当我们访问 http://var.lion-test.club:8081/test?pid=121414&cid=sadasd 时,由于 Nginx 中写了 return 方法,因此 chrome 浏览器会默认为我们下载一个文件,下面展示的就是下载的文件内容:
remote_addr: 27.16.220.84
remote_port: 56838
server_addr: 172.17.0.2
server_port: 8081
server_protocol: HTTP/1.1
binary_remote_addr: 茉
connection: 126
uri: /test/
request_uri: /test/?pid=121414&cid=sadasd
scheme: http
request_method: GET
request_length: 518
args: pid=121414&cid=sadasd
arg_pid: 121414
is_args: ?
query_string: pid=121414&cid=sadasd
host: var.lion-test.club
http_user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36
http_referer:
http_via:
request_time: 0.000
https:
request_filename: /usr/share/nginx/html/test/
document_root: /usr/share/nginx/html
07
Nginx 应用核心概念
不管是正向代理还是反向代理,实现的都是上面的功能。
②反向代理
隐藏真实服务器。
负载均衡便于横向扩充后端动态服务。
动静分离,提升系统健壮性。
③动静分离
动静分离是指在 web 服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提示整个服务的访问性和可维护性。
举个具体的例子,晚高峰乘坐地铁的时候,入站口经常会有地铁工作人员大喇叭“请走 B 口, B 口人少车空……”,这个工作人员的作用就是负载均衡。
轮询策略:默认情况下采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
最小连接数策略:将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
最快响应时间策略:优先分配给响应时间最短的服务器。
客户端 IP 绑定策略:来自同一个 IP 的请求永远只分配一台服务器,有效解决了动态网页存在的 session 共享问题。
08
Nginx 实战配置
语法:upstream name {
...
}
上下文:http
示例:
upstream back_end_server{
server 192.168.100.33:8081
}
用于定义上游服务器(指的就是后台提供的应用服务器)的相关信息。
server 定义上游服务器地址。
zone 定义共享内存,用于跨 worker 子进程。
keepalive 对上游服务启用长连接。
keepalive_requests 一个长连接最多请求 HTTP 的个数。
keepalive_timeout 空闲情形下,一个长连接的超时时长。
hash 哈希负载均衡算法。
ip_hash 依据 IP 进行哈希计算的负载均衡算法。
least_conn 最少连接数负载均衡算法。
least_time 最短响应时间负载均衡算法。
random 随机负载均衡算法。
server:定义上游服务器地址。
语法:server address [parameters]
上下文:upstream
weight=number 权重值,默认为 1。
max_conns=number 上游服务器的最大并发连接数。
fail_timeout=time 服务器不可用的判定时间。
max_fails=numer 服务器不可用的检查次数。
backup 备份服务器,仅当其他服务器都不可用时才会启用。
down 标记服务器长期不可用,离线维护。
keepalive:限制每个 worker 子进程与上游服务器空闲长连接的最大数量。
keepalive connections;
上下文:upstream
示例:keepalive 16;
keepalive_requests:单个长连接可以处理的最多 HTTP 请求个数。
语法:keepalive_requests number;
默认值:keepalive_requests 100;
上下文:upstream
keepalive_timeout:空闲长连接的最长保持时间。
语法:keepalive_timeout time;
默认值:keepalive_timeout 60s;
上下文:upstream
配置实例:
upstream back_end{
server 127.0.0.1:8081 weight=3 max_conns=1000 fail_timeout=10s max_fails=2;
keepalive 32;
keepalive_requests 50;
keepalive_timeout 30s;
}
用于配置代理服务器:
语法:proxy_pass URL;
上下文:location、if、limit_except
示例:
proxy_pass http://127.0.0.1:8081
proxy_pass http://127.0.0.1:8081/proxy
URL 必须以 http 或 https 开头。
URL 中可以携带变量。
URL 中是否带 URI ,会直接影响发往上游请求的 URL。
接下来让我们来看看两种常见的 URL 用法:
proxy_pass http://192.168.100.33:8081
proxy_pass http://192.168.100.33:8081/
不带 / 意味着 Nginx 不会修改用户 URL,而是直接透传给上游的应用服务器;
带 / 意味着 Nginx 会修改用户 URL ,修改方法是将 location 后的 URL 从用户 URL 中删除;
不带 / 的用法:
location /bbs/{
proxy_pass http://127.0.0.1:8080;
}
用户请求 URL:/bbs/abc/test.html
请求到达 Nginx 的 URL:/bbs/abc/test.html
请求到达上游应用服务器的 URL :/bbs/abc/test.html
带 / 的用法:
location /bbs/{
proxy_pass http://127.0.0.1:8080/;
}
用户请求 URL:/bbs/abc/test.html
请求到达 Nginx 的 URL:/bbs/abc/test.html
请求到达上游应用服务器的 URL:/abc/test.html
我们把 121.42.11.34 服务器作为上游服务器,做如下配置:
# /etc/nginx/conf.d/proxy.conf
server{
listen 8080;
server_name localhost;
location /proxy/ {
root /usr/share/nginx/html/proxy;
index index.html;
}
}
# /usr/share/nginx/html/proxy/index.html
<h1> 121.42.11.34 proxy html </h1>
把 121.5.180.193 服务器作为代理服务器,做如下配置:
# /etc/nginx/conf.d/proxy.conf
upstream back_end {
server 121.42.11.34:8080 weight=2 max_conns=1000 fail_timeout=10s max_fails=3;
keepalive 32;
keepalive_requests 80;
keepalive_timeout 20s;
}
server {
listen 80;
server_name proxy.lion.club;
location /proxy {
proxy_pass http://back_end/proxy;
}
}
本地机器要访问 proxy.lion.club 域名,因此需要配置本地 hosts,通过命令:vim /etc/hosts 进入配置文件,添加如下内容:
121.5.180.193 proxy.lion.club
当访问 proxy.lion.club/proxy 时通过 upstream 的配置找到 121.42.11.34:8080。
因此访问地址变为 http://121.42.11.34:8080/proxy。
连接到 121.42.11.34 服务器,找到 8080 端口提供的 server。
通过 server 找到 /usr/share/nginx/html/proxy/index.html 资源,最终展示出来。
我们把 121.42.11.34 服务器作为上游服务器,做如下配置(/etc/nginx/conf.d/balance.conf):
server{
listen 8020;
location / {
return 200 'return 8020 \n';
}
}
server{
listen 8030;
location / {
return 200 'return 8030 \n';
}
}
server{
listen 8040;
location / {
return 200 'return 8040 \n';
}
}
nginx -t 检测配置是否正确。
nginx -s reload 重启 Nginx 服务器。
执行 ss -nlt 命令查看端口是否被占用,从而判断 Nginx 服务是否正确启动。
把 121.5.180.193 服务器作为代理服务器,做如下配置(/etc/nginx/conf.d/balance.conf):
upstream demo_server {
server 121.42.11.34:8020;
server 121.42.11.34:8030;
server 121.42.11.34:8040;
}
server {
listen 80;
server_name balance.lion.club;
location /balance/ {
proxy_pass http://demo_server;
}
}
配置完成后重启 Nginx 服务器。并且在需要访问的客户端配置好 ip 和域名的映射关系。
# /etc/hosts
121.5.180.193 balance.lion.club
在客户端机器执行 curl http://balance.lion.club/balance/ 命令:
hash 算法:通过制定关键字作为 hash key,基于 hash 算法映射到特定的上游服务器中。关键字可以包含有变量、字符串。
upstream demo_server {
hash $request_uri;
server 121.42.11.34:8020;
server 121.42.11.34:8030;
server 121.42.11.34:8040;
}
server {
listen 80;
server_name balance.lion.club;
location /balance/ {
proxy_pass http://demo_server;
}
}
ip_hash:根据客户端的请求 ip 进行判断,只要 ip 地址不变就永远分配到同一台主机。它可以有效解决后台服务器 session 保持的问题。
upstream demo_server {
ip_hash;
server 121.42.11.34:8020;
server 121.42.11.34:8030;
server 121.42.11.34:8040;
}
server {
listen 80;
server_name balance.lion.club;
location /balance/ {
proxy_pass http://demo_server;
}
}
最少连接数算法:各个 worker 子进程通过读取共享内存的数据,来获取后端服务器的信息。来挑选一台当前已建立连接数最少的服务器进行分配请求。
语法:least_conn;
上下文:upstream;
示例:
upstream demo_server {
zone test 10M; # zone可以设置共享内存空间的名字和大小
least_conn;
server 121.42.11.34:8020;
server 121.42.11.34:8030;
server 121.42.11.34:8040;
}
server {
listen 80;
server_name balance.lion.club;
location /balance/ {
proxy_pass http://demo_server;
}
}
proxy_cache:存储一些之前被访问过、而且可能将要被再次访问的资源,使用户可以直接从代理服务器获得,从而减少上游服务器的压力,加快整个访问速度。
语法:proxy_cache zone | off ; # zone 是共享内存的名称
默认值:proxy_cache off;
上下文:http、server、location
proxy_cache_path:设置缓存文件的存放路径。
语法:proxy_cache_path path [level=levels] ...可选参数省略,下面会详细列举
默认值:proxy_cache_path off
上下文:http
path 缓存文件的存放路径。
level path 的目录层级。
keys_zone 设置共享内存。
inactive 在指定时间内没有被访问,缓存会被清理,默认 10 分钟。
proxy_cache_key:设置缓存文件的 key 。
语法:proxy_cache_key
默认值:proxy_cache_key $scheme$proxy_host$request_uri;
上下文:http、server、location
proxy_cache_valid:配置什么状态码可以被缓存,以及缓存时长。
语法:proxy_cache_valid [code...] time;
上下文:http、server、location
配置示例:proxy_cache_valid 200 304 2m;; # 说明对于状态为 200 和 304 的缓存文件的缓存时间是 2 分钟
proxy_no_cache:定义相应保存到缓存的条件,如果字符串参数的至少一个值不为空且不等于“ 0”,则将不保存该响应到缓存。
语法:proxy_no_cache string;
上下文:http、server、location
示例:proxy_no_cache $http_pragma $http_authorization;
proxy_cache_bypass:定义条件,在该条件下将不会从缓存中获取响应。
语法:proxy_cache_bypass string;
上下文:http、server、location
示例:proxy_cache_bypass $http_pragma $http_authorization;
upstream_cache_status 变量:它存储了缓存是否命中的信息,会设置在响应头信息中,在调试中非常有用。
MISS:未命中缓存
HIT:命中缓存
EXPIRED:缓存过期
STALE:命中了陈旧缓存
REVALIDDATED:Nginx 验证陈旧缓存依然有效
UPDATING:内容陈旧,但正在更新
BYPASS:X响应从原始服务器获取
配置实例:我们把 121.42.11.34 服务器作为上游服务器,做如下配置(/etc/nginx/conf.d/cache.conf):
server {
listen 1010;
root /usr/share/nginx/html/1010;
location / {
index index.html;
}
}
server {
listen 1020;
root /usr/share/nginx/html/1020;
location / {
index index.html;
}
}
把 121.5.180.193 服务器作为代理服务器,做如下配置(/etc/nginx/conf.d/cache.conf):
proxy_cache_path /etc/nginx/cache_temp levels=2:2 keys_zone=cache_zone:30m max_size=2g inactive=60m use_temp_path=off;
upstream cache_server{
server 121.42.11.34:1010;
server 121.42.11.34:1020;
}
server {
listen 80;
server_name cache.lion.club;
location / {
proxy_cache cache_zone; # 设置缓存内存,上面配置中已经定义好的
proxy_cache_valid 200 5m; # 缓存状态为 200 的请求,缓存时长为 5 分钟
proxy_cache_key $request_uri; # 缓存文件的 key 为请求的URI
add_header Nginx-Cache-Status $upstream_cache_status # 把缓存状态设置为头部信息,响应给客户端
proxy_pass http://cache_server; # 代理转发
}
}
对于一些实时性要求非常高的页面或数据来说,就不应该去设置缓存,下面来看看如何配置不缓存的内容。
...
server {
listen 80;
server_name cache.lion.club;
# URI 中后缀为 .txt 或 .text 的设置变量值为 "no cache"
if ($request_uri ~ \.(txt|text)$) {
set $cache_name "no cache"
}
location / {
proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,如果没有值则进行缓存
proxy_cache cache_zone; # 设置缓存内存
proxy_cache_valid 200 5m; # 缓存状态为 200的请求,缓存时长为 5 分钟
proxy_cache_key $request_uri; # 缓存文件的 key 为请求的 URI
add_header Nginx-Cache-Status $upstream_cache_status # 把缓存状态设置为头部信息,响应给客户端
proxy_pass http://cache_server; # 代理转发
}
}
客户端(浏览器)访问 https://www.baidu.com 百度网站。
百度服务器返回 HTTPS 使用的 CA 证书。
浏览器验证 CA 证书是否为合法证书。
验证通过,证书合法,生成一串随机数并使用公钥(证书中提供的)进行加密。
发送公钥加密后的随机数给百度服务器。
百度服务器拿到密文,通过私钥进行解密,获取到随机数(公钥加密,私钥解密,反之也可以)。
百度服务器把要发送给浏览器的内容,使用随机数进行加密后传输给浏览器。
此时浏览器可以使用随机数进行解密,获取到服务器的真实传输内容。
关于 HTTPS 更多知识,可以查看作者的另外一篇文章:
https://juejin.cn/post/6844904148601667598#heading-37
配置证书:下载证书的压缩文件,里面有个 Nginx 文件夹,把 xxx.crt 和 xxx.key 文件拷贝到服务器目录,再进行如下配置:
server {
listen 443 ssl http2 default_server; # SSL 访问端口号为 443
server_name lion.club; # 填写绑定证书的域名(我这里是随便写的)
ssl_certificate /etc/nginx/https/lion.club_bundle.crt; # 证书地址
ssl_certificate_key /etc/nginx/https/lion.club.key; # 私钥地址
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 支持ssl协议版本,默认为后三个,主流版本是[TLSv1.2]
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
下面给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:
http://store.company.com/dir2/other.html 同源
https://store.company.com/secure.html 不同源,协议不同
http://store.company.com:81/dir/etc.html 不同源,端口不同
http://news.company.com/dir/other.html 不同源,主机不同
Web 数据层面,同源策略限制了不同源的站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据。
DOM 层面,同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。
网络层面,同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。
前端 server 的域名为:fe.server.com
后端服务的域名为:dev.server.com
现在我们只需要启动一个 Nginx 服务器,将 server_name 设置为 fe.server.com 然后设置相应的 location 以拦截前端需要跨域的请求,最后将请求代理回 dev.server.com。如下面的配置:
server {
listen 80;
server_name fe.server.com;
location / {
proxy_pass dev.server.com;
}
}
⑧配置开启 gzip 压缩
并不是每个浏览器都支持 gzip 的,如何知道客户端是否支持 gzip 呢,请求头中的 Accept-Encoding 来标识对压缩的支持。
启用 gzip 同时需要客户端和服务端的支持,如果客户端支持 gzip 的解析,那么只要服务端能够返回 gzip 的文件就可以启用 gzip 了,我们可以通过 Nginx 的配置来让服务端支持 gzip。下面的 respone 中 content-encoding:gzip,指服务端开启了 gzip 的压缩方式。
在 /etc/nginx/conf.d/ 文件夹中新建配置文件 gzip.conf:
# # 默认 off,是否开启 gzip
gzip on;
# 要采用 gzip 压缩的 MIME 文件类型,其中 text/html 被系统强制启用;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# ---- 以上两个参数开启就可以支持 Gzip 压缩了 ---- #
# 默认 off,该模块启用后,Nginx 首先检查是否存在请求静态文件的 gz 结尾的文件,如果有则直接返回该 .gz 文件内容;
gzip_static on;
# 默认 off,Nginx 做为反向代理时启用,用于设置启用或禁用从代理服务器上收到相应内容 gzip 压缩;
gzip_proxied any;
# 用于在响应消息头中添加 Vary:Accept-Encoding,使代理服务器根据请求头中的 Accept-Encoding 识别是否启用 gzip 压缩;
gzip_vary on;
# gzip 压缩比,压缩级别是 1-9,1 压缩级别最低,9 最高,级别越高压缩率越大,压缩时间越长,建议 4-6;
gzip_comp_level 6;
# 获取多少内存用于缓存压缩结果,16 8k 表示以 8k*16 为单位获得;
gzip_buffers 16 8k;
# 允许压缩的页面最小字节数,页面字节数从 header 头中的 Content-Length 中进行获取。默认值是 0,不管页面多大都压缩。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大;
# gzip_min_length 1k;
# 默认 1.1,启用 gzip 所需的 HTTP 最低版本;
gzip_http_version 1.1;
09
Nginx 架构
多进程结构 Nginx 的进程模型图:
Master Process 用来管理子进程的,其本身并不真正处理用户请求。某个子进程 down 掉的话,它会向 Master 进程发送一条消息,表明自己不可用了,此时 Master 进程会去新起一个子进程。某个配置文件被修改了 Master 进程会去通知 work 进程获取新的配置信息,这也就是我们所说的热部署。
子进程间是通过共享内存的方式进行通信的。
向 master 进程发送 HUP 信号(reload 命令)。
master 进程检查配置语法是否正确。
master 进程打开监听端口。
master 进程使用新的配置文件启动新的 worker 子进程。
master 进程向老的 worker 子进程发送 QUIT 信号。
老的 worker 进程关闭监听句柄,处理完当前连接后关闭进程。
整个过程 Nginx 始终处于平稳运行中,实现了平滑升级,用户无感知。
Nginx 的内部结构是由核心部分和一系列的功能模块所组成。这样划分是为了使得每个模块的功能相对简单,便于开发,同时也便于对系统进行功能扩展。Nginx 的模块是互相独立的,低耦合高内聚。
10
总结
有热门推荐👇
真尼玛秀:「跳过更新」竟然得付费!Docker 新功能引争议!
SQL语句中 left join 后用 on 还是 where,区别大了!
学习+使用Linux的最佳姿势,收录近600条Linux系统命令
点击阅读原文,前往学习SpringCloud实战项目