在需要真实的流量做旁路测试的时候,我们就可以使用 Nginx 来做流量的拷贝
1 Nginx Mirror 模块
Nginx 自1.13.4 版本开始,自带一个 ngx_http_mirror_module,使用起来非常简单,只要在需要 mirror 的 location 处添加 mirror 关键字就行
copy
1 2 3 4 5 6 7 8 9 |
location / { mirror /mirror; proxy_pass http://backend; } location = /mirror { internal; proxy_pass http://test_backend$request_uri; } |
copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
http { upstream webserver1 { server 127.0.0.1:8881; } upstream webserver2 { server 127.0.0.1:8882; } server { listen 8080; server_name localhost; location / { root html; index index.html index.htm; } location /test { mirror /mirror; proxy_pass http://webserver1/index; } location /mirror { internal; proxy_pass http://webserver2/index; } } } |
2 lua 脚本分发请求
但是 Nginx 版本过低时,该如何做呢?
我们可以使用集成来 lua 的 OpenResty,使用 lua 脚本处理 web 请求完成流量的拷贝
我们直接看例子:
Nginx.conf
copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
user root; worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { upstream product { server 127.0.0.1:8881; } upstream test { server 127.0.0.1:8882; } server { listen 8080; server_name 172.27.133.28; #lua_code_cache off; # 外部应用的请求地址,通过 lua 脚本分发到新的 product 和 test 地址 location /predict/fake { client_body_buffer_size 2m; set $switch "on"; #开启或关闭copy功能 content_by_lua_file /tmp/copy_req.lua; } # lua 脚本分发到 product,并且对 url 重写后,反向代理到 product 的 server location ~* ^/product { log_subrequest on; rewrite ^/product(.*)$ /predict break; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://product; access_log logs/product-upstream.log; } # lua 脚本分发到 test,并且对 url 重写后,反向代理到 test 的 server location ~* ^/test { log_subrequest on; rewrite ^/test(.*)$ /predict break; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://test; access_log logs/test-upstream.log; } } } |
copy_req.lua
copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
local res1,res2,action action = ngx.var.request_method if action == "POST" then arry = {method = ngx.HTTP_POST,body = ngx.req.read_body()} else arry = {method = ngx.HTTP_GET} end if ngx.var.switch == "on" then res1,res2 = ngx.location.capture_multi { -- 分发请求的核心函数 { "/product" .. ngx.var.request_uri,arry},{ "/test" .. ngx.var.request_uri,} else res1,res2 = ngx.location.capture_multi { { "/product" .. ngx.var.request_uri,} end if res1.status == ngx.HTTP_OK then local header_list = {"Content-Length","Content-Type","content-encoding","Accept-Ranges"} for _,i in ipairs(header_list) do if res1.header[i] then ngx.header[i] = res1.header[i] end end ngx.say(res1.body) else ngx.status = ngx.HTTP_NOT_FOUND end |
我们来捋一捋这个流程:
背景:首先我们向外部注册的地址的是 /predict/fake,我们实际 web server 的地址是 /predict,然后一个生产的 upstream (product)一个测试用的 upstream(test),ok,这时候一个 /predict/fake 请求过来了发生了什么呢
- 首先 /predict/fake 匹配到了 location,然后经过 lua 脚本分发请求,产生了两个子请求 /product/predict/fake 和 /test/predict/fake
- /product/predict/fake 匹配到新的 location,并且对这个 url 进行了 rewrite,变成了真实的后端请求地址 /predict,并且反向代理到 product 这个 upstream 下的 server,同理对 /test/predict/fake 也是一样的
- 两个子请求都有返回,但是在 lua 脚本中,只有 product 对应的请求被最终返回给了前端
需要注意的点:
反向代理时 rewrite 后的 url 会覆盖 proxy_pass 的 url
参考:
原文地址:https://blog.csdn.net/thlzjfefe" target="_blank" rel="noopener" title="thlzjfefe">thlzjfefe</a> <img class="article-time-img article-heard-img" src="https://csdnimg.cn/release/blo
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。