Java进阶-Nginx进阶
Nginx的HTTPS支持配置
- SSL安全协议
- 传输层安全性协议,SSL,介于http与tcp/UDP之前的一层混合加密的协议,确保数据传输的安全性
- TLS是SSL后序的升级版
环境配置
- 让当前的nginx支持https,因为之前最开始安装nginx时,下载依赖模块没有下载openssl相关的依赖,因此当时编译的nginx也没有支持openssl
- 安装https支持的openssl
yum install -y openssl openssl-devel
- 给源码添加https(openssl)模块
-
进入到之前解压的nginx-1.20.1目录下,查看一下有configure文件夹,执行下面命令
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
-
- 执行make,重新编译nginx, 注意: 不需要执行make install
- 把编译后的最新的可执行程序nginx替换旧的nginx
- cd到objs文件,可以看到编译的nginx
-
备份之前运行nginx
cd /usr/local/nginx/sbin cp nginx nginx.old
-
将源码中重新编译的nginx替换掉/usr/local/nginx/sbin下的nginx
//此时就在/usr/local/nginx/sbin目录下,执行下面命令 cp -f /usr/local/src/nginx-1.20.1/objs/nginx ./
-
向Master发送USER2信号
ps -ef |grep nginx #查看nginx的进程id //1355为nginx的进程id kill -s SIGUSR2 1355
- 此时通过
ps -ef |gep nginx
会发现会重新启动一个nginx进程,一共有2个,一个是旧的,一个是新的 - 接下来需要用新的提供服务,旧的下线
- 此时通过
-
向老的Master进程发送QUIT信号,关闭老的进程
kill -QUIT 1355
-
如果新的nginx启动报错,还可以回滚:向老的Master进程发送HUP信号, 向新的Master进程发送QUIT信号
kill -HUP 1355
SSL证书
- 既然当前nginx已经支持https了,那就需要首先拿到证书,然后在nginx上配置证书,这样,才能使用
免费申请证书,然后nginx配置证书
- 申请证书:
- 前提条件是必须要有域名,比如:coderzhong.online
- 添加依赖库文件:
yum install epel-release -y
- 安装用于免费申请证书的工具包
yum install python2-certbot-nginx
- 开始申请免费证书:
certbot --nginx --nginx-server-root=/usr/local/nginx/conf -d coderzhong.online
-
在nginx.conf配置ssl支持
server { listen 443 ssl; server_name coderzhong.online; ssl_certificate /etc/letsencrypt/live/coderzhong.online/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/coderzhong.online/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { root html; index index.html index.htm; } }
自己制作证书,然后nginx配置证书
-
openssl命令生成证书
# 创建服务器私钥,命令会让你输入一个口令:随便写,比如1234,相当于一个密码,后面还要用,该命令执行完,会生成一个server.key文件 openssl genrsa -des3 -out server.key 1024 # 将该文件移动到/usr/local/nginx/sbin/下 mv server.key /usr/local/nginx/sbin/ # 根据秘钥,创建签名请求的证书(CSR)server.csr :仍然需要输入上面的口令,国家输入cn,其余直接回车 cd server.key /usr/local/nginx/sbin/ openssl req -new -key server.key -out server.csr # 在加载SSL支持的Nginx并使用上述私钥时除去必须的口令:生成一个没有密码的秘钥 openssl rsa -in server.key -out server_nopass.key # 最后标记证书使用上述私钥和CSR:使用没有密码的秘钥、有密码的csr,生成一个没有密码的csr证书 ,x509是证书类型,365是证书有效期,最后生成crt证书 openssl x509 -req -days 365 -in server.csr -signkey server_nopass.key -out server.crt
- 会在/usr/local/nginx/sbin/目录下生成:server.key、server.csr、server_nopass.key、server.crt几个文件
-
在nginx.conf配置ssl支持
server { # hhtps默认端口是443 listen 443 ssl; server_name 127.0.0.1; # 证书位置 ssl_certificate /usr/local/nginx/sbin/server.crt; # 私钥位置 ssl_certificate_key /usr/local/nginx/sbin/server_nopass.key; location / { proxy_pass http://crm; } }
- 重新加载nginx :
sbin/nginx -s reload
- 公钥在证书中,当浏览器访问时,会将证书下载到浏览器
- 将浏览器访问地址修改为https,可以直接访问,然后会提示危险,是否继续,点击继续即可
- 提示危险是有其他机构会检测你的证书,由于是自己创建的,所以会提示不安全
-
HTTPS通信流程
Nginx跨域解决方案
- 什么是跨域问题
- 请求的URI组成:
http://www.52it.com:80/subject/java/getInfo?id=100
- http: 请求的协议
- www.520it.com: 域名(可以是IP地址)
- 80端口: 没有写端口, 对于http协议默认的是80端口
- /subject/java/getInfo: 资源在服务端的路径
- id=100 请求参数
- 当一个请求(异步请求)url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
- 请求的URI组成:
- 跨域的具体配置
-
在请求的目标资源上加上对应的请求的, 允许资源的跨域访问
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers '*';
- ccess-Control-Allow-Origin: 设置请求可以从哪些地址发送过来, * 代表所有的地址
- Access-Control-Allow-Methods: 设置可以跨域请求的方法, OPTIONS 是一个预检方法
- Access-Control-Allow-Headers: 设置允许的请求头信息
-
在nginx.conf下的server块下的location下配置
location / { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers '*'; proxy_pass http://crm; }
-
缓存的开启
- 当发送到tomcat的请求响应数据非常少时,可以将数据直接缓存在nginx,提高效率
- 有时候为了减轻后台的请求压力, 会把对应的请求结果缓存在nginx服务器, 到时候直接从nginx服务器获取对应的缓存结果即可
- 官方文档:
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache
proxy_cache_path :设置缓存路径 ,在http模块中配置 keys_zone=name:size 设置缓存的key 和大小 //举例 proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m; levels: 表示目录 1: 表示1位16进制, 2 表示2位16进制 一个冒号 表示的是有两级目录
- 官方文档:
-
配置
# http模块: proxy_cache_path /datas/cache levels=1:2 keys_zone=one:10m; # location模块进行指定当前请求使用缓存功能 # 配置缓存的区域, 使用one, 对应key_zone中的one proxy_cache one; # 配置有效的缓存, 对于服务器响应200的结果, 数据缓存1分钟 proxy_cache_valid 200 1m;
Http请求防盗链
- 什么是资源盗链
- 资源盗链是指内容不在自己服务器上,而通过技术手段,绕过别人的限制,将别人的内容,比如热门的图片放到自己页面上,展示给用户,以此来盗取别人网站的流量,即蹭流量。
- 情景:为了防止别人爬取自己的网站数据,可以进行请求防盗链配置,相当于添加白名单
- 当浏览器向web服务器发送请求的时候,一般都会带上Referer字段,来告诉浏览器该网页是从哪个页面链接过来的;
- 后台服务器根据获取到的这个Referer信息,从而判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回403(服务端拒绝访问)的状态信息)
- 使用nginx的referer模块
-
指令
valid_referers none: 如果Header中的Referer为空,允许访问; block: 允许referer头部没有对应的值进行访问,在Header中的Referer不为空,但是该值被防火墙或代理进行伪装过,如不带"http://" 、"https://"等协议头的资源允许访问; server_names: 允许匹配的域名进行访问 对于域名可以使用前缀+通配符(*) 进行匹配 referer_hash_bucket_size referer_hash_max_size //变量,用来判断是否能够访问 $invalid_referer: 允许访问, 变量值为空 不允许访问, 变量值为1
-
比如:在location中配置
//添加这个之后,浏览器的请求头会自动添加referer参数 valid_referers none blocked server_name www.crm.com; if($invalid_referer) { return 443; }
Nginx限流方案
- 为何要对nginx限流?
- nginx的最大并发5w,而tomcat的最大并发300每台,那么如果客户端请求量非常多的情况下,nginx直接将请求转发给tomcat就会造成 服务器的雪崩效应
- 因此需要对nginx进行限流,保证能够平稳的合理的请求量转发给tomcat
- 也就是说tomcat不能承受大于其最大并发的请求,否则就会挂掉,因此请求到达tomcat之前可以用nginx做限流控制
- 常见的限流策略
- 计数器算法:在指定的时间内,放行指定数量的请求
- 令牌桶
- 漏桶算法
- Nginx限流实现
- 限制并发连接数(计数器算法)
-
使用limit_conn模块
#定义共享内存,key 通常取客户端ip limit_conn_zone key zone=name:size http #限制并发连接数 limit_conn zone number; http|server|location
-
配置
//addr:限流的名称 limit_conn_zone $binary_remote_addr zone=addr:10m; location / { limit_conn_status 500; limit_conn_log_level error; #请求下载的速度 limit_rate 50; # 限流策略,每分钟一个请求 limit_conn addr 1; }
-
- 限制访问频率(漏桶算法)
-
imit_req 指令
#定义共享内存够大小 limit_req_zone key zone=name:size rate=rate; http模块 #限制并发连接数 limit_req zone=name [burst=number][nodelay]; http|server|location #burst 默认为0 nodelay: 对burst请求立即处理
-
配置
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/m; location / { limit_req zone=one; }
-
- 限制并发连接数(计数器算法)
Http请求的处理流程
- Nginx请求处理流程、Nginx内部处理流程图
搭建高可用环境
- 我们是通过Nginx进行反向代理,如果Nginx关了的话就没有其他服务支撑.所以我们需要来实现Nginx的高可用,高可用就是我们一台机器挂了可以切换到另外一台机器
- 我们使用Nginx+keepalived搭建高可用环境
- 实现场景
- 假设部署了2台Nginx(master、backup),一台挂了能自动访问另一台
- 客户端只需要连接一个虚拟的IP地址,正常情况这个虚拟的地址映射到master,一旦master挂了,能自动指向backup
- keepalived实现的功能
- 保证生成一个vip地址(虚拟ip),并且可以vip可以自动切换
- 定时检测对应的nginx服务状态,对于master的状态信息要即时通知backup
Keepalived简介
- 首先介绍一下Keepalived,它是一个高性能的服务器高可用或热备解决方案,Keepalived主要防止服务器单点故障的问题,可以通过其与Nginx的配合实现web服务器端的高可用.
-
Keepalived以VRRP协议为实现基础,使用VRRP协议来实现高可用性(HA).VRRP(Virtual Router Redundacy Protocol)协议用于实现路由器冗余的协议,VRRP协议将两台或多台路由器设备虚拟成一个设备,向外提供虚拟路由IP(一个或多个),如下图所示:
- 安装keepalived(master、Slave都要安装)
-
第一步:安装keepalived依赖的包
yum install gcc openssl-devel libnl3-devel popt-devel iptables-devel libnfnetlink-devel -y
-
第二步:编译安装keepalived
将keepalived的安装包 上传到/usr/local/software 目录下 cd /usr/local/software tar -zxvf keepalived-2.0.20.tar.gz -C /usr/local/src/ cd /usr/local/src/keepalived-2.0.20/ # 配置将源码编译到哪个目录下 ./configure --prefix=/usr/local/keepalived make && make install
-
第三步:将 keepalived 安装成 Linux 系统服务
//安装完成之后,需要做一些工作复制默认配置文件到默认路径 mkdir /etc/keepalived cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ cp /usr/local/keepalived/sbin/keepalived /usr/sbin/ cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ cp /usr/local/keepalived/sbin/keepalived /etc/init.d/
-
第四步:编写nginx检测脚本:
vi /etc/keepalived/nginx_check.sh //内容如下: //检查是否存在nginx进程信息 #!/bin/bash A=`ps -C nginx –no-header |wc -l` if [ $A -eq 0 ];then /usr/local/nginx/sbin/nginx sleep 2 if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then killall keepalived fi fi
-
赋予执行权限
chmod +x /etc/keepalived/nginx_check.sh
-
修改Master机器配置
- 修改keepalived的Master配置文件:
vi /etc/keepalived/keepalived.conf
-
删除里面所有内容,写上如下内容
! Configuration File for keepalived global_defs { router_id wolfcode ##路由器标志 } # 集群资源监控,组合track_script进行 vrrp_script check_haproxy { script "/etc/keepalived/nginx_check.sh" #检测 nginx 状态的脚本路径 interval 2 #检测时间间隔 weight -20 #条件成立 权重减20 } vrrp_instance PROXY { # 设置当前主机为主节点,如果是备用节点,则设置为BACKUP state MASTER # 指定HA监测网络接口,就是当前主机的网卡,用ifconfig查看当前网卡信息,来决定设置哪一个 interface ens32 # 虚拟路由标识,同一个VRRP实例要使用同一个标识,主备机,即n个主备生成一个虚拟IP,那么这n个机器要设置一样 virtual_router_id 80 # 因为当前环境中VRRP组播有问题,改为使用单播发送VRRP报文 如果VRRP组播没问题,以下这块的内容可以注释掉。 # 这个地方需要关注,之前未做此设置,结果主备节点互相不能发现,因此主备节点都升级成了MASTER,并且绑定了VIP # 主节点时,内容为:当前这台机器的IP地址 # unicast_src_ip 192.168.122.133 # 设置优先级,确保主节点的优先级高过备用节点 priority 100 # 用于设定主备节点间同步检查时间间隔 advert_int 2 # 设置主备节点间的通信验证类型及密码,同一个VRRP实例中需一致 authentication { auth_type PASS auth_pass wolfcode } # 集群资源监控,组合vrrp_script进行 track_script { check_haproxy } # 设置虚拟IP地址,当keepalived状态切换为MASTER时,此IP会自动添加到系统中 # 当状态切换到BACKUP时,此IP会自动从系统中删除 # 可以通过命令ip add查看切换后的状态 virtual_ipaddress { 192.168.122.110 #虚拟ip配置完之后就用它访问 } }
- 启动master:
# 启动keepalived systemctl start keepalived # 运行 systemctl status keepalived # 查看虚拟IP地址 ip addr # 停止keepalived systemctl stop keepalived
修改Slave配置
- 修改keepalived的Slave配置文件:
vi /etc/keepalived/keepalived.conf
-
删除里面所有内容,写上如下内容
! Configuration File for keepalived global_defs { router_id wolfcode ##路由器标志 } # 集群资源监控,组合track_script进行 vrrp_script check_haproxy { script "/etc/keepalived/nginx_check.sh" #检测 nginx 状态的脚本路径 interval 2 #检测时间间隔 weight -20 #条件成立 权重减20 } vrrp_instance PROXY { # 设置当前主机为主节点,如果是备用节点,则设置为BACKUP state BACKUP # 指定HA监测网络接口,可以用ifconfig查看来决定设置哪一个 interface ens32 # 虚拟路由标识,同一个VRRP实例要使用同一个标识,主备机 virtual_router_id 80 # 因为当前环境中VRRP组播有问题,改为使用单播发送VRRP报文 如果VRRP组播没问题,以下这块的内容可以注释掉。 # 这个地方需要关注,之前未做此设置,结果主备节点互相不能发现,因此主备节点都升级成了MASTER,并且绑定了VIP # 主节点时,内容为: # unicast_src_ip 192.168.122.134 # 设置优先级,确保主节点的优先级高过备用节点 priority 90 # 用于设定主备节点间同步检查时间间隔 advert_int 2 # 设置主备节点间的通信验证类型及密码,同一个VRRP实例中需一致 authentication { auth_type PASS auth_pass wolfcode } # 集群资源监控,组合vrrp_script进行 track_script { check_haproxy } # 设置虚拟IP地址,当keepalived状态切换为MASTER时,此IP会自动添加到系统中 # 当状态切换到BACKUP时,此IP会自动从系统中删除 # 可以通过命令ip add查看切换后的状态 virtual_ipaddress { 192.168.122.110 #虚拟ip配置完之后就用它访问 } }
- 启动slave(同master略)
map命令使用(后序补充)
map指令是Nginx的高级功能,只有在Nginx版本1.9.0及以上版本中才可用。
nginx根据cookie里的信息分流
$cookie_ :是关键字,后面拼接的可以是自定义变量,可以是nginx内置变量,作用就是从请求获取cookie的某个字段,如果id字段值为123,那么group值就是admin
map $cookie_id $group {
123 admin
234 aaa
default root
}
同理,$http_是获取请求头的关键字,后面拼接的可以是自定义变量,可以是nginx内置变量,作用就是从请求头获取某个字段
如果你想要基于自定义的请求头进行操作,你需要将$http_部分替换为你的自定义头部名称,例如$http_x_custom_header,其中x_custom_header是你的自定义头部名称。