Nginx应用场景
Nginx配置文件说明
Nginx 的配置文件位置
1、文件位置
安装目录\conf\nginx.conf
安装目录\nginx.conf
2、两个文件是一样的
3、使用 /usr/local/nginx/sbin/nginx 启动 Nginx ,默认用的是 安装目录 \nginx.conf 配置文件
4、作用:完成对 Nginx 的各种配置,包括端口,并发数,重写规则等
1.反向代理
配置说明:当浏览器对nginx所在服务器发起请求时,比如:192.168.79.111/XXX
请求会被转发到linux本机安装的tomcat端口为8080,当然如果nginx和tomcat不在同一个服务器proxy_pass更改为对应的IP和端口即可。
这样做的好处在于只需对外暴露nginx所在的服务器ip,而不必暴露tomcat所在服务器ip。
server {
listen 80;
# Nginx所在得服务器得ip
server_name 192.168.79.111;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
# 当浏览器请求192.168.79.111/XXX就会转发到127.0.0.1:8080/XXX
proxy_pass http://127.0.0.1:8080;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
2.负载均衡
负载均衡就是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快
linux 下有 Nginx、LVS、Haproxy 等等服务可以提供负载均衡服务, Nginx 提供了几种分
配方式(策略):
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔
除
2、weight(权重)
weight 代表权重,默认为 1,权重越高被分配的客户端越多
指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况。 例如
upstream llpservers{
server 192.168.79.111:8080 weight=1;
server 192.168.79.111:8081 weight=2;
}
3、ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决session共享的问题。
upstream llpservers{
ip_hash;
server 192.168.79.111:8081;
server 192.168.79.111:8080;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配
upstream llpservers{
server 192.168.79.111:8080;
server 192.168.79.111:8081;
fair;
}
#1.配置要进行负载均衡的服务器ip和端口 llpservers由可以根据实际情况命名
#2.注意upstream上游服务器配置在http全局块中
upstream llpservers {
server 192.168.79.111:8080;
server 192.168.79.111:8081;
}
#配置nginx要监听的端口和ip
server {
listen 80;
server_name 192.168.79.111;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
# proxy_pass http://127.0.0.1:8080;
#1.指定要对那一组服务器进行负载均衡
#2.llpservers在前面进行了配置
proxy_pass http://llpservers;
index index.html index.htm;
}
ps:小技巧执行在nginx安装目录执行./sbin/nginx -t
可以检查配置那里有问题
3.动静分离
什么时动静分离?
- Nginx 动静分离简单来说就是把动态跟静态请求分开,可以理解成使用 Nginx 处理静态
页面/资源,Tomcat 处理动态页面/资源。 - 动静分离可以减轻 Tomcat 压力,静态请求由 Nginx 处理,提供系统整体性能.
- 不管是前后端分离项目还是传统项目,动静分离在nginx中都是配置动态应用和静态应用的Localtion匹配规则
location / {
root /usr/local/nginx/html/dist;
index index.html index.htm;
}
规则说明
:已nginx服务器ip为192.168.109.130为例,/usr/local/nginx/html/dist
目录存放的是一个前端项目,当浏览器请求192.168.109.130/XX资源时,会到 /usr/local/nginx/html/dist
目录下去查找资源
192.168.109.130/1.jpg ----> 192.168.109.130//usr/local/nginx/html/dist/1.jpg
3.Nginx资源压缩
建立在动静分离的基础之上,如果一个静态资源的Size
越小,那么自然传输速度会更快,同时也会更节省带宽,因此我们在部署项目时,也可以通过Nginx
对于静态资源实现压缩传输,一方面可以节省带宽资源,第二方面也可以加快响应速度并提升系统整体吞吐。
在Nginx
也提供了三个支持资源压缩的模块ngx_http_gzip_module、ngx_http_gzip_static_module、ngx_http_gunzip_module
,其中ngx_http_gzip_module
属于内置模块,代表着可以直接使用该模块下的一些压缩指令,后续的资源压缩操作都基于该模块,先来看看压缩配置的一些参数/指令:
参数项 | 释义 | 参数值 |
---|---|---|
gzip | 开启或关闭压缩机制 | on/off; |
gzip_types | 根据文件类型选择性开启压缩机制 | image/png、text/css... |
gzip_comp_level | 用于设置压缩级别,级别越高越耗时 | 1~9 (越高压缩效果越好) |
gzip_vary | 设置是否携带Vary:Accept-Encoding 头域的响应头部 | on/off; |
gzip_buffers | 设置处理压缩请求的缓冲区数量和大小 | 数量 大小,如16 8k; |
gzip_disable | 针对不同客户端的请求来设置是否开启压缩 | 如 .*Chrome.*; |
gzip_http_version | 指定压缩响应所需要的最低HTTP 请求版本 | 如1.1; |
gzip_min_length | 设置触发压缩的文件最低大小 | 如512k; |
gzip_proxied | 对于后端服务器的响应结果是否开启压缩 | off、expired、no-cache... |
了解了Nginx
中的基本压缩配置后,接下来可以在Nginx
中简单配置一下:
http{
# 开启压缩机制
gzip on;
# 指定会被压缩的文件类型(也可自己配置其他类型)
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png;
# 设置压缩级别,越高资源消耗越大,但压缩效果越好
gzip_comp_level 5;
# 在头部中添加Vary: Accept-Encoding(建议开启)
gzip_vary on;
# 处理压缩请求的缓冲区数量和大小
gzip_buffers 16 8k;
# 对于不支持压缩功能的客户端请求不开启压缩机制
gzip_disable "MSIE [1-6]\."; # 低版本的IE浏览器不支持压缩
# 设置压缩响应所支持的HTTP最低版本
gzip_http_version 1.1;
# 设置触发压缩的最小阈值
gzip_min_length 2k;
# 关闭对后端服务器的响应结果进行压缩
gzip_proxied off;
}
在上述的压缩配置中,最后一个gzip_proxied
选项,可以根据系统的实际情况决定,总共存在多种选项:
off
:关闭Nginx
对后台服务器的响应结果进行压缩。expired
:如果响应头中包含Expires
信息,则开启压缩。no-cache
:如果响应头中包含Cache-Control:no-cache
信息,则开启压缩。no-store
:如果响应头中包含Cache-Control:no-store
信息,则开启压缩。private
:如果响应头中包含Cache-Control:private
信息,则开启压缩。no_last_modified
:如果响应头中不包含Last-Modified
信息,则开启压缩。no_etag
:如果响应头中不包含ETag
信息,则开启压缩。auth
:如果响应头中包含Authorization
信息,则开启压缩。any
:无条件对后端的响应结果开启压缩机制。
OK~,简单修改好了Nginx
的压缩配置后,我们来做个测试 ,下面是我做了上传得静态文件,以app.7733e065.js
文件为例没用压缩之前是241kb
配置压缩,重启nginx之后再次访问,可以看到app.7733e065.js
只有79kb,效果还是很明显得.
配置压缩并不会影响图片清晰度,但是会比较耗费性能占用带宽.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jan5OT8b-1674027324348)(http://cdn.llinp.cn/imgs/202301130943242.png)]
4.Nginx设置ip黑白名单
有时候往往有些需求,可能某些接口只能开放给对应的合作商,或者购买/接入API
的合作伙伴,那么此时就需要实现类似于IP
白名单的功能。而有时候有些恶意攻击者或爬虫程序,被识别后需要禁止其再次访问网站,因此也需要实现IP
黑名单。那么这些功能无需交由后端实现,可直接在Nginx
中处理。
Nginx
做黑白名单机制,主要是通过allow、deny
配置项来实现:
allow xxx.xxx.xxx.xxx; # 允许指定的IP访问,可以用于实现白名单。
deny xxx.xxx.xxx.xxx; # 禁止指定的IP访问,可以用于实现黑名单。
要同时屏蔽/开放多个IP
访问时,如果所有IP
全部写在nginx.conf
文件中显然是不合适的,这种方式比较冗余,那么可以新建两个文件BlocksIP.conf、WhiteIP.conf
:
# --------黑名单:BlocksIP.conf---------
deny 192.177.12.222; # 屏蔽192.177.12.222访问
deny 192.177.44.201; # 屏蔽192.177.44.201访问
deny 127.0.0.0/8; # 屏蔽127.0.0.1到127.255.255.254网段中的所有IP访问
# --------白名单:WhiteIP.conf---------
allow 192.177.12.222; # 允许192.177.12.222访问
allow 192.177.44.201; # 允许192.177.44.201访问
allow 127.45.0.0/16; # 允许127.45.0.1到127.45.255.254网段中的所有IP访问
deny all; # 除开上述IP外,其他IP全部禁止访问
分别将要禁止/开放的IP
添加到对应的文件后,可以再将这两个文件在nginx.conf
中导入:
nginx有两个配置文件,安装目录\conf\nginx.conf、安装目录\nginx.conf,nginx以哪一个配置文件启动就配置在哪一个文件中,这里以安装目录\nginx.conf
为例,引入BlocksIP.conf和WhiteIPs.conf的配置和安装目录\nginx.conf
在同一个目录即可,也可以指定绝对路径
http{
# 屏蔽该文件中的所有IP
include include BlocksIP.conf;
server{
location xxx {
# 某一系列接口只开放给白名单中的IP
include WhiteIPs.conf;
}
}
}
重启nginx
/usr/local/nginx/sbin/nginx -s reload
对于文件具体在哪儿导入,这个也并非随意的,如果要整站屏蔽/开放就在http
中导入,如果只需要一个域名下屏蔽/开放就在sever
中导入,如果只需要针对于某一系列接口屏蔽/开放IP
,那么就在location
中导入。
也可以通过ngx_http_geo_module、ngx_http_geo_module
第三方库去实现(这种方式可以按地区、国家进行屏蔽,并且提供了IP
库)。
5.Nginx解决跨域问题
跨域问题在之前的单体架构开发中,其实是比较少见的问题,除非是需要接入第三方SDK
时,才需要处理此问题。但随着现在前后端分离、分布式架构的流行,跨域问题也成为了每个Java开发必须要懂得解决的一个问题。
跨域问题产生的原因
产生跨域问题的主要原因就在于**「同源策略」** ,为了保证用户信息安全,防止恶意网站窃取数据,同源策略是必须的,否则cookie
可以共享。由于http
无状态协议通常会借助cookie
来实现有状态的信息记录,例如用户的身份/密码等,因此一旦cookie
被共享,那么会导致用户的身份信息被盗取。 同源策略主要是指三点相同,「协议+域名+端口」 相同的两个请求,则可以被看做是同源的,但如果其中任意一点存在不同,则代表是两个不同源的请求,同源策略会限制了不同源之间的资源交互。
Nginx解决跨域问题
弄明白了跨域问题的产生原因,接下来看看Nginx
中又该如何解决跨域呢?其实比较简单,在nginx.conf
中稍微添加一点配置即可:
location / {
# 允许跨域的请求,可以自定义变量$http_origin,*表示所有
add_header 'Access-Control-Allow-Origin' *;
# 允许携带cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
# 允许跨域请求的方法:GET,POST,OPTIONS,PUT
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT';
# 允许请求时携带的头部信息,*表示所有
add_header 'Access-Control-Allow-Headers' *;
# 允许发送按段获取资源的请求
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
# 一定要有!!!否则Post请求无法进行跨域!
# 在发送Post跨域请求前,会以Options方式发送预检请求,服务器接受时才会正式请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
# 对于Options方式的请求返回204,表示接受跨域请求
return 204;
}
}
在nginx.conf
文件加上如上配置后,跨域请求即可生效了。
但如果后端是采用分布式架构开发的,有时候RPC调用也需要解决跨域问题(不同服务之间),不然也同样会出现无法跨域请求的异常,因此可以在你的后端项目中,通过继承HandlerInterceptorAdapter
类、实现WebMvcConfigurer
接口、添加@CrossOrgin
注解的方式实现接口之间的跨域配置。
6.Nginx防盗链
首先了解一下何谓盗链:「盗链即是指外部网站引入当前网站的资源对外展示」 ,来举个简单的例子理解:
好比壁纸网站X
站、Y
站,X
站是一点点去购买版权、签约作者的方式,从而积累了海量的壁纸素材,但Y
站由于资金等各方面的原因,就直接通过<img src="X站/xxx.jpg" />
这种方式照搬了X
站的所有壁纸资源,继而提供给用户下载。
Nginx
的防盗链机制实现,跟一个头部字段:Referer
有关,该字段主要描述了当前请求是从哪儿发出的,那么在Nginx
中就可获取该值,然后判断是否为本站的资源引用请求,如果不是则不允许访问。Nginx
中存在一个配置项为valid_referers
,正好可以满足前面的需求,语法如下:
-
valid_referers none | blocked | server_names | string ...;
-
none
:表示接受没有Referer
字段的HTTP
请求访问。blocked
:表示允许http://
或https//
以外的请求访问。server_names
:资源的白名单,这里可以指定允许访问的域名。string
:可自定义字符串,支配通配符、正则表达式写法。
简单了解语法后,接下来的实现如下:
# 在动静分离的location中开启防盗链机制
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){
# 最后面的值在上线前可配置为允许的域名地址或ip
valid_referers blocked 192.168.12.129;
if ($invalid_referer) {
# 可以配置成返回一张禁止盗取的图片
# rewrite ^/ http://xx.xx.com/NO.jpg;
# 也可直接返回403
return 403;
}
root /soft/nginx/static_resources;
#当nginx设置了expires后,例如设置为:expires 10d;
#那么,所在的location或if的内容,用户在10天内请求的时候,
#都只会访问浏览器中的缓存,而不会去请求nginx。
#ps:需要注意的是,这种缓存方式只能在用户不对浏览器强制刷新的情况下生效
#expires 30s; #缓存30秒
#expires 30m; #缓存30分钟
#expires 2h; #缓存2小时
#expires 30d; #缓存30天
expires 7d;
}
ps:防盗链机制也无法解决爬虫伪造referers
信息的这种方式抓取数据。
7.Nginx大文件传输配置
在某些业务场景中需要传输一些大文件,但大文件传输时往往都会会出现一些Bug
,比如文件超出限制、文件传输过程中请求超时等,那么此时就可以在Nginx
稍微做一些配置,先来了解一些关于大文件传输时可能会用的配置项:
配置项 | 释义 |
---|---|
client_max_body_size | 设置请求体允许的最大体积 |
client_header_timeout | 等待客户端发送一个请求头的超时时间 |
client_body_timeout | 设置读取请求体的超时时间 |
proxy_read_timeout | 设置请求被后端服务器读取时,Nginx 等待的最长时间 |
proxy_send_timeout | 设置后端向Nginx 返回响应时的超时时间 |
配置在nginx配置文件最外层
client_max_body_size 50m; # 限制请求体的大小,若超过所设定的大小,返回413错误,默认1m
client_header_timeout 1m; # 读取请求头的超时时间,若超过所设定的大小,返回408错误
client_body_timeout 1m; # 读取请求实体的超时时间,若超过所设定的大小,返回413错误
proxy_connect_timeout 60s; # http请求没法当即被容器(tomcat, netty等)处理,被放在nginx的待处理池中等待被处理。此参数为等待的最长时间,默认为60秒,官方推荐最长不要超过75秒
proxy_read_timeout 1m; # http请求被容器(tomcat, netty等)处理后,nginx会等待处理结果,也就是容器返回的response。此参数即为服务器响应时间,默认60秒
proxy_send_timeout 1m; # http请求被服务器处理完后,把数据传返回给Nginx的用时,默认60秒
8.Nginx配置SLL证书
随着越来越多的网站接入HTTPS
,因此Nginx
中仅配置HTTP
还不够,往往还需要监听443
端口的请求,HTTPS
为了确保通信安全,所以服务端需配置对应的数字证书,当项目使用Nginx
作为网关时,那么证书在Nginx
中也需要配置,接下来简单聊一下关于SSL
证书配置过程:
-
①先去CA机构或从云控制台中申请对应的
SSL
证书,审核通过后下载Nginx
版本的证书。 -
②下载数字证书后,完整的文件总共有三个:
.crt、.key、.pem
: -
.crt
:数字证书文件,.crt
是.pem
的拓展文件,因此有些人下载后可能没有。.key
:服务器的私钥文件,及非对称加密的私钥,用于解密公钥传输的数据。.pem
:Base64-encoded
编码格式的源证书文本文件,可自行根需求修改拓展名。
-
③在
Nginx
目录下新建certificate
目录,并将下载好的证书/私钥等文件上传至该目录。 -
④最后修改一下
nginx.conf
文件即可,如下:
# ---------HTTP请求转HTTPS-------------
server {
# 监听HTTP默认的80端口
listen 80;
# 如果80端口出现访问该域名的请求
server_name www.xxx.com;
# 将请求改写为HTTPS(这里写你配置了HTTPS的域名)
rewrite ^(.*)$ https://www.xxx.com;
}
# ----------HTTPS配置-----------
server {
# 监听HTTPS默认的443端口
listen 443;
# 配置自己项目的域名
server_name www.xxx.com;
# 打开SSL加密传输
ssl on;
# 输入域名后,首页文件所在的目录
root html;
# 配置首页的文件名
index index.html index.htm index.jsp index.ftl;
# 配置自己下载的数字证书
ssl_certificate certificate/xxx.pem;
# 配置自己下载的服务器私钥
ssl_certificate_key certificate/xxx.key;
# 停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
ssl_session_timeout 5m;
# TLS握手时,服务器采用的密码套件
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
# 服务器支持的TLS版本
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# 开启由服务器决定采用的密码套件
ssl_prefer_server_ciphers on;
#如果是静态文件,直接指向目录,如果是动态应用,用proxy_pass转发一下
location / {
root /usr/local/service/ROOT;
index index.html;
}
#动态应用
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://ip:port;
}
}