利用nginx的nginx-amqp模块把前端的数据转发到rabbitmq
一、前言
随着企业对大数据越来越重视,
日志埋点
的地方越来越多,如:nginx
服务器上的日志,微服务
上的日志;特别是客户端
上的日志处理越来越多。
对于nginx日志
与微服务应用服务器上的业务日志
,没什么好说的,直接用flume
或logstash
等日志工具拉取即可。
对于处理客户端日志的方式就比较麻烦一些:
前端通过
Http请求直接发送日志
到后台微服务处理,就会额外增加微服务集群的压力。这种方式不可取。前端
利用中间件的SDK发送日志
到中间件,比如上图的rabbitmq
,这会造成前端与中间件过于耦合,也会造成前端编码复杂度,也不可取。设计一个基于
Netty
的后台服务来处理日志请求,这样做也是吃力不讨好,自己重新设计一个Netty
日志服务器稳定性与性能上也不能一蹴而就。最好的方式还是用
nginx
添加nginx-amqp模块
作为日志服务器,前端通过http请求发送日志
到nginx
,nginx
再转发到中间件,这样可以解决前 3 点的缺点
,简单,稳定,性能高,易维护,耦合度低(换中间件直接换个模块就行,如中间件换kafka
,直接添加一下ngx_kafka_module
就行);当然也可以不用nginx
来转发到中间件,nginx
(需要添加lua模块
或form模块
)直接记录日志到本地,通过flume
或logstash
来拉取就行。
二、下载
nginx: https://github.com/nginx/nginx/archive/release-1.17.9.tar.gz
nginx form 模块: https://github.com/calio/form-input-nginx-module/archive/v0.12.tar.gz
依赖: ngx devel kit 模块: https://github.com/vision5/ngx_devel_kit/archive/v0.3.1.tar.gz
nginx amqp 模块 https://github.com/JamesKotov/nginx-amqp.git
依赖: rabbitmq-c https://github.com/alanxz/rabbitmq-c/archive/v0.10.0.tar.gz
三、安装
1. 系统环境
Centos 7
, Docker
2. rabbitmq
docker pull rabbitmq:3.6.11-management
docker run -it --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
浏览器访问: http://192.168.88.150:15672
添加
:
类别 | 名称 | routingKey |
---|---|---|
exchange | rumExchange | - |
queue | rumQueue | defaultRoutingKey |
queue | test | log |
如图:
3. nginx
解压压缩包: nginx-1.17.9.tar.gz
、ngx_devel_kit-0.3.1.tar.gz
、form-input-nginx-module-0.12.tar.gz
、nginx-amqp.zip
、rabbitmq-c-0.10.0.tar.gz
安装
rabbitmq-c
yum install -y cmaker gcc clang openssl openssl-devel
cd rabbitmq-c
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
cmake --build . --target install安装
nginx
及nginx 模块
cd nignx-1.17.9
# /usr/local/lib64 为 rabbitmq-c 库目录
./configure --prefix=/usr/local/nginx --with-ld-opt="-Wl,-rpath,/usr/local/lib64" --with-http_ssl_module --with-http_stub_status_module --add-module=/home/soft/ngx_devel_kit-0.3.1 --add-module=/home/soft/form-input-nginx-module-0.12 --add-module=/home/soft/amqp/nginx-amqp
make && make install注意点:
ldd /usr/local/nginx/sbin/nginx
可以查看nginx是否正确安装,如果库出现 not found,
可以在上面./configure
命令参数中--with-ld-opt="-Wl,-rpath,/usr/local/lib64"
添加库的路径,用逗号
分隔。ldd /usr/local/nginx/sbin/nginx
linux-vdso.so.1 => (0x00007ffd871b1000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fdd3e3b5000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fdd3e199000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fdd3df62000)
librabbitmq.so.4 => /usr/local/lib64/librabbitmq.so.4 (0x00007fdd3dd49000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fdd3dae7000)
libssl.so.10 => /lib64/libssl.so.10 (0x00007fdd3d875000)
libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007fdd3d412000)
libz.so.1 => /lib64/libz.so.1 (0x00007fdd3d1fc000)
libc.so.6 => /lib64/libc.so.6 (0x00007fdd3ce2e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdd3e5b9000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007fdd3cc2b000)
librt.so.1 => /lib64/librt.so.1 (0x00007fdd3ca23000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fdd3c7d6000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fdd3c4ed000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fdd3c2e9000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fdd3c0b6000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fdd3bea6000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fdd3bca2000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fdd3ba88000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fdd3b861000)
四、配置 nginx.conf
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid /usr/local/nginx/logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
#log_format dm ' msg::"$request_body"##ua::$http_user_agent##referer::$http_referer##clientIP::$remote_addr##createdAt::$time_iso8601" ';
server {
listen 80;
server_name localhost;
location /amqp/test {
proxy_set_header X-Real-IP $remote_addr;
amqp_ip "localhost";
amqp_port 5672;
amqp_exchange "rumExchange";
# 默认 routing_key 为 defaultRoutingKey
amqp_routing_key "defaultRoutingKey";
amqp_user "guest";
amqp_password "guest";
# 获取GET请求传递的参数
amqp_publish "rum::$arg_rum##ua::$http_user_agent##referer::$http_referer##clientIP::$remote_addr##createdAt::$time_iso8601";
# 设置为 1 开启 debug 模式会返回状态码200和处理的数据,设置为 0 关闭 debug 模式, 只返回状态码 204
amqp_debug 1;
keepalive_timeout 0;
}
location /amqp/log {
#设定form 提交的参数变量
set_form_input $body_msg rum;
proxy_set_header X-Real-IP $remote_addr;
amqp_ip "localhost";
amqp_port 5672;
amqp_exchange "rumExchange";
amqp_routing_key "log";
amqp_user "guest";
amqp_password "guest";
# 获取POST请求, request_body中传递的参数
amqp_publish "msg::$body_msg##ua::$http_user_agent##referer::$http_referer##clientIP::$remote_addr##createdAt::$time_iso8601";
# 设置为 1 开启 debug 模式会返回状态码200和处理的数据,设置为 0 关闭 debug 模式, 只返回状态码 204
amqp_debug 1;
keepalive_timeout 0;
}
#error_page 404 /404.html;
#
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
五、测试
cd /usr/local/nginx
sbin/nginx -c conf/nginx.conf
发送
POST
请求,通过请求体传送数据:nginx-amqp
curl http://192.168.88.150/amqp/log -d "rum=nginx-amqp"
rumExchange::log
messagebody: msg::sdfdf##ua::PostmanRuntime/7.26.3##referer::##clientIP::192.168.88.1##createdAt::2020-09-05T15:06:58+08:00
NO ERROR init=0
ntonuk.informationS1.1 rabbitmq管理页面
查看结果
发送GET
请求,通过请求头传送数据:rabbitmq
curl http://192.168.88.150/amqp/test?rum=rabbitmq
rumExchange::defaultRoutingKey
messagebody: rum::rabbitmq##ua::PostmanRuntime/7.26.3##referer::##clientIP::192.168.88.1##createdAt::2020-09-05T23:05:28+08:00
NO ERROR init=1
onS
2.1 rabbitmq管理页面查看结果