Nginx相关概念
简单请求与非简单请求
请求方法是HEAD、GET、POST三种之一,并且HTTP头信息限于Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(限于application/x-www-form-urlencoded、multipart/form-data、text/plain)即为简单请求,其余皆为非简单请求。简单请求与非简单请求区别体现在服务器对请求响应的预处理以及请求信息设置还有返回信息的处理上,不详细表述,可自行查阅相关文档。跨域
开发几乎都知道,不详细表述1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//同源的例子
http://example.com/app1/index.html //只是路径不同
http://example.com/app2/index.html
http://Example.com:80 //只是大小写差异
http://example.com
//不同源的例子
http://example.com/app1 //协议不同
https://example.com/app2
http://example.com //host 不同
http://www.example.com
http://myapp.example.com
http://example.com //端口不同
http://example.com:8080正向代理与反向代理
正向代理:客户端->代理服务器->目标服务器,客户端向代理服务器发送请求指定目标服务器,由代理服务器与目标服务器进行数据交换,再又代理服务器将数据返回给客户端。理解:翻墙工具
反向代理:客户端->代理服务器->服务器集群,客户端发送请求给代理服务器,代理服务器将请求再分发给服务器集群,具体哪个服务器处理信息不知道,使得真实处理的服务器对客户端不可见。理解:商店买东西,明确买什么商品,商店采购,商店扮演的就是反向服务器角色。负载均衡
请求并发不多的情况下,服务器能够正常响应所有的请求,网络响应快速。当并发量上来了之后,单一的服务器不能同时处理太多的请求。此时只能将服务器性能提高。或者采用负载均衡的做法,简单理解就是,使用多台服务器形成一个服务器集群,当大规模的请求来临的时候,由Nginx充当协调员角色,将请求分发到不同的服务器去处理并返回响应。动静分离
将服务器上的静态资源与动态资源分离。根据不同的请求类型请求对应的资源,还可以利用nginx缓存的优势更快的响应资源请求。
Nginx操作常用命令
1 | nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启 |
Nginx配置
主配置文件/etc/nginx/nginx.conf
nginx.config结构图:
1
2
3
4
5
6
7
8
9
10
11main # 全局配置,对全局生效
├── events # 配置影响 Nginx 服务器或与用户的网络连接
├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置
│ ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分
│ ├── server # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块
│ ├── server
│ │ ├── location # server 块可以包含多个 location 块,location 指令用于匹配 uri
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...配置实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45user nginx; # 运行用户,默认即是nginx,可以不进行设置
worker_processes 1; # Nginx 进程数,一般设置为和 CPU 核数一样
error_log /var/log/nginx/error.log warn; # Nginx 的错误日志存放目录
pid /var/run/nginx.pid; # Nginx 服务启动时的 pid 存放位置
events {
use epoll; # 使用epoll的I/O模型(如果你不知道Nginx该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
worker_connections 1024; # 每个进程允许最大并发数
}
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 {
listen 80; # 配置监听的端口
server_name localhost; # 配置的域名
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; # 同上
}
}全局变量
变量名 作用 $host 请求信息中的 Host,如果请求中没有 Host 行,则等于设置的服务器名,不包含端口 $request_method 客户端请求类型,如 GET、POST $remote_addr 客户端的 IP 地址 $args 请求参数 $arg_PARAMETER GET 请求中变量名 PARAMETER 参数的值,例如:$http_user_agent(Uaer-Agent 值)… $content_length 请求头中的 Content-length 字段 $http_user_agent 客户端agent信息 $http_cookie 客户端cookie信息 $remote_addr 客户端的IP地址 $remote_port 客户端端口 $http_user_agent 客户端agent信息 $server_protocol 请求使用的协议,如 HTTP/1.0、HTTP/1.1 $server_addr 服务器地址 $server_name 服务器名称 $server_port 服务器端口号 $scheme HTTP 方法(如http,https) … … 反向代理配置
- 简单配置,例如前端api接口请求转发
1
2
3
4
5
6
7
8server{
listen 80;
server_name localhost;
location /api {
proxy_pass http://www.xxx.com;
}
} - 请求转发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15server{
listen 80;
server_name localhost;
// 把访问 http://127.0.0.1:9001/edu 的请求转发到 http://127.0.0.1:8080
// 把访问 http://127.0.0.1:9001/vod 的请求转发到 http://127.0.0.1:8081
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
}
- 简单配置,例如前端api接口请求转发
跨域配置
- 反向代理处理跨域问题以上配置会将a.abc.com的请求全部代理到b.abc.com,通常情况下不需要代理全部的请求,所以可以使用请求的后缀来区分静态资源与动态资源的区分。
1
2
3
4
5
6
7
8
9
10server {
listen 9001;
server_name a.abc.com;
// 假设a、b都是服务器的二级域名,指向的ip都一样但是二级域名间请求仍然会跨域
location / {
proxy_pass b.abc.com;
}
}1
2
3
4
5
6
7
8
9# 请求跨域,约定代理后端服务请求path以/apis/开头
location ^~/api/ {
# 这里重写了请求,将正则匹配中的第一个分组的path拼接到真正的请求后面,并用break停止后续匹配
rewrite ^/apis/(.*)$ /$1 break;
proxy_pass b.abc.com;
# 两个域名之间cookie的传递与回写
proxy_cookie_domain a.abc.com b.abc.com;
} - 设置请求头处理跨域问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# /etc/nginx/conf.d/b.conf
server {
listen 80;
server_name b.abc.com;
add_header 'Access-Control-Allow-Origin' $http_origin; # 全局变量获得当前请求origin,带cookie的请求不支持*
add_header 'Access-Control-Allow-Credentials' 'true'; # 为 true 可带上 cookie
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # 允许请求方法
add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; # 允许请求的 header,可以为 *
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000; # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204; # 200 也可以
}
location / {
root /usr/share/nginx/html/b;
index index.html;
}
}
- 反向代理处理跨域问题
开启gzip
nginx配置gzip需要配合前端工程打包成gzip模式才能正常使用。例如vite中使用vite-plugin-compression插件打包资源文件,配置参考1
2
3
4
5
6
7
8
9
10# /etc/nginx/conf.d/gzip.conf
gzip on; # 默认off,是否开启gzip
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; # 采用gzip压缩的MIME文件类型
gzip_static on; # 默认 off,该模块启用后,Nginx 首先检查是否存在请求静态文件的 gz 结尾的文件,如果有则直接返回该 .gz 文件内容
gzip_proxied any; # 默认 off,nginx做为反向代理时启用,用于设置启用或禁用从代理服务器上收到相应内容 gzip 压缩
gzip_vary on; # 用于在响应消息头中添加 Vary:Accept-Encoding,使代理服务器根据请求头中的 Accept-Encoding 识别是否启用 gzip 压缩
gzip_comp_level 6; # gzip 压缩比,压缩级别是 1-9,1 压缩级别最低,9 最高,级别越高压缩率越大,压缩时间越长,建议 4-6
gzip_buffers 16 8k; # 获取多少内存用于缓存压缩结果,16 8k 表示以 8k*16 为单位获得
gzip_min_length 1k; # 设置最低压缩文件大小
gzip_http_version 1.1; # 默认 1.1,启用 gzip 所需的 HTTP 最低版本负载均衡
nginx配置负载均衡有几种分配方式- 轮询,默认方式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务挂了,能自动剔除;
- weight,权重分配,指定轮询几率,权重越高,在被访问的概率越大,用于后端服务器性能不均的情况;
- ip_hash,每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决动态网页 session 共享问题。负载均衡每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的;
- fair(第三方),按后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件 nginx-upstream-fair,需要先安装;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16http {
upstream myserver {
# ip_hash; # ip_hash 方式
# fair; # fair 方式
server 127.0.0.1:8081; # 负载均衡目的服务地址
server 127.0.0.1:8080;
server 127.0.0.1:8082 weight=10; # weight 方式,不写默认为 1
}
server {
location / {
proxy_pass http://myserver;
proxy_connect_timeout 10;
}
}
}
配置动静分离
通过请求后缀名匹配不同资源请求方式实现动静分离,另外可以给静态资源文件设置expires设置缓存时间,从而减少客户端请求的时间。1
2
3
4
5
6
7
8
9
10
11
12
13server {
location / {
root /dist/;
index index.html index.htm;
}
location /image {
root /dist/images;
autoindex on; # 开启静态资源列目录
autoindex_exact_size off; # on(默认)显示文件的确切大小,单位是byte;off显示文件大概大小,单位KB、MB、GB
autoindex_localtime off; # off(默认)时显示的文件时间为GMT时间;on显示的文件时间为服务器时间
}
}移动端pc端适配
1
2
3
4
5
6
7
8
9
10
11
12
13# /etc/nginx/conf.d/a.abc.com.conf
server {
listen 80;
server_name a.abc.com;
location / {
root /usr/share/nginx/html/pc;
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
root /usr/share/nginx/html/mobile;
}
index index.html;
}
}图片防盗链
1
2
3
4
5
6
7
8
9
10
11
12server {
listen 80;
server_name xxx;
# 图片防盗链
location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
valid_referers none blocked server_names ~\.google\. ~\.baidu\. *.qq.com; # 只允许本机 IP 外链引用
if ($invalid_referer){
return 403;
}
}
}配置图片,字体等静态文件缓存
1
2
3
4
5
6
7# 图片缓存时间设置
location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ {
expires 10d;
}
# 如果不希望缓存
expires -1;
以上只涉及到nginx部分常用配置,掌握了这些基本上就能cover住nginx操作,因为平时仅负责前端开发部分的工作,服务器方面实践比较少,仅以此文记录一下方便以后参考。