原创

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

一、前言

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

  1. 前端通过Http请求直接发送日志到后台微服务处理,就会额外增加微服务集群的压力。这种方式不可取。
  2. 前端利用中间件的SDK发送日志到中间件,比如上图的 rabbitmq,这会造成前端与中间件过于耦合,也会造成前端编码复杂度,也不可取。
  3. 设计一个基于Netty的后台服务来处理日志请求,这样做也是吃力不讨好,自己重新设计一个Netty日志服务器稳定性与性能上也不能一蹴而就。
  4. 最好的方式还是用nginx添加nginx-amqp模块作为日志服务器,前端通过http请求发送日志nginxnginx再转发到中间件,这样可以解决前 3 点的缺点,简单,稳定,性能高,易维护,耦合度低(换中间件直接换个模块就行,如中间件换kafka,直接添加一下ngx_kafka_module就行);当然也可以不用nginx来转发到中间件,nginx(需要添加lua模块form模块)直接记录日志到本地,通过flumelogstash来拉取就行。

二、下载

三、安装

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.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管理页面查看结果
  2. 发送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管理页面查看结果
正文到此结束
本文目录