Nginx-反向代理、动静分离、负载均衡、Rewrite、防盗链

反向代理

	server {
		listen		8081;
		server_name	www.fan.cn;
		location / {
			proxy_pass http://127.0.0.1:5001;
		}	
	}

实际使用中,可以将请求转发到本机另一个服务器上,也可以根据访问的路径跳转到不同端口的服务中。
比如我们监听 9001 端口,然后把访问不同路径的请求进行反向代理:
把访问 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
这种要怎么配置呢,首先同样打开主配置文件,然后在 http 模块下增加一个 server 块:

server {
  listen 9001;
  server_name *.fan.cn;

  location ~ /edu/ {
    proxy_pass http://127.0.0.1:8080;
  }
  
  location ~ /vod/ {
    proxy_pass http://127.0.0.1:8081;
  }
}

动静分离

动静分离可通过location对请求url进行匹配,将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。通常将静态资源放到nginx中,动态资源转发到tomcat服务器中。

	server {
		listen		8083;
		server_name	*.fan.cn;
		
		# 当url中有/static时,会和root目录路径拼接,也就时html/static目录下找文件
		location /static {
			root 	html;
			index	index.html index.htm;
		}
		
		location / {
			proxy_pass http://127.0.0.1:5001;
		}
	}

当访问http://order.fan.cn:8083/static/1.jpg时,会去nginx中的html/staic目录找文件,当访问http://order.fan.cn:8083,去将请求转发到http://127.0.0.1:5001

负载均衡

#定义一组服务器
	upstream myServers1
	{
		server 127.0.0.1:5000;
		server 127.0.0.1:5001;
	}
	server {
		listen		8084;
		server_name	*.fan.cn;
		location / {
			proxy_pass http://myServers1;
		}	
	}

以上配置使用轮询模式,5000、5001会交替被访问

其他负载均衡模式

  • 权重模式
	upstream myServers1
	{
		server 127.0.0.1:5000 weight=1;
		server 127.0.0.1:5001 weight=3;
	}
  • ip_hash
    根据客户端的ip地址转发同一台服务器,可以保持会话,但是很少用这种方式去保持会话,例如我们当前正在使用wifi访问,当切换成手机信号访问时,会话就不保持了。
  • least_conn
    最少连接访问,优先访问连接最少的那一台服务器,这种方式也很少使用,因为连接少,可能是由于该服务器配置较低,刚开始赋予的权重较低。
  • url_hash(需要第三方插件)
    根据用户访问的url定向转发请求,不同的url转发到不同的服务器进行处理(定向流量转发)。
  • fair(需要第三方插件)
    根据后端服务器响应时间转发请求,这种方式也很少使用,因为容易造成流量倾斜,给某一台服务器压垮。

upstream参数

  • server 反向服务地址加端口
  • weight 权重,默认是1,越大权重就越大
  • max_fails 失败多少次认为主机已挂掉则,踢出 (默认配置10s,即服务器宕掉,会自动剔除)
  • fail_timeout 踢出后重新探测时间
  • backup 备用服务,当其他非backup的机器全部宕机或者繁忙的时候,才会启动这台机器。
  • down 表示当前Server不参与负载
upstream myApiTest {
    server localhost:9001 backup;
    server localhost:9002 down;
    server localhost:9003;
}
  • max_conns 允许最大连接数
  • slow_start 当节点恢复,不立即加入,而是等待 slow_start 后加入服务对列。

Rewrite

掩藏真实的url以及url中可能暴露的参数,以及隐藏web使用的编程语言,提高安全性便于搜索引擎收录

	server {
		listen		8085;
		server_name	*.fan.cn;
		location / {
			rewrite ^/product.html$ /product/index break;
			proxy_pass http://127.0.0.1:5001;
		}	
	}

flag标记说明:

last:本条规则匹配完后,继续向下匹配新的location URI规则;
break:本条规则匹配完即终止,不再匹配后面的规则;
redirect:返回302临时重定向,浏览器会显示跳转后的URL;
permanent:返回301永久重定向,浏览器会显示跳转后的URL;

防盗链

        location ^~/images/ {
            valid_referers 192.168.8.102;  #valid_referers 指令,配置是否允许 referer 头部以及允许哪些 referer 访问。192.168.8.102不是ip而是域名(去掉http:// 前缀)
            if ($invalid_referer) {  # 注意这里if后要加空格
                return 403; ## 返回错误码
            }
            
            root   /www/resources;
        }

HTTP 请求转发到 HTTPS

server {
  listen 80;
  server_name www.fan.cn;
  location / {
    rewrite ^(.*) https://$server_name$1 permanent;
  }
}

配置 HTTPS

server {
  listen 443 ssl http2 default_server;   # SSL 访问端口号为 443
  server_name sherlocked93.club;         # 填写绑定证书的域名

  ssl_certificate /etc/nginx/https/1_sherlocked93.club_bundle.crt;   # 证书文件地址
  ssl_certificate_key /etc/nginx/https/2_sherlocked93.club.key;      # 私钥文件地址
  ssl_session_timeout 10m;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;      #请按照以下协议配置
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
  ssl_prefer_server_ciphers on;
  
  location / {
    root         /usr/share/nginx/html;
    index        index.html index.htm;
  }
}

适配 PC 或移动设备

根据用户设备不同返回不同样式的站点,以前经常使用的是纯前端的自适应布局,但无论是复杂性和易用性上面还是不如分开编写的好,比如我们常见的淘宝、京东......这些大型网站就都没有采用自适应,而是用分开制作的方式,根据用户请求的 user-agent 来判断是返回 PC 还是 H5 站点。

server {
  listen 80;
	server_name fe.sherlocked93.club;

	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;
	}
}

静态服务

server {
  listen       80;
  server_name  static.sherlocked93.club;
  charset utf-8;    # 防止中文文件名乱码

  location /download {
    alias	          /usr/share/nginx/html/static;  # 静态资源目录
    
    autoindex               on;    # 开启静态资源列目录
    autoindex_exact_size    off;   # on(默认)显示文件的确切大小,单位是byte;off显示文件大概大小,单位KB、MB、GB
    autoindex_localtime     off;   # off(默认)时显示的文件时间为GMT时间;on显示的文件时间为服务器时间
  }
}

请求过滤

# 非指定请求全返回 403
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
  return 403;
}

location / {
  # IP访问限制(只允许IP是 192.168.0.2 机器访问)
  allow 192.168.0.2;
  deny all;
  
  root   html;
  index  index.html index.htm;
}

静态文件缓存

由于图片、字体、音频、视频等静态文件在打包的时候通常会增加了 hash,所以缓存可以设置的长一点,先设置强制缓存,再设置协商缓存;如果存在没有 hash 值的静态文件,建议不设置强制缓存,仅通过协商缓存判断是否需要使用缓存。

# 图片缓存时间设置
location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ {
	expires 10d;
}

# 如果不希望缓存
expires -1;

解决跨域

1、如果前后端域名不一致

# 请求跨域,约定代理后端服务请求path以/apis/开头
location ^~/apis/ {
    # 这里重写了请求,将正则匹配中的第一个分组的path拼接到真正的请求后面,并用break停止后续匹配
    rewrite ^/apis/(.*)$ /$1 break;
    proxy_pass api.fan.cn;
  
    # 两个域名之间cookie的传递与回写
    proxy_cookie_domain admin.fan.cn api.fan.cn;
}

这样,静态资源我们使用 admin.fan.cn/xx.html,动态资源我们使用 admin.fan.cn/apis/getAwo,浏览器页面看起来仍然访问的前端服务器,绕过了浏览器的同源策略,毕竟我们看起来并没有跨域。
也可以统一一点,直接把前后端服务器地址直接都转发到另一个 server.fan.cn,只通过在后面添加的 path 来区分请求的是静态资源还是后端服务,看需求了。

2、配置 header 解决跨域

# /etc/nginx/conf.d/be.sherlocked93.club.conf

server {
  listen       80;
  server_name  be.sherlocked93.club;
  
	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/be;
		index index.html;
	}
}

开启gzip

gzip 是一种常用的网页压缩技术,传输的网页经过 gzip 压缩之后大小通常可以变为原来的一半甚至更小(官网原话),更小的网页体积也就意味着带宽的节约和传输速度的提升,特别是对于访问量巨大大型网站来说,每一个静态资源体积的减小,都会带来可观的流量与带宽的节省。

# /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_static on;
gzip_proxied any;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_min_length 1k;
gzip_http_version 1.1;

泛域名路径分离

经常有时候我们可能需要配置一些二级或者三级域名,希望通过 Nginx 自动指向对应目录,比如:
test1.doc.sherlocked93.club 自动指向 /usr/share/nginx/html/doc/test1 服务器地址;
test2.doc.sherlocked93.club 自动指向 /usr/share/nginx/html/doc/test2 服务器地址;

server {
    listen       80;
    server_name  ~^([\w-]+)\.doc\.sherlocked93\.club$;

    root /usr/share/nginx/html/doc/$1;
}

泛域名转发

和之前的功能类似,有时候我们希望把二级或者三级域名链接重写到我们希望的路径,让后端就可以根据路由解析不同的规则:
test1.serv.sherlocked93.club/api?name=a 自动转发到 127.0.0.1:8080/test1/api?name=a
test2.serv.sherlocked93.club/api?name=a 自动转发到 127.0.0.1:8080/test2/api?name=a

server {
    listen       80;
    server_name ~^([\w-]+)\.serv\.sherlocked93\.club$;

    location / {
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        Host $http_host;
        proxy_set_header        X-NginX-Proxy true;
        proxy_pass              http://127.0.0.1:8080/$1$request_uri;
    }
}

最佳实践

  1. 为了使 Nginx 配置更易于维护,建议为每个服务创建一个单独的配置文件,存储在 /etc/nginx/conf.d 目录,根据需求可以创建任意多个独立的配置文件。
  2. 独立的配置文件,建议遵循以下命名约定 <服务>.conf,比如域名是 sherlocked93.club,那么你的配置文件的应该是这样的 /etc/nginx/conf.d/sherlocked93.club.conf,如果部署多个服务,也可以在文件名中加上 Nginx 转发的端口号,比如 sherlocked93.club.8080.conf,如果是二级域名,建议也都加上 fe.sherlocked93.club.conf。
  3. 常用的、复用频率比较高的配置可以放到 /etc/nginx/snippets 文件夹,在 Nginx 的配置文件中需要用到的位置 include 进去,以功能来命名,并在每个 snippet 配置文件的开头注释标明主要功能和引入位置,方便管理。比如之前的 gzip、cors 等常用配置,我都设置了 snippet。
  4. Nginx 日志相关目录,内以 域名.type.log 命名(比如 be.sherlocked93.club.access.log 和 be.sherlocked93.club.error.log )位于 /var/log/nginx/ 目录中,为每个独立的服务配置不同的访问权限和错误日志文件,这样查找错误时,会更加方便快捷。

参考:
https://xie.infoq.cn/article/2051e9a2e76e80393353d826a

posted @ 2022-05-28 14:55  .Neterr  阅读(73)  评论(0编辑  收藏  举报