Java进阶-Nginx进阶

Nginx的HTTPS支持配置

  1. SSL安全协议
    1. 传输层安全性协议,SSL,介于http与tcp/UDP之前的一层混合加密的协议,确保数据传输的安全性
    2. TLS是SSL后序的升级版

环境配置

  1. 让当前的nginx支持https,因为之前最开始安装nginx时,下载依赖模块没有下载openssl相关的依赖,因此当时编译的nginx也没有支持openssl
  2. 安装https支持的openssl
     yum install -y openssl openssl-devel
    
  3. 给源码添加https(openssl)模块
    1. 进入到之前解压的nginx-1.20.1目录下,查看一下有configure文件夹,执行下面命令

       ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
      
  4. 执行make,重新编译nginx, 注意: 不需要执行make install
  5. 把编译后的最新的可执行程序nginx替换旧的nginx
    1. cd到objs文件,可以看到编译的nginx
    2. 备份之前运行nginx

       cd /usr/local/nginx/sbin
       cp nginx nginx.old
      
    3. 将源码中重新编译的nginx替换掉/usr/local/nginx/sbin下的nginx

       //此时就在/usr/local/nginx/sbin目录下,执行下面命令
       cp  -f /usr/local/src/nginx-1.20.1/objs/nginx ./
      
  6. 向Master发送USER2信号

     ps -ef |grep nginx #查看nginx的进程id
     //1355为nginx的进程id
     kill -s SIGUSR2  1355
    
    1. 此时通过ps -ef |gep nginx会发现会重新启动一个nginx进程,一共有2个,一个是旧的,一个是新的
    2. 接下来需要用新的提供服务,旧的下线
  7. 向老的Master进程发送QUIT信号,关闭老的进程

     kill -QUIT 1355
    
  8. 如果新的nginx启动报错,还可以回滚:向老的Master进程发送HUP信号, 向新的Master进程发送QUIT信号

     kill -HUP 1355
    

SSL证书

  1. 既然当前nginx已经支持https了,那就需要首先拿到证书,然后在nginx上配置证书,这样,才能使用

免费申请证书,然后nginx配置证书

  1. 申请证书:
    1. 前提条件是必须要有域名,比如:coderzhong.online
    2. 添加依赖库文件: yum install epel-release -y
    3. 安装用于免费申请证书的工具包 yum install python2-certbot-nginx
    4. 开始申请免费证书: certbot --nginx --nginx-server-root=/usr/local/nginx/conf -d coderzhong.online
  2. 在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配置证书

  1. 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
    
    1. 会在/usr/local/nginx/sbin/目录下生成:server.key、server.csr、server_nopass.key、server.crt几个文件
  2. 在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;
         }
     }
    
  3. 重新加载nginx :sbin/nginx -s reload
  4. 公钥在证书中,当浏览器访问时,会将证书下载到浏览器
    1. 将浏览器访问地址修改为https,可以直接访问,然后会提示危险,是否继续,点击继续即可
    2. 提示危险是有其他机构会检测你的证书,由于是自己创建的,所以会提示不安全
  5. HTTPS通信流程

    图1

Nginx跨域解决方案

  1. 什么是跨域问题
    1. 请求的URI组成:http://www.52it.com:80/subject/java/getInfo?id=100
      1. http: 请求的协议
      2. www.520it.com: 域名(可以是IP地址)
      3. 80端口: 没有写端口, 对于http协议默认的是80端口
      4. /subject/java/getInfo: 资源在服务端的路径
      5. id=100 请求参数
    2. 当一个请求(异步请求)url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
  2. 跨域的具体配置
    1. 在请求的目标资源上加上对应的请求的, 允许资源的跨域访问

       add_header Access-Control-Allow-Origin *;
       add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
       add_header Access-Control-Allow-Headers '*';
      
      1. ccess-Control-Allow-Origin: 设置请求可以从哪些地址发送过来, * 代表所有的地址
      2. Access-Control-Allow-Methods: 设置可以跨域请求的方法, OPTIONS 是一个预检方法
      3. Access-Control-Allow-Headers: 设置允许的请求头信息
    2. 在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;
       }
      

缓存的开启

  1. 当发送到tomcat的请求响应数据非常少时,可以将数据直接缓存在nginx,提高效率
  2. 有时候为了减轻后台的请求压力, 会把对应的请求结果缓存在nginx服务器, 到时候直接从nginx服务器获取对应的缓存结果即可
    1. 官方文档: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进制  一个冒号 表示的是有两级目录
    
  3. 配置

     # 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请求防盗链

  1. 什么是资源盗链
    1. 资源盗链是指内容不在自己服务器上,而通过技术手段,绕过别人的限制,将别人的内容,比如热门的图片放到自己页面上,展示给用户,以此来盗取别人网站的流量,即蹭流量。
  2. 情景:为了防止别人爬取自己的网站数据,可以进行请求防盗链配置,相当于添加白名单
    1. 当浏览器向web服务器发送请求的时候,一般都会带上Referer字段,来告诉浏览器该网页是从哪个页面链接过来的;
    2. 后台服务器根据获取到的这个Referer信息,从而判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回403(服务端拒绝访问)的状态信息)
  3. 使用nginx的referer模块
  4. 指令

     valid_referers 
     none: 如果Header中的Referer为空,允许访问;
     block: 允许referer头部没有对应的值进行访问,在Header中的Referer不为空,但是该值被防火墙或代理进行伪装过,如不带"http://" 、"https://"等协议头的资源允许访问;
     server_names: 允许匹配的域名进行访问 对于域名可以使用前缀+通配符(*) 进行匹配
     referer_hash_bucket_size
     referer_hash_max_size
        
     //变量,用来判断是否能够访问
     $invalid_referer: 
     允许访问, 变量值为空
     不允许访问, 变量值为1 
    
  5. 比如:在location中配置

     //添加这个之后,浏览器的请求头会自动添加referer参数
     valid_referers none blocked server_name www.crm.com;
     if($invalid_referer) {
         return 443;
     }
    

Nginx限流方案

  1. 为何要对nginx限流?
    1. nginx的最大并发5w,而tomcat的最大并发300每台,那么如果客户端请求量非常多的情况下,nginx直接将请求转发给tomcat就会造成 服务器的雪崩效应
    2. 因此需要对nginx进行限流,保证能够平稳的合理的请求量转发给tomcat
    3. 也就是说tomcat不能承受大于其最大并发的请求,否则就会挂掉,因此请求到达tomcat之前可以用nginx做限流控制
  2. 常见的限流策略
    1. 计数器算法:在指定的时间内,放行指定数量的请求
    2. 令牌桶
    3. 漏桶算法
  3. Nginx限流实现
    1. 限制并发连接数(计数器算法)
      1. 使用limit_conn模块

         #定义共享内存,key 通常取客户端ip
         limit_conn_zone key  zone=name:size  http
         #限制并发连接数
         limit_conn  zone  number;  http|server|location
        
      2. 配置

         //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; 
         }
        
    2. 限制访问频率(漏桶算法)
      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请求立即处理
        
      2. 配置

         limit_req_zone $binary_remote_addr zone=one:10m rate=20r/m;
         location / {
           limit_req zone=one; 
         }
        

Http请求的处理流程

  1. Nginx请求处理流程、Nginx内部处理流程图

图1

搭建高可用环境

  1. 我们是通过Nginx进行反向代理,如果Nginx关了的话就没有其他服务支撑.所以我们需要来实现Nginx的高可用,高可用就是我们一台机器挂了可以切换到另外一台机器
  2. 我们使用Nginx+keepalived搭建高可用环境
  3. 实现场景
    1. 假设部署了2台Nginx(master、backup),一台挂了能自动访问另一台
    2. 客户端只需要连接一个虚拟的IP地址,正常情况这个虚拟的地址映射到master,一旦master挂了,能自动指向backup
  4. keepalived实现的功能
    1. 保证生成一个vip地址(虚拟ip),并且可以vip可以自动切换
    2. 定时检测对应的nginx服务状态,对于master的状态信息要即时通知backup

Keepalived简介

  1. 首先介绍一下Keepalived,它是一个高性能的服务器高可用或热备解决方案,Keepalived主要防止服务器单点故障的问题,可以通过其与Nginx的配合实现web服务器端的高可用.
  2. Keepalived以VRRP协议为实现基础,使用VRRP协议来实现高可用性(HA).VRRP(Virtual Router Redundacy Protocol)协议用于实现路由器冗余的协议,VRRP协议将两台或多台路由器设备虚拟成一个设备,向外提供虚拟路由IP(一个或多个),如下图所示:

    图1

  3. 安装keepalived(master、Slave都要安装
    1. 第一步:安装keepalived依赖的包

       yum install gcc openssl-devel libnl3-devel popt-devel iptables-devel libnfnetlink-devel   -y
      
    2. 第二步:编译安装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 
      
    3. 第三步:将 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/
      
    4. 第四步:编写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  
      
    5. 赋予执行权限

       chmod +x /etc/keepalived/nginx_check.sh 
      

修改Master机器配置

  1. 修改keepalived的Master配置文件:vi /etc/keepalived/keepalived.conf
  2. 删除里面所有内容,写上如下内容

     ! 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配置完之后就用它访问    
     	}    
     }  
    
  3. 启动master:
     # 启动keepalived
     systemctl start keepalived
     # 运行
     systemctl status keepalived
     # 查看虚拟IP地址
     ip addr
     # 停止keepalived
     systemctl stop keepalived
    

修改Slave配置

  1. 修改keepalived的Slave配置文件:vi /etc/keepalived/keepalived.conf
  2. 删除里面所有内容,写上如下内容

     ! 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配置完之后就用它访问    
     	}    
     }
    
  3. 启动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是你的自定义头部名称。
Table of Contents