如何解决生产诡异问题之——Nginx流量拷贝

我去,生产出bug了,测试环境还重现不了。

铃铃铃,产品来电:喂,喂,小墨,生产怎么出问题了。

铃铃铃,老板来电:咋回事啊,这东西怎么用不了了,make it work,还想不想干了。

如何解决生产诡异问题之——Nginx流量拷贝_第1张图片


为啥要用Nginx流量拷贝

在日常开发中,我们经常碰到很多“测试环境明明没问题,为什么到了生产就有问题”的情况。

线上出了问题,再怎么心大,终究还是会有一丢丢慌的。

但是这种情况,又是真的捉急,因为这种问题大部分不是必现问题,很多时候都跟线上的请求量(流量)有关,大流量的请求造成多线程并发,连接池异常,内存泄露等问题。

当然,解决这些问题的方式有很多种:

  • 例如最常用的暂时打开线上debug日志的开关;
  • 对用户访问链进行链式日志分析;
  • 利用arthas(推荐使用)进行线上跟踪,远程断点等;
  • 其它等等办法(出了问题,只要能知道是什么问题,总是有不同的办法解决的)

但是今天不具体介绍这些方法的具体使用了,就讲一个很炫酷的解决方式。

当然这种方式是大杀器,一般情况还是少用(杀鸡焉用牛刀),但是一旦你碰到很诡异,很坑爹的问题的时候,那么同学,推荐你使用接下来的这种解决方式;Nginx流量拷贝

这种查找分析问题的思路就是:

既然是因为环境,流量等引起的问题,那么我弄一个和你近乎一样(不要太绝对^-^)的环境,看看究竟是为啥。

另外,流量拷贝可以做很多事情,例如:

  •  本地断点模拟及排查生产问题;
  •  用真实流量请求系统,不需要手动造数据,不影响线上正常访问;
  •  灰度测试未上线的功能对系统的影响;
  •  放大流量,进行压测;
  •  对请求日志进行安全分析;
  •  等等...等等

这里,我们只是用来解决生产的诡异问题;但是也可以在日常开发中,把这个炫酷的功能利用起来的。

如何通过nginx进行流量拷贝

试想一哈,如果是要让你自己去弄一下流量拷贝,是不是想想就头大,各种网络配置什么鬼的。

不过还好我们有nginx(疯狂给nginx打call),nginx提供了非常nice的一个模块,ngx_http_mirror_module,只要我们安装了这个模块,我们就可以稍微改改config,然后重启一波就可以。

niinx支持ngx_http_mirror_module的最低版本:1.13.4

1.安装nginx

nginx的安装可以参考一下我写的简简单单的安装一下nginx 。

nginx 1.13.4及后续版本内置ngx_http_mirror_module模块,提供流量镜像(复制)的功能,默认开启。

nginx版本

2.配置config

只需要在configserver中,在location里面添加mirror及对应的转发地址即可。

mirror /mirror/; 

location /mirror/ {                  # 镜像请求 
	internal; #指定此location只能被“内部的”请求调用,外部的调用请求会返回”Not found” (404)
	proxy_pass http://192.168.1.145:8082/;
}

另外,可以禁止除GET之外的请求进行复制。

# 判断请求方法,不是GET返回403
if ($request_method != GET) {
    return 403;
}

如果是直接进行internal转发的是没有access.log日志的,如果想要记录流量拷贝后的日志,可以通过转发到内部端口,再监听内部端口的方式进行日志记录。

server {
    
    ...
    
    location /mirror1 {                  # 镜像请求
		proxy_set_header Host $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://localhost:10901$request_uri; # 内部端口转发可以在对应端口的access_log查看访问日志
	}
	
	...
    
}


server {
	# server没法设置为内部
	listen 10901;
	location / {
		access_log log/access2.log;
		proxy_pass http://192.168.1.85:8082/;
	}
}

3.测试

利用postman直接进行接口调用,查看对应的access.log日志及对应的服务端,可以发现,流量拷贝成功。

如何解决生产诡异问题之——Nginx流量拷贝_第2张图片

4.完整配置

server {
    listen       8083;
    server_name  localhost;


    #charset koi8-r;

    #access_log  logs/host.access.log  main;
    
    location /zz {

			mirror /mirror/;                 # 配置镜像请求
			mirror /mirror/;                 # 配置多个镜像请求,可进行流量放大
			mirror /mirror1;                 # 配置镜像请求
			proxy_pass http://192.168.1.127:8082/zz;
			proxy_set_header Host $http_host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header REMOTE-HOST $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	}
		
	location /mirror/ {                  # 镜像请求 
	
	    # 判断请求方法,不是GET返回403
        if ($request_method != GET) {
            return 403;
        }
	
		internal; #指定此location只能被“内部的”请求调用,外部的调用请求会返回”Not found” (404)
		proxy_pass http://192.168.1.145:8082/;
	}
	location /mirror1 {                  # 镜像请求
	
	    # 判断请求方法,不是GET返回403
        if ($request_method != GET) {
            return 403;
        }
	
		proxy_set_header Host $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://localhost:10901$request_uri; # 内部端口转发可以在对应端口的access_log查看访问日志
	}
        
}
	
server {
	# server没法设置为内部
	listen 10901;
	location / {
		access_log log/access2.log;
		proxy_pass http://192.168.1.85:8082/;
	}
}

需要注意的地方

虽然nginx这个功能很强,但是仍然还有几个需要注意的地方。

  • 最需要注意的,就是风险管控,这个东西需要严格控制,防止泄露泄露生产真实数据
  • 经过测试,复制多份流量到后端和复制流量到有故障的后端,对原始请求都没有问题,但是在复制到 响应缓慢的后端 时,会使原始请求阻塞,所以,还是要合理使用。

关于nginx流量复制的进一步研究和测试,各位可以参考一下这位的Nginx 流量镜像使用技巧,里面的总结和测试很到位。

你可能感兴趣的:(Java,nginx,java,nginx)