以最常用的 CentOS 上的使用为例,相对完整的介绍 Nginx 在日常工作中的作用,包括基础的使用、指令的概念和作用以及工作中的一些运用场景等
# CentOS
sudo yum install nginx
# MacOS
brew install nginx
# Start: nginx start
sudo systemctl start nginx
# Stop: nginx stop
sudo systemctl stop nginx
# Reload conf: nginx -s reload
sudo systemctl reload nginx
nginx.conf 配置文件一般在不同的操作系统上会存放在特定的位置
CentOS:
/etc/nginx/nginx.conf
MacOS:
/usr/local/etc/nginx/nginx.conf
Nginx 的运行日志存放位置通常取决于 Nginx 的配置文件中指定的日志路径。在默认情况下,Nginx 的主配置文件中会指定默认的日志路径,一般是在 Nginx 安装目录下的 logs
目录中
通常情况下,Nginx 的主日志文件是 error.log
和 access.log
,分别记录 Nginx 的错误日志和访问日志
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
通过 nginx.conf
文件进行配置 Nginx 服务器的行为,主要由指令和块组成
指令和块通常位于特定的上下文中,例如 http
、server
、location
等上下文中,决定了指令的作用范围
注意:
Nginx 的配置具有继承和覆盖的特性,子块可以继承父块的指令,也可以覆盖父块的指令
指令可以被包含在一个块中,一个块以 {}
包围,用于分组相关指令。例如:
server {
listen 80;
server_name example.com;
}
Nginx 中常见的块:
http 块是 Nginx 配置文件中的最外层块,用于配置全局的 HTTP 参数和 HTTP 服务器
server
块是 http
块内的子块,用于定义虚拟主机(Virtual Host)。每个 server 块对应一个虚拟主机,用于处理客户端的请求
location
块是 server
块内的子块,用于匹配请求的 URI,并设置对应的处理规则。location 块可以根据请求的 URI 进行匹配,并定义不同的处理逻辑
upstream 块用于定义一组后端服务器的集群。通常用于负载均衡和反向代理等场景
if
块是用于条件判断的块,可以根据条件执行不同的指令
Nginx 配置文件由一系列指令组成,每个指令都控制着 Nginx 服务器的行为。指令由名称和参数组成,参数可以是字符串、数字、变量等。例如:listen 80;
、root /var/www/html;
用于定义虚拟主机(Virtual Host),即服务器监听的 IP 地址和端口号,以及与该虚拟主机相关的配置。一个 Nginx 配置文件可以包含多个 server
块,每个块定义一个虚拟主机
用于定义 Nginx 服务器中的不同 URL 路径的配置。每个 location
块可以包含一组指令,用于指定该路径下的行为,例如代理、重定向、缓存等
server
块下的多个 location
指令的执行顺序是根据匹配规则来确定的。Nginx 会按照配置文件中 location
指令的顺序逐个匹配请求的 URI,并执行第一个匹配成功的 location
块中的指令,一旦 Nginx 匹配到了一个 location
块,就会停止继续查找其他 location
块。如果没有匹配成功的 location
块,则会执行 server
块中的默认指令
通常情况下,Nginx 会按照以下几个规则来确定 location 块的匹配顺序:
a) 精确匹配(Exact Match):Nginx 会优先匹配 URI 与 location
指令中的 URI 完全相同的 location
块
location / {
# 匹配根目录
}
location /example {
# 匹配/example路径
}
b) 最长前缀匹配(Longest Prefix Match):如果没有精确匹配的 location
块,则 Nginx 会选择 URI 最长前缀与 location 指令中的 URI 匹配的 location 块
location / {
# 匹配根目录
}
location /example {
# 匹配/example路径
}
location /example/foo {
# 匹配/example/foo路径
}
c) 正则表达式匹配(Regular Expression Match):如果没有精确匹配或最长前缀匹配的 location 块,则 Nginx 会尝试与使用正则表达式定义的 location 块中的 URI 匹配
location ~* \.(jpg|jpeg|png|gif)$ {
# 匹配图片文件
}
location ~* \.php$ {
# 匹配PHP文件
}
用于指定 Nginx 服务器监听的 IP 地址和端口号
用于指定 Nginx 服务器提供静态文件服务时的根目录
用于设置 Nginx 作为反向代理时转发请求到后端服务器的地址
用于对请求的 URI 进行重写,可以用来实现 URL 重定向等功能
分别用于设置访问日志和错误日志的文件路径和格式
用于将其他配置文件包含到当前配置文件中,可以使配置文件更加模块化和易于管理
用于配置 SSL 证书和私钥,启用 HTTPS 协议
分别用于配置请求速率限制和连接数限制,用于保护服务器免受 DDoS 攻击等
在 Nginx 配置中,有许多内置变量和模块提供的变量可以用于控制和定制服务器行为。以下是一些常见的 Nginx 配置变量:
内置变量:
$is_args
:如果请求中包含查询参数,则 $is_args 的值为 ?;如果请求中不包含查询参数,则为一个空字符串,用于检查
求中是否包含查询参数。它通常用于在配置中执行条件判断
$args
:请求中的查询参数部分
$uri
:不带查询参数的请求 URI
$request_uri
:完整的原始请求 URI,包括查询参数
$request_method
:HTTP 请求方法,比如 GET、POST 等
$remote_addr
:客户端的 IP 地址
$http_user_agent
:客户端的用户代理字符串
$server_name
:当前请求的主机名
$scheme
:请求的协议,通常是 http 或 https
$http_referer
:请求来源页面的 URL
$http_cookie
:请求中的 Cookie
其他模块提供的变量:
$request_body
:请求主体的内容
$request_time
:请求处理时间,以秒为单位
$http_<header>
:HTTP 请求头中的任意一个头部字段,例如$http_user_agent
$arg\_<param>
:获取请求中指定查询参数的值,例如$arg_id 可以获取 id 参数的值
做为一款 Web 服务器,和开发场景联系最紧密的就是使用 Nginx 作为反向代理服务器和负载均衡器等使用场景,除此之外还有一些其他应用:
作为静态文件服务器提供前端站点资源 HTML、JS、CSS 的访问,如本站点的博客直接通过启动一个 Nginx server 来实现站点资源的访问
转发客户端的请求,反向代理可以隐藏服务器真实 IP
通过本地客户端启动一个 Ng server 来转发接口的请求解决本地跨域问题也是很容易的(webpack dev server 的 proxy middleware 就是这个原理)这个就属于正向代理的范畴了
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
上面的配置使用了 IP 哈希算法,根据客户端 IP 地址将请求分发给后端服务器,以保证同一客户端的请求始终被分发到同一后端服务器
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
http {
# 定义缓存路径和名称
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;
# 配置其他缓存参数
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 301 302 304 5m;
proxy_cache_valid any 1m;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_server;
proxy_cache my_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 301 302 304 5m;
proxy_cache_valid any 1m;
}
}
location / {
proxy_cache_bypass $http_cache_control;
proxy_no_cache $http_pragma $http_authorization;
}
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge my_cache $1$is_args$args;
}
Nginx 1.9.5 版本+,HTTP/2 必须与 SSL/TLS 一起使用
server {
listen 443 ssl http2; # 启用了 HTTP/2
server_name example.com;
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
# 其他 SSL/TLS 相关配置
location / {
# 其他配置
}
}
limit_req
模块,用于限制请求的速率。可以在 Nginx 的配置文件中配置 limit_req_zone
来定义一个共享内存区域,然后在 server
或 location
块中使用 limit_req
指令来设置请求的速率限制limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/s;
server {
location / {
limit_req zone=limit_zone burst=20;
# 其他配置
}
}
上面的配置将限制每秒接受来自同一 IP 地址的请求不超过 10 个,超过限制的请求将会被延迟处理或者拒绝
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
location / {
limit_conn addr 10;
# 其他配置
}
}
这个配置将限制来自同一 IP 地址的并发连接数不超过 10 个
配置访问频率限制: 可以使用第三方模块,如 ngx_http_limit_req_module、ngx_http_limit_req_module 等,来实现更加灵活和细粒度的访问频率限制
使用防火墙和安全组: 除了 Nginx 本身的配置,还可以使用防火墙和安全组来限制访问。通过配置防火墙规则,可以在网络层面对恶意请求进行阻止或过滤
ngx_http_healthcheck_module
:这是一个常用的第三方 Nginx 模块,可以实现对后端服务器的健康检查。通过配置 Nginx 来定期发送健康检查请求到后端服务器,根据返回的状态码或响应内容来判断后端服务器的健康状态
a) 健康检查脚本:编写一个简单的脚本,定期检查后端服务器的健康状态,并根据检查结果向 Nginx 发送相应的信号。Nginx 可以根据接收到的信号来启用或禁用特定的后端服务器
#!/bin/bash
# 后端服务器的 IP 地址和端口
SERVER="backend.example.com:8080"
# 检查后端服务器的响应状态
check_status() {
if curl -s --head $SERVER | head -n 1 | grep "200 OK" > /dev/null; then
echo "Server $SERVER is UP"
return 0
else
echo "Server $SERVER is DOWN"
return 1
fi
}
# 检查后端服务器状态并发送信号给 NGINX
check_status_and_signal_nginx() {
if check_status; then
# 向 NGINX 发送启用后端服务器的信号
else
# 向 NGINX 发送禁用后端服务器的信号
fi
}
# 每隔 60 秒检查一次
while true; do
check_status_and_signal_nginx
sleep 60
done
b) 监控工具:使用监控工具(如 Prometheus)来监控后端服务器的健康状态,并将监控结果反馈给 Nginx。Nginx 可以根据监控数据来动态调整后端服务器的负载均衡策略
如配置 Nginx Exporter 部署和使用 Prometheus 配合 Grafana 进行看板的可视化直观的观察 Nginx 的健康状态