nginx流量复制与放大
2022-08-15 18:44 曾左 阅读(820) 评论(0) 编辑 收藏 举报一、需求
1. 功能方面
在不影响真实业务前提下,能满足:
(1)流量复制,用于线故障分析、系统迁移评估等
(2)流量放大,通过多倍复制,实现放大流量,用于性能压测
2. 配置方面
(1)支持或禁止 post 请求复制
(2)记录镜像请求的访问日志
二、解决方案
nginx 1.13.4 版本,内置 ngx_http_mirror_module 模块,能满足上述需求
1. ngx_http_mirror_module 模块特性
(1)相比 tcp-copy 的优势:无需录制流量,实时可用,配置相当简单
(2)源站请求,直接原路返回
(3)复制请求不影响源站请求,源站 nginx-server 将流量复制到 mirror 站后,两者不再有任何交集
三、配置方法
下面配置在 nginx 1.14.1 验证通过,具体配置说明,请看注释信息
1. 复制请求
server {
listen 80;
server_name web1.www.com;
# 源站配置
location / {
access_log /data/nginx/1.14.1/logs/web1/access.log accesslog;
mirror /mirror;
mirror_request_body on;# Indicates whether the client request body is mirrored. default value is on.
proxy_pass http://web1.upstream.name;
}
# 镜像站点配置
location /mirror {
internal; # 内部配置
proxy_pass http://mirror.web1.upstream.name$request_uri;
proxy_pass_request_body on; # Indicates whether the original request body is passed to the proxied server. default value is on
proxy_set_header X-Original-URI $request_uri; # 使用真实的 uri 重置 uri
}
}
2. 不允许复制 post 请求
默认支持 post 请求,禁止需要将 mirror_request_body 修改为 off,并判断$request_method
server {
listen 80;
server_name web1.www.com;
# 源站配置
location / {
access_log /data/nginx/1.14.1/logs/web1/access.log accesslog;
mirror /mirror;
mirror_request_body off;# Indicates whether the client request body is mirrored. default value is on.
proxy_pass http://web1.upstream.name;
}
# 镜像站点配置
location /mirror {
# 判断请求方法,不是 GET 返回 403
if ($request_method != GET) {
return 403;
}
internal; # 内部配置
proxy_pass http://mirror.web1.upstream.name$request_uri;
proxy_pass_request_body off; # Indicates whether the original request body is passed to the proxied server. default value is on
proxy_set_header Content-Length ""; # mirror_request_body/proxy_pass_request_body 都设置为 off,则 Conten-length 需要设置为"",否则有坑
proxy_set_header X-Original-URI $request_uri; # 使用真实的 uri 重置 uri
}
}
3. 流量放大
配置多份 mirror
server {
listen 80;
server_name web1.www.com;
# 源站配置
location / {
access_log /data/nginx/1.14.1/logs/web1/access.log accesslog;
mirror /mirror;
# 多加一份 mirror,流量放大一倍
mirror /mirror;
mirror_request_body on;# Indicates whether the client request body is mirrored. default value is on.
proxy_pass http://web1.upstream.name;
}
# 镜像站点配置
location /mirror {
internal; # 内部配置
proxy_pass http://mirror.web1.upstream.name$request_uri;
proxy_pass_request_body on; # Indicates whether the original request body is passed to the proxied server. default value is on
proxy_set_header X-Original-URI $request_uri; # 使用真实的 uri 重置 uri
}
}
4. 添加 mirror 日志
mirror 中不支持配置 access_log,解决方法:mirror-location 跳转到 server,在 server 中配置 accesslog.
server {
listen 80;
server_name web1.www.com;
# 源站配置
location / {
access_log /data/nginx/1.14.1/logs/web1/access.log accesslog;
mirror /mirror;
mirror_request_body off;# Indicates whether the client request body is mirrored. default value is on.
proxy_pass http://web1.upstream.name;
}
# 镜像站点配置
location /mirror {
internal; # 内部配置
# 跳转到下面的内部 server
proxy_pass http://127.0.0.1:10901$request_uri;
proxy_set_header X-Original-URI $request_uri; # 使用真实的 uri 重置 uri
}
}
server {
# server 没法设置为内部
listen 127.0.0.1:10901;
location / {
access_log /data/nginx/1.14.1/logs/web1/access.log accesslog;
proxy_pass http://mirror.web1.upstream.name;
}
}
四、性能影响评估
测试前提:使用 jemeter,在相同环境,使用 30 个并发,各请求 3000 次 get 或 post 方法,参数一样,一组为有 mirror 配置,另一组为没 mirror 配置。
测试结果:mirror 性能损失在 5%以内,具体如下:
五、遇到问题
1. 镜像配置错误确时,无日志
镜像配置不正确,导致复制操作没正常执行,但是 nginx 没有相应的错误日志,严重影响调试。建议配置镜像日志,配置方法如 4. 添加 mirror 日志
2. mirror_request_body/proxy_pass_request_body 与 Content-Length 需配置一致
如果 mirror_request_body 或者 proxy_pass_request_body 设置为 off,则 Content-Length 必须设置为""。因为 nginx/tomcat 处理 post 请求时,会根据 Content-Length 获取 request_body。如果 Content-Length 不为空,mirror_request_body、proxy_pass_request_body 设置为 off ,导致提交内容为空,但是nginx/tomcat 会以为 post 有内容,实际上 request_body 没有内容。此时 nginx 会报 upstream 请求超时,tomcat 会报如下错误:
"2018-11-08T17:26:36.803+08:00" "331632b86ec64b829672066a96fc6324" "department" "group" "project_name" "hostname" "127.0.0.1" "" "/post" "p=11" "-" "PostmanRuntime/7.1.1" "ERROR" "xxx.GlobalControllerAdvice" "operateExp" "-" "26" "xxxx.GlobalControllerAdvice" "unknown" "org.springframework.http.converter.HttpMessageNotReadableException" "I/O error while reading input message; nested exception is java.net.SocketTimeoutException" "GlobalControllerAdvice 中捕获全局异常" "org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.net.SocketTimeoutException
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:229)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:150)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:128)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)