vlambda博客
学习文章列表

利用nginx的nginx-amqp模块把前端的数据转发到rabbitmq

一、前言

随着企业对大数据越来越重视,日志埋点的地方越来越多,如:nginx服务器上的日志,微服务上的日志;特别是客户端上的日志处理越来越多。
对于nginx日志与微服务应用服务器上的业务日志,没什么好说的,直接用 flume或 logstash 等日志工具拉取即可。
对于处理客户端日志的方式就比较麻烦一些:

  1. 前端通过Http请求直接发送日志到后台微服务处理,就会额外增加微服务集群的压力。这种方式不可取。

  2. 前端利用中间件的SDK发送日志到中间件,比如上图的 rabbitmq,这会造成前端与中间件过于耦合,也会造成前端编码复杂度,也不可取。

  3. 设计一个基于Netty的后台服务来处理日志请求,这样做也是吃力不讨好,自己重新设计一个Netty日志服务器稳定性与性能上也不能一蹴而就。

  4. 最好的方式还是用nginx添加nginx-amqp模块作为日志服务器,前端通过http请求发送日志nginxnginx再转发到中间件,这样可以解决前 3 点的缺点,简单,稳定,性能高,易维护,耦合度低(换中间件直接换个模块就行,如中间件换kafka,直接添加一下ngx_kafka_module就行);当然也可以不用nginx来转发到中间件,nginx(需要添加lua模块form模块)直接记录日志到本地,通过flumelogstash来拉取就行。

二、下载

  • 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 7Docker

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

如图:

利用nginx的nginx-amqp模块把前端的数据转发到rabbitmq

3. nginx

解压压缩包: nginx-1.17.9.tar.gzngx_devel_kit-0.3.1.tar.gzform-input-nginx-module-0.12.tar.gznginx-amqp.ziprabbitmq-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
  • 安装nginxnginx 模块

    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
  1. 发送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.informationS

    1.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管理页面查看结果