Nginx是什么?
Nginx (engine x) 是一个高性能的HTTP静态页面服务器,更是一个常用的反向代理服务器,同时还可以作为IMAP/POP3/SMTP代理服务器。
经常使用Nginx服务器,进行一些简单配置,但只是从网上照抄,知其然不知其所以然。
本文,我们主要学习一下nginx的目录结构和基础规则,补一补nginx基础。
安装Nginx
linux中安装nginx,参考文档《CentOS7设置Nginx开机自启动》
docker安装nginx,参考文档《使用Docker安装配置Nginx》
目录结构
因为nginx目录是可以指定的,所以真实使用的目录结构请以命令查看。
1 | ps aux | grep nginx |
程序目录
可能的程序目录:
1 | /usr/sbin/nginx |
配置目录
可能的默认配置目录:
1 | /etc/nginx/ |
nginx.conf一般放在这两个目录中,nginx.conf中会写清楚子配置目录,比如:
1 | http { |
那么,子配置文件就放在 /etc/nginx/conf.d/ 目录中,并且子配置文件必须以 .conf 结尾。一般情况下,我们比较少修改 nginx.conf,大部分时候都是修改子配置文件。
根目录
可能的默认根目录:
1 | /usr/share/nginx/html |
根目录下一般会有nginx自带的index.html和50x.html。
curl ${nginx_server}
时看到内容,就是index.html文件中的内容。
我们自己的静态页面项目,最好不要放到默认根目录下,因为默认根目录可以通过ip和路径访问到,这往往是不符合预期的。
推荐的静态页面项目目录为:/usr/share/nginx/work
日志目录
可能的默认日志目录:
1 | /var/log/nginx |
日志文件中一般有两个日志文件,error.log和access.log。
常用命令
测试配置
1 | nginx -t |
重新加载配置
1 | nginx -s reload |
重启nginx
1 | systemctl restart nginx |
常见配置
静态页面服务器配置
1 | server { |
这个配置,是一个标准的静态页面服务器配置。
使用以上配置,如果已经配置好了域名解析,那么访问 www.voidking.com 时,就会看到nginx首页,也就是 index.html。
反向代理到其他域名
1 | server { |
使用以上配置,访问 www.voidking.com 时,实际上看到的是 voidking.coding.me 这个域名返回的内容。
反向代理到一个服务
1 | server { |
使用以上配置,访问 www.voidking.com 时,实际上看到的是 192.168.56.101:8080 这个服务返回的内容。
反向代理到upstream
1 | upstream www_voidking_com{ |
使用以上配置,访问 www.voidking.com 时,实际上看到的是upstream里的服务返回的内容。
但是问题来了,upstream里有三个服务,到底是哪个服务返回的内容呢?答:不一定,这就要用到传说中的加权轮询算法了。
三个服务的权值分别为 5、2、1(默认),从权值来看,最大可能打到第一个服务。
有没有想到什么知识点?没错,负载均衡,使用了加权轮询算法的负载均衡。
反向代理到websocket服务
1 | http { |
更多内容参考一篇带给你Nginx代理WebSocket方法和NGINX as a WebSocket Proxy
配置域名证书
1 | server { |
四层代理
nginx四层代理依赖ngx_stream_core_module
模块(nginx参数为--with-stream
),在nginx1.22.0以上版本已经默认支持并开启ngx_stream_core_module
模块。
1 | nginx -V |
如果是低版本的nginx,需要自行编译并开启ngx_stream_core_module
模块。
nginx.conf中加载ngx_stream_module.so
1 | #load_module /usr/lib/nginx/modules/ngx_stream_module.so; |
新版本默认加载,一般配置路径为:/usr/share/nginx/modules/
一个四层代理的实例:
1 | stream { |
注意:stream是和http同一级的,不要配置到nginx/conf.d目录中。最好新建一个nginx/stream.d目录,专门放置四层代理配置。
请求body大小
1 | Syntax: client_max_body_size size; |
Sets the maximum allowed size of the client request body. If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client. Please be aware that browsers cannot correctly display this error. Setting size to 0 disables checking of client request body size.
参考文档ngx_http_core_module - client_max_body_size
配置文件优先级
conf.d中的配置文件,是按照名称顺序有优先级的,第一个匹配到的配置文件会作为default。
如果一个域名指向了nginx,但是nginx中没有这个域名的配置,那么就会走default配置。
详情参考《使用Docker安装配置Nginx》文中的【重定向问题排查】一节。
基础规则
location规则
在常见配置中,我们看到了一个叫 location 的关键字。location规则为:
1 | location [ = | ~ | ~* | ^~ ] /uri/ { ... } |
紧跟在location后面的,是可选的修饰符,uri是要匹配的字符串。
常见匹配:
location = /uri
精确匹配location ^~ /uri
前缀匹配,在正则匹配之前location ~ pattern
正则匹配,区分大小写location ~* pattern
正则匹配,不区分大小写location /uri
前缀匹配,在正则匹配之后location /
通用匹配,未匹配到其它location的请求会匹配到它
详情参考location 匹配规则
匹配规则
匹配过程:
1、精确匹配
2、前缀匹配(^~
)
3、正则匹配(按配置顺序)
4、前缀匹配(/xxx
)
5、通用匹配
其中前缀匹配如果有包含关系时,遵循最大匹配原则。
proxy_pass规则
如果nginx作为反向代理使用,那么必须要搞明白的就是proxy_pass的规则,这关系到请求能否打到正确的接口。
proxy_pass规则:
- 如果proxy_pass后面没有路径,那么转发时带上uri
- 如果proxy_pass后面有路径,那么转发时使用该路径替换匹配到的uri
保留uri
1 | location /test { |
访问 www.voidking.com/test/index 会被代理到 http://192.168.56.101:8080/test/index 这个url,/test/index
被保留转发给了后端服务。
去掉uri
1 | location /test { |
访问 www.voidking.com/test/index 会被代理到 http://192.168.56.101:8080/index 这个url,/test
被去掉了。
替换uri
1 | location /test { |
访问 www.voidking.com/test/index 会被代理到 http://192.168.56.101:8080/qa/index 这个url,/test/index
被替换成了 /qa/index
,然后转发给了后端服务。
1 | location /test { |
访问 www.voidking.com/test/index 会被代理到 http://192.168.56.101:8080/qaindex 这个url,/test/index
被替换成了 /qaindex
,然后转发给了后端服务。
配置日志格式
1 | http { |
字段 | 含义 | 示例 |
---|---|---|
body_bytes_sent | 响应body字节数 | 3650 |
bytes_sent | 响应总字节数 | 175 |
host | IP或域名(不包括端口) | 10.10.10.14 |
http_host | IP或域名(包括端口) | 10.10.10.14:81 |
http_referer | referer信息 | http://10.10.10.14/ |
http_user_agent | UA信息 | Mozilla/5.0 |
http_x_forwarded_for | XFF信息 | 192.168.1.1 |
remote_addr | 客户端地址 | 10.10.10.1 |
remote_user | 客户端认证用户名 | admin |
request | 请求URI和协议 | GET |
request_body | 请求的body | |
request_length | 请求长度 | 571 |
request_method | 请求方法 | GET |
request_time | 请求处理时间 | 0.000 |
response_body | 返回的body,依赖lua,需要编写lua脚本来采集 | |
response_header_data | 响应头数据,依赖headers-more-nginx-module | |
schema | 协议 | http |
server_name | 虚拟主机名称 | |
server_port | 服务器端口 | |
server_protocol | 服务器协议 | |
ssl_cipher | 交换数据中的算法 | |
ssl_protocol | SSL协议版本 | |
status | 返回状态码 | 404 |
time_local | 时间戳 | 16/Jun/2019:23:29:50 |
upstream_addr | 后端提供服务地址 | |
upstream_connect_time | 与服务器连接所花费的时间 | |
upstream_response_time | 后端处理时间 | |
upstream_status | upstream状态 | 200 |
参考文档:
修改日志格式后,需要重启nginx,然后查看日志确认格式
1 | tail -f /opt/nginx/log/access.log |
map指令
map 的作用是创建自定义变量。
语法:
1 | map $var1 $var2 |
map 的var1为源变量,通常是nginx的内置变量,var2 是自定义变量。 var2 的值取决于 var1 在对应表达式的匹配情况。如果一个都匹配不到则 var2 就是 default 对应的值。
例子:
1 | map $args $foo { |
args 是nginx内置变量,就是获取的请求 url 的参数。 如果 args 匹配到 debug 那么 foo 的值会被设为 1 ,如果 args 一个都匹配不到 foo 就是 default 定义的值,在这里就是 0
参考文档Nginx map 使用详解
rewrite指令
rewrite指令的作用是重定向。
语法:
1 | rewrite regex replacement [flag]; |
- rewrite:该指令是实现URL重写的指令。
- regex:用于匹配URI的正则表达式。
- replacement:将regex正则匹配到的内容替换成 replacement。
- flag: flag标记。
flag有如下值:
- last: 本条规则匹配完成后,继续向下匹配新的location URI 规则。(不常用)
- break: 本条规则匹配完成即终止,不再匹配后面的任何规则(不常用)。
- redirect: 返回302临时重定向,浏览器地址会显示跳转新的URL地址。
- permanent: 返回301永久重定向。浏览器地址会显示跳转新的URL地址。
例子:
1 | rewrite ^/(.*) http://www.baidu.com/$1 permanent; |
- rewrite 是固定关键字,表示开始进行rewrite匹配规则。
- regex 是
^/(.*)
,这是一个正则表达式,匹配完整的域名和后面的路径地址。 - replacement 是
http://www.baidu.com/$1
,其中$1
是取regex部分()里面的内容,如果匹配成功后跳转到的URL - flag 是 permanent,代表永久重定向的含义,即跳转到
http://www.baidu.com/$1
状态码
- 1xx:信息响应类,表示接收到请求并且继续处理
- 2xx:处理成功响应类,表示动作被成功接收、理解和接受
- 3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
- 4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
- 5xx:服务端错误,服务器不能正确执行一个正确的请求
详情参考HTTP 状态码详解与选用