Nginx
简介
nginx [engine x]是一个HTTP和反向代理服务器,一个邮件代理服务器和一个通用的TCP / UDP代理服务器。
Nginx 相对于 Apache 优点如下
- 高并发响应性能好,对静态处理文件并发 5w/s
- 负载均衡 和 反向代理 性能非常强
- 内存 cpu 占用率低
- 提供健康检查
- 支持 PHP CGI 和Fast CGI
- 可以作为缓存服务器、邮件代理服务器
Nginx常用命令
# fast shutdown
nginx -s stop
# graceful shutdown
nginx -s quit
# reloading the configuration file
nginx -s reload
# reopening the log files
nginx -s reopen
# 为 Nginx 指定一个配置文件,来代替缺省的
nginx -c filename
# 不运行nginx,只检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# 显示 nginx 的版本
nginx -v
# 显示 nginx 的版本,编译器版本和配置参数
nginx -V
Nginx信号控制
TERM、INT | 快速关闭进程 |
---|---|
QUIT | 优雅的关闭进程,即等请求结束之后再关闭 |
HUP | 改变配置文件之后、平滑的重读配置文件 |
USR1 | 切割日志 |
USR2 | Nginx平滑的升级 |
WINCH | 优雅的关闭旧进程,配合USR2进行升级 |
kill -HUP `cat /var/run/nginx.pid`
正向代理
局域网中的客户端要访问Internet,通过nginx代理服务器来访问目标网站,代理向原始服务器转交请求并将获得的内容返回给客户端。
server{
listen 82; #代理监听端口
resolver 8.8.8.8; #DNS
resolver_timeout 10s; # DNS解析超时时间
location / {
# 配置正向代理参数
proxy_pass $scheme://$host$request_uri;
# 解决如果URL中带"."后Nginx 503错误
proxy_set_header Host $http_host;
# 配置缓存大小
proxy_buffers 256 4k;
# 关闭磁盘缓存读写减少I/O
proxy_max_temp_file_size 0;
# 代理连接超时时间
proxy_connect_timeout 30;
# 配置代理服务器HTTP状态缓存时间
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
}
}
反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。nginx一般均作为反向代理使用
Load Balancer 负载均衡(upstream{}
)
负载均衡利用一定的分配策略把网络负载平衡的分摊到网络集群的各个节点上。Nginx基于优先级的加权轮询方法。
NGINX 负载均衡策略
- Round Robin:默认策略,请求在服务器之间均匀分布,并考虑服务器权重
- least_conn:将请求发送到具有最少活动连接数的服务器,同时考虑服务器权重
- ip_hash ,从客户端IP地址确定发送请求的服务器,保证同个请求分配的服务器不变;如果需要从负载平衡轮换中临时删除其中一个服务器,则可以使用该down参数对其进行标记,以便保留客户端IP地址的当前哈希值。可以解决session不共享的问题。
- hash:发送请求的服务器是从用户定义的密钥确定的,该密钥可以是文本字符串,变量或组合,在 upstream 中有应用服务器被加入或删除时,会重新计算散列进行分发;hash $request_uri consistent;
NGINX Plus 新增2种策略
- least_time:对于每个请求,nginx plus选择具有最低平均延迟和最低数量的活动连接,参数:header - 从服务器接收第一个字节的时间;last_byte - 从服务器接收完整响应的时间;last_byte inflight - 考虑到不完整的请求,是时候从服务器接收完整的响应(least_time header ;)
- random:nginx plus每个请求都将传递给随机选择的服务器参数:least_conn - 活动连接数最少;least_time=header - 从服务器接收响应头的平均时间最短
upstream_response_time;(random two least_time=last_byte;)
HTTP负载均衡(常用) http{ upstream{} }
将HTTP流量代理到一组服务器。跨多个应用程序实例的负载平衡是一种常用技术,用于优化资源利用率,最大化吞吐量,减少延迟并确保容错配置。在http{}
模块配置
http {
upstream backend {
ip_hash; # 均衡策略
server backend1.example.com weight=5; # weight默认是1
server backend2.example.com;
server 192.0.0.1 backup; # 定义为备份
server 192.0.0.1 down; # 临时删除服务器,保留客户端IP地址的当前哈希值
}
server {
location / {
proxy_pass http://backend;
}
}
}
TCP和UDP负载均衡 stream{ upstream{} }
可以代理和负载均衡TCP流量和UDP流量。Nginx Plus或者Nginx 编译时怎加--with-stream选项。在stream {}
模块配置。
- TCP(传输控制协议)是许多流行应用程序和服务的协议,例如LDAP,MySQL和RTMP。
- UDP(用户数据报协议)是许多流行的非事务性应用程序的协议,例如DNS,syslog和RADIUS。
stream {
upstream stream_backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
}
upstream dns_servers {
server 192.168.136.130:53;
server 192.168.136.131:53;
}
server {
listen 12345; # TCP流量将会被转发到"stream_backend"的upstream
proxy_pass stream_backend;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
server {
listen 53 udp; # UDP流量将会被转发到"dns_servers"的upstream
proxy_pass dns_servers;
}
}
upstream健康检查
upstream study-steam-kada {
server 10.172.131.172:16042;
server 10.172.131.167:16042;
check interval=3000 rise=2 fall=3 timeout=5000 type=http;
check_http_send "HEAD /health/status HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
NGINX 服务器提供两种不同的健康检测方案
- 开源版的 NGINX 提供被动检测功能:
被动检测的实现原理是:NGINX 服务器通过检测客户端发送的请求及被代理(被负载均衡)服务器的响应结果进行判断被代理服务器是否失效。被动检测方案,可以有效降低被代理服务器的负载压力。
upstream backend {
server backend1.example.com:1234 max_fails=3 fail_timeout=3s;
server backend2.example.com:1234 max_fails=3 fail_timeout=3s;
}
- NGINX PLUS 提供主动检测功能:
主动检测的实现原理是,NGINX 代理服务向被代理服务器定时的发送连接请求,如果被代理服务器正常响应,则说明被代理服务器正常运行。主动检测则能够在客户端发送请求之前,就能够剔除掉失效服务器。
# 通过向被代理服务器每隔 2 秒,发送一个到 '/' URI 的请求来检测被代理服务器是否失效。
# 被代理服务器连续接收 5 个请求,如果其中有 2 个连续请求响应失败,将被视作服务器失效
# 被代理服务器的健康响应格式在 match 块级指令中配置
# 规定响应状态码为 200, 响应 Content-Type类型为'text/html',响应 body 为 "Welcome to nginx!" 字符串的响应为有效服务器
http {
upstream backend {
server backend1.example.com:1234 max_fails=3 fail_timeout=3s;
server backend2.example.com:1234 max_fails=3 fail_timeout=3s;
health_check interval=2s fails=2 passes=5 uri=/ match=welcome;
}
match welcome {
status 200;
header Content-Type = text/html;
body ~ "Welcome to nginx!";
}
server {
location / {
proxy_pass http://backend;
}
}
}
upstream服务器慢启动
最近恢复的服务器很容易被连接淹没,这可能导致服务器再次被标记为不可用。慢启动允许上游服务器在恢复或变得可用之后逐渐将其权重从零恢复到其标称值。
upstream backend {
server backend1.example.com slow_start=30s;
server backend2.example.com;
}
Web server(http{ server{} }
)
虚拟主机的配置在 http
上下文的server
里,配置完成后绑定/etc/hosts
测试
server {
listen 192.168.0.100:80; # 监听ip和端口
server_name www.example.com ~^www\d+\.example\.com$; # 虚拟服务器的名称
charset utf-8;
access_log /var/log/nginx/access.log; # 访问日志
error_log /var/log/nginx/error.log; # 错误日志
allow 192.168.1.0/32; # 白名单
deny all;
location / { # 匹配uri
proxy_set_header X-Real-IP $remote_addr; # $remote_addr为客户端的ip
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 记录整个的代理过程
proxy_set_header Host $host; # $host就是nginx代理服务器
proxy_http_version 1.1; # 长连接
proxy_next_upstream error timeout; # 重试机制,出现 错误、连接超时,尝试下一个后端
proxy_pass http://web_backend; # 转发
}
}
location {}
= :精确匹配
^~ :匹配开头
~ :区分大小写的正则匹配结尾
~* :不区分大小写的正则匹配结尾
! :不匹配
/ :通用匹配,任何请求都会匹配到。
location / 匹配任何以/开头的路由
location =/ 表示只匹配/,也就是根目录
按匹配优先级进行匹配,匹配到了会停止其他location
location = / { # 精确匹配/,会加快访问速度
[ configuration A ]
}
location / {
[ configuration B ] # 匹配任何请求,最低优先级,更长字符匹配或者正则表达式匹配会优先匹配
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ { # 前缀匹配
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ { # 正则匹配,所有 /images/ 目录的请求将由 [Configuration D]处理.
[ configuration E ]
}
带/与不带/的区别
location /some/path/ { } # 带/会认为是一个路径
location /some/file { } # 不带/会认为是一个文件
HTTPS
server {
listen 443 ssl; # 启用https
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/www.example.com.crt; # crt文件
ssl_certificate_key /etc/nginx/ssl/www.example.com.key; # key文件
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # ssl协议
ssl_ciphers HIGH:!aNULL:!MD5; # 启用的密码
}
HTTPS服务器优化
SSL操作会消耗额外的CPU资源。最耗CPU的操作是SSL握手。有两种方法可以最大程度地减少每个客户端执行这些操作的次数:
启用保持连接以通过一个连接发送多个请求
-
重用SSL会话参数以避免并行和后续连接的SSL握手
http { ssl_session_cache shared:SSL:10m; # 设置存储会话参数的缓存的类型和大小,1m大约4000个会话 ssl_session_timeout 10m; # 默认5分钟 server { listen 443 ssl; server_name www.example.com; keepalive_timeout 70; ssl_certificate /etc/nginx/ssl/www.example.com.crt; ssl_certificate_key /etc/nginx/ssl/www.example.com.key; } }
proxy_set_header
重新定义传递给代理服务器的请求标头,预定义变量见 (http://nginx.org/en/docs/http/ngx_http_core_module.html#variables)
Syntax: proxy_set_header field value;
Default:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context: http, server, location
proxy_http_version
代理的HTTP协议版本(长连接),HTTP1.1之后,HTTP协议支持持久连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。
Syntax: proxy_http_version 1.0 | 1.1;
Default: proxy_http_version 1.0;
Context: http, server, location
proxy_next_upstream 重试机制
当请求服务器发生错误或超时时,会尝试到下一台服务器
Syntax: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | non_idempotent | off ...;
Default:
proxy_next_upstream error timeout;
Context: http, server, location
proxy_pass 设置代理服务器的协议和地址
- url带
/
和不带/
- 在nginx中配置
proxy_pass
代理转发时,如果在proxy_pass
后面的url加/
,表示绝对根路径; - 如果没有
/
,表示相对路径,把匹配的路径部分也给代理走。
# http://127.0.0.1/index.html
location /proxy/ {
proxy_pass http://127.0.0.1/;
}
# http://127.0.0.1/proxy/index.html
location /proxy/ {
proxy_pass http://127.0.0.1;
}
将请求传递给非HTTP代理服务器
-
fastcgi_pass
将请求传递给FastCGI服务器 -
uwsgi_pass
将请求传递给uwsgi服务器 -
scgi_pass
将请求传递给SCGI服务器 -
memcached_pass
将请求传递给memcached服务器
server {
root /www/data;
location / {
index index.$geo.html index.htm index.html; # 按指定的顺序搜索文件并返回它找到的第一个文件
}
location /images/ {
autoindex on;
}
location ~ \.(mp3|mp4) {
root /www/media;
}
location ~ \.php {
fastcgi_pass localhost:8000;
}
location ~ .*\.(gif|jpg|jpeg|png)$ { # 静态文件
expires 24h; # 本地缓存24小时
root /data/nginx/2/image1/;
}
}
proxy_buffering 缓存头
location /some/path/ {
proxy_buffering on; # 默认就是on
proxy_buffers 16 4k;
proxy_buffer_size 2k;
proxy_pass http://localhost:8000;
}
proxy_bind 配置出口ip
location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}
location /app3/ {
proxy_bind $server_addr;
proxy_pass http://example.com/app3/;
}
if
upstream hilinux_01 {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
server {
listen 80;
server_name www.hi-linux.com;
access_log logs/www.hi-linux.com.log main;
#match cookie
set $group "default";
if ($http_cookie ~* "version=V1"){
set $group hilinux_01;
}
if ($http_cookie ~* "version=V2"){
set $group hilinux_02;
}
if ($remote_addr ~ "211.118.119.11") {
set $group hilinux_02;
}
location / {
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
return 返回
Syntax: return code [text];
return code URL;
return URL;
Context: server, location, if
uri重定向,301
, 302
, 303
, and 307
可以重定向至网页或者文本
location /wrong/url {
return 404;
}
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
实例:对访问xxx.com的请求转到https
server {
server_name xxx.com;
return 307 https://xxx.com$request_uri;
}
server {
server_name xxx.com;
listen 443 ssl;
启用HSTS307
跳转
HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。
server {
server_name xxx.com;
listen 80;
listen 443 ssl http2;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
rewrite 地址重定向
应用场景:
- 调整用户浏览的URL,看起来规范
- 为了让搜索引擎收录网站内容,让用户体验更好
- 网站更换新域名后
- 根据特殊的变量、目录、客户端信息进行跳转
Syntax: rewrite regex replacement [flag];
Context: server, location, if
flag:
last 本条规则匹配完成后继续向下匹配新的location URI规则
break 本条规则匹配完成后终止,不在匹配任何规则
redirect 返回302临时重定向
permanent 返回301永久重定向
重写uri,第一个参数是正则匹配的uri,第二个参数是重写后的uri,第三个是 返回动作或者状态码301
or 302
server {
listen 80;
server_name brian.com;
rewrite ^/(.*) http://www.brian.com/$1 permanent; # 301跳转
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
}
location /images/ {
if ( !-e $request_filename ){ # -f 文件是否存在, -d 目录是否存在
# -e 文件或目录是否存在, -x 文件是否可执行
rewrite ^/(.*) /$1.php last; # 如果文件不存在,就在后面加.php(省略url)
}
}
}
gzip
压缩响应通常会显着减少传输数据的大小,降低延迟。但是,由于压缩在运行时发生,因此它还会增加相当大的处理开销,从而对性能产生负面影响。
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location
server {
gzip on; # 启用gzip
gzip_types text/plain application/xml; # 默认使用MIME类型压缩响应text/html
gzip_min_length 1000; # 要指定要压缩的响应的最小长度,默认20字节
gzip_proxied no-cache no-store private expired auth; # 默认情况下,NGINX不会压缩对代理请求(来自代理服务器的请求)的响应。
gunzip on; # 某些客户端不支持使用gzip编码方法的响应,配置动态解压缩数据
}
sendfile 允许上传文件
sendfile on;
client_max_body_size 10m; #上传文件大小限制,默认1m
proxy timeout 超时时间
proxy_connect_timeout 150; # 与upstream server的连接超时时间
proxy_read_timeout 150; # 等待多长时间来获得请求的响应
proxy_send_timeout 150; # 发送请求给upstream服务器的超时时间
set map geo 设置变量
Syntax: map string $variable { ... }
Context: http
geo [$address] $variable { ... }
从remote_addr
示例
set $vncserver_id vncadmin1; # 创建一个新变量
# 设置agent的值,如果http_user_agent里包含curl,值为curl;如果http_user_agent里包含apachebench,值为ab;默认是
map $http_user_agent $agent {
default "";
~curl curl;
~*apachebench ab;
}
map $uri $value {
/abc /index.php;
~^/teacher/(?<suffix>.*)$ /boy/;
~/fz(/.*) /index.php?fz=1;
}
# 白名单配置
http{
geo $whiteiplist {
default 1; # 默认ip获取到的是1
127.0.0.1 0; # 这些ip获取到的是0
123.123.123.123 0;
172.27.2.5 0;
}
map $whiteiplist $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=req_addr:10m rate=300r/m;
server{
limit_req zone=req_addr burst=50;
limit_req_log_level warn;
}
}
error_page
访问不存在的图片,跳转到指定页面
server {
location /images/ {
root /data/www;
open_file_cache_errors off;
error_page 404 = /fetch$uri;
}
location /old/path.html {
error_page 404 =301 http:/example.com/new/path.html; # 错误处理,将404重定向到特定网页
}
}
auth_basic 登录认证
location / {
auth_basic "这里随意起个名字";
auth_basic_user_file /usr/local/openresty/nginx/conf/auth_file;
}
使用
# 使用 wget
wget --http-user=user --http-passwd=123456 http://localhost/
# 使用 curl
curl -u user:123456 -O http://localhost/
阻止恶意压测
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
# 这里使用的是$binary_remote_addr(4字节)变量,而不是$remote_addr(7-15字节)变量,因为其占有内存小。如果共享内存空间被耗尽,服务器将会对后续所有的请求返回 503(Service Temporarily Unavailable) 错误。
server {
limit_conn addr 100; # 指定一个会话最大的并发连接数(与之前的limit_conn_zone配合使用),多于100个返回Services unavailable(503)状态,生产环境需考虑办公室或者局域网共享IP问题
limit_rate_after 1m; # 设置单连接限速条件(当下载文件字节数超过1MB后,limit_rate限速生效,限速100k)
limit_rate 100k; # 单连接限速
}
}
Content Cache 缓存
配置缓存
启用缓存后,NGINX会将响应保存在磁盘缓存中,并使用它们响应客户端,而无需每次都代理对相同内容的请求。减少后端压力,提高网站并发延时。
- loader_threshold - 迭代持续时间,以毫秒为单位(默认情况下 200)
- loader_files - 一次迭代期间加载的最大项目数(默认情况下 100)
- loader_sleeps - 迭代之间的延迟,以毫秒为单位(默认情况下 50)
示例
http {
...
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m loader_threshold=300 loader_files=200; # 设置缓存的路径,2级目录,大小10m
server {
proxy_cache mycache; # 定义用于缓存的共享内存区域
proxy_cache_valid 200 206 304 301 302 10d; # 缓存10天
proxy_cache_key $uri # 定义缓存唯一key,通过唯一key来进行hash存取
location / {
proxy_pass http://localhost:8000;
}
}
}
proxy_cache_valid 带有代码的响应200或被302认为有效10分钟,带代码的响应404有效1分钟
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 5m;
proxy_cache_key 定义用于缓存的密钥
Syntax: proxy_cache_key string;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location
清除缓存中 proxy_cache_purge
NGINX可以从缓存中删除过时的缓存文件。这对于删除过时的缓存内容以防止同时提供旧版本和新版本的网页是必要的。在收到包含自定义HTTP标头或HTTP PURGE方法的特殊“清除”请求时,将清除缓存。
http {
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on; # 启用清除缓存
## 配置清除缓存方法
map $request_method $purge_method {
PURGE 1;
default 0;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass https://localhost:8002;
proxy_cache mycache;
proxy_cache_purge $purge_method;
}
}
## 限制发送清除命令的主机
geo $purge_allowed {
default 0; # deny from other
10.0.0.1 1; # allow from localhost
192.168.0.0/24 1; # allow from 192.168.0.0/24
}
map $request_method $purge_method {
PURGE $purge_allowed;
default 0;
}
}
发送清除缓存命令
$ curl -X PURGE -D – "https://www.example.com/*"
HTTP/1.1 204 No Content
Server: nginx/1.15.0
Date: Sat, 19 May 2018 16:33:04 GMT
Connection: keep-alive