Nginx是什么

Nginx是一个高性能的 HTTP 和反向代理服务器,特点是占用内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。

Nginx 专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告 Nginx 能支持高达 50000 个并发连接数

Nginx的功能

  • 正向代理

    正向代理:局域网中的电脑用户想要直接访问网络是不可行的,只能通过代理服务器来访问,这种代理服务就被称为正向代理。

  • 反向代理

    反向代理:客户端无法感知代理,因为客户端访问网络不需要配置,只要把请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据,然后再返回到客户端。

    客户端通过Nginx来透明的调用后台服务器,Nginx来选择具体的Worker

  • 负载均衡

    当Nginx反向代理了多个同类型实例的时候,选择一个可以最大化并发量或者效率的服务器调用方式,来将请求路由到对应的Worker上,就是负载均衡

  • 动静分离

    根据用户请求的区别,将动态页面和静态页面的处理交给不同的服务器,加快解析的速度,降低单个服务器路由的压力。

  • 高可用

Nginx 的配置文件

user  nginx; # 定义 Nginx 运行的用户和用户组。
worker_processes auto; # 指定 worker 进程的数量,通常设置为 CPU 核心数

error_log /var/log/nginx/error.log warn; # 定义全局错误日志文件的位置和级别。
pid /var/run/nginx.pid; # 设置存储 Nginx 进程 ID 的文件路径。

events { # events 块: 影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 workprocess 下的网络连接进行序列化,是否允许同时接收多个网络连接等等。
worker_connections 1024; # 支持的最大连接数
}

http { # HTTP 配置块(HTTP block):控制 HTTP 服务的全局设置。诸如反向代理和负载均衡都在此配置
include /etc/nginx/mime.types; # include:引入其他配置文件,如虚拟主机配置。
default_type application/octet-stream; # default_type:设置默认的 MIME 类型。

log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # log_format:自定义日志格式
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on; # sendfile:启用或禁用 sendfile() 系统调用以优化传输性能。是否启用 零拷贝
tcp_nopush on;

keepalive_timeout 65; # keepalive_timeout:设置长连接的超时时间。

gzip on; # 启用 gzip 压缩来减少传输内容的大小。
gzip_types text/css application/javascript;

include /etc/nginx/conf.d/*.conf;

server { # Server 块用于配置虚拟主机,每个 Server 块表示一个独立的站点。通常,Server 块包含域名绑定、监听端口等。
listen 80 default_server; # listen:指定监听的端口。
listen [::]:80 default_server;
server_name _; # server_name:指定处理的域名。相同的IP和端口和用来代理不同的服务,就是根据域名做的区分
root /usr/share/nginx/html; # root:定义站点的根目录。

# SSL/TLS 配置 为站点启用 HTTPS 支持。
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;

index index.html index.htm; # index:指定默认访问的文件。

access_log /var/log/nginx/example_access.log; # access_log 和 error_log:指定访问日志和错误日志的路径。
error_log /var/log/nginx/example_error.log;

# Load configuration files for the default server block.
include /etc/nginx/conf.d/*.conf;

# 通过 upstream 块定义后端服务器的集合(即一组服务器),然后通过 proxy_pass 指令将客户端请求转发到这些服务器。
upstream backend_servers {
# 负载均衡算法

# 轮询(Round Robin)(默认算法) 轮询是 Nginx 的默认算法,轮流将请求分配给每个服务器。
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;

# 最少连接数(Least Connections) 最少连接算法将请求分配给当前连接最少的服务器,适合于请求处理时间差异较大的场景。
least_conn;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;

# IP 哈希(IP Hash) IP Hash 算法基于客户端 IP 地址的哈希值,将相同 IP 地址的请求始终分配到同一台服务器。它适合于会话保持(如状态性会话)场景。
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;

# 加权轮询(Weighted Round Robin) 通过为每个服务器分配权重,可以让负载更高的服务器处理更多的请求。权重越高,分配的请求越多。
server backend1.example.com weight=3;
server backend2.example.com weight=1;
server backend3.example.com weight=1;

# 健康检查: Nginx 支持对后端服务器进行健康检查,可以自动将健康状况不佳的服务器从负载均衡池中剔除,以保证请求只会发往正常运行的服务器。
# max_fails:指定服务器在被临时标记为不可用之前,允许失败的最大次数。
# fail_timeout:指定在 fail_timeout 时间内失败的次数达到 max_fails 后,服务器会被标记为不可用,并且在该时间内不会再向其发送请求
server backend1.example.com max_fails=3 fail_timeout=30s;
server backend2.example.com;
server backend3.example.com;

# 在某些应用中(如带有用户登录的应用),需要确保同一用户的请求总是分发到同一个服务器(会话保持)。可以使用第三方模块如 nginx-sticky-module 实现。
sticky;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;

}

# Location 块用于匹配 URL 路径,并针对不同路径设置不同的处理规则。

# location:匹配请求的路径,可以使用正则表达式或普通路径匹配。
location / {
try_files $uri $uri/ =404;
}
location /images/ {
root /data;
}
# proxy_pass:配置反向代理,转发请求到其他服务器。
location /api/ {
proxy_pass http://backend_server;
# 传递客户端的真实 IP
proxy_set_header X-Real-IP $remote_addr;

# 传递 X-Forwarded-For 头信息(包含客户端和之前代理服务器的 IP)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 传递原始主机名
proxy_set_header Host $host;

# 传递客户端使用的协议(http 或 https)
proxy_set_header X-Forwarded-Proto $scheme;

# 超时设置 在负载均衡的过程中,可以设置连接超时和响应超时,防止后端服务器响应过慢或无法响应的问题:
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;

}

# rewrite:重写 URL。
location /rewrite/ {
rewrite ^/old/(.*)$ /new/$1 permanent;
}

#
error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

# 缓存设置 可以在 Nginx 服务器端启用缓存,以减轻后端服务器的压力:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

server {
location / {
proxy_cache my_cache;
proxy_pass http://backend_servers;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
}
}

# 限流配置 Nginx 可以对进入的请求进行限流,防止流量过载:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

server {
location /api/ {
limit_req zone=one burst=5 nodelay;
proxy_pass http://backend_servers;
}
}

}


Nginx自带的变量

变量名称 描述
$remote_addr 客户端的 IP 地址。
$remote_port 客户端的端口号。
$remote_user 客户端的用户名(如果 HTTP 基本认证通过)。
$http_user_agent 客户端请求中的 User-Agent
$http_cookie 客户端请求中的 Cookie 值。
$server_addr 服务器的 IP 地址。
$server_name 请求中匹配的 server_name
$server_port 服务器的端口号。
$hostname Nginx 服务器的主机名。
$request_uri 完整的原始请求 URI,包含查询字符串。
$uri 去掉查询字符串的 URI,可以被内部重定向修改。
$document_uri $uri 相同,不能被内部重定向修改。
$document_root 请求的根目录,通常由 rootalias 指定。
$realpath_root 文件系统中真实的路径,解析符号链接后的值。
$query_string 请求 URL 中的查询字符串部分。
$args $query_string 相同。
$request_method 请求方法(如 GETPOST 等)。
$scheme 请求使用的协议(httphttps)。
$is_args 如果有查询字符串则为 ?,否则为空字符串。
$request 请求行的完整内容,如 GET /index.html HTTP/1.1
$request_length 请求的总大小,包括请求行、头部和请求体。
**$http_* ** 代表客户端请求中的任意 HTTP 头部,如 $http_host$http_referer
$proxy_add_x_forwarded_for 客户端的 IP 和 X-Forwarded-For 头的组合。
$proxy_host 代理服务器的主机名。
$proxy_port 代理服务器的端口号。
$upstream_addr 实际处理请求的上游服务器的地址。
$upstream_response_time 上游服务器的响应时间。
$status HTTP 响应的状态码。
$bytes_sent 发送给客户端的总字节数。
$body_bytes_sent 响应体的字节数,不包括头部。
**$sent_http_* ** 响应中的 HTTP 头部,如 $sent_http_content_type
$connection 当前连接的序列号。
$connection_requests 当前连接处理的请求数。
$nginx_version Nginx 的版本号。
$request_filename 当前请求对应的文件路径。
$document_root 当前请求的根目录路径。
$realpath_root 解析符号链接后的实际根目录路径。
$time_local 本地时间,格式如 04/Jul/2024:15:45:10 +0800
$time_iso8601 ISO 8601 格式的时间,如 2024-07-04T15:45:10+08:00
$ssl_protocol SSL/TLS 协议版本。
$ssl_cipher SSL/TLS 使用的加密算法。
$ssl_client_cert 客户端证书的完整内容(PEM 编码)。
$ssl_client_fingerprint 客户端证书的 SHA1 指纹。
$limit_rate 限制传输速率,单位为字节/秒。
$pid Nginx 进程的 PID。

Location与正则

location[ = | ~ | ~* | ^~] url{}

location 指令说明,该语法用来匹配 url,语法如上:

  • =:用于不含正则表达式的 url 前,要求字符串与 url 严格匹配,匹配成功就停止向下搜索并处理请求。
  • ~:用于表示 url 包含正则表达式,并且区分大小写。
  • **~*:**用于表示 url 包含正则表达式,并且不区分大小写。
  • ^~:用于不含正则表达式的 url 前,要求 Nginx 服务器找到表示 url 和字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再匹配。
  • 如果有 url 包含正则表达式,不需要有 ~ 开头标识。

Nginx的高可用

Nginx 高可用的核心要素

  1. 负载均衡:将流量分发到多个后端服务器,从而避免单个服务器的瓶颈或宕机影响整体系统的可用性。
  2. 故障转移(Failover):当一台服务器不可用时,流量自动转移到另一台健康的服务器,确保服务不中断。
  3. 无状态架构:通过会话保持、共享存储等技术,确保服务的可扩展性和高可用性。
  4. 集群化部署:多个 Nginx 实例协同工作,提高冗余和容错能力。

Nginx 高可用的实现方式

  1. 使用 Keepalived 实现主备切换(Master-Slave Failover)

Keepalived 是一个常用于实现高可用性服务的工具。它通过虚拟 IP(VIP)的方式实现主备 Nginx 节点之间的自动切换。当主 Nginx 宕机时,备份节点会自动接管 VIP 并继续提供服务。

架构示例

  • 两台 Nginx 服务器(主 Nginx 和备份 Nginx)配置了 Keepalived 进行主备切换。
  • 一个虚拟 IP(VIP)用于接收客户端请求,VIP 会根据 Keepalived 的状态漂移到不同的服务器。
  • 当主 Nginx 服务器宕机时,Keepalived 自动将 VIP 转移到备 Nginx 服务器,客户端请求无感知切换。

基本配置

/etc/keepalived/keepalived.conf

Keepalived 配置(主服务器):

vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.0.100
}
track_script {
chk_nginx
}
}

Keepalived 配置(备份服务器)

vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
virtual_ipaddress {
192.168.0.100
}
track_script {
chk_nginx
}
}

Nginx 高可用的架构图示

+-------------------------+           +-------------------------+
| Client Requests | | Client Requests |
+-------------------------+ +-------------------------+
| |
v v
+------------------+ +------------------+
| VIP (Keepalived) |<--Failover-->| VIP (Keepalived)|
+------------------+ +------------------+
| |
v v
+------------------+ +------------------+
| Nginx (Master) | | Nginx (Backup) |
+------------------+ +------------------+
| |
v v
+-------------------------+ +-------------------------+
| Backend Server Pool | | Backend Server Pool |
+-------------------------+ +-------------------------+