Link Search Menu Expand Document

演进&洞察

现在经过几年的技术演进,我们不再自己造轮子自己写这个采集端,因为相对来讲不太稳健:

  • 容易崩,一旦崩了会带来各种问题,还得维护、排错,也不知道哪个地方出问题,说不定是语法,或者各种奇奇怪怪的场景。
  • 中间层不太稳健,量大的就出各种问题,取决于机器性能和日志处理的瓶颈。

最好的方式还是基于现成的采集来实现,选型中有Flume、Logstash,也有Filebeat这些,看了下对比:参考指南最终,因为分析工具是基于Golang的,而且我们整个工作台也是奔着云原生的方向去走,所以,我们在采集这端优先用Filebeat,主要洞察是:

  • 针对中小型的客户,比较好融合,基于Kafka实现,订阅消费的模式比较容易解耦。(正正合适,对业务0嵌入)
  • 针对中大型的客户,如日志量到PB级一天,这种基于Hadoop集群的模式,可以单独再聊,不在本文范畴里。(从画像来讲,这类客户极其罕见,真有,我们可以定制)
  • Kafka相对稳健成熟的基础设施,不需要过多对比,什么性能指标、各种推理,客户不用有过多的顾虑,怕用一个不成熟的第三方,导致各种问题,怕自研的采集器要么不维护,要么不稳定,中立挺好,kafka大家都熟,没有顾虑。
  • 兼容容器集群(K8S)的场景,在容器中基于Filebeat采集有天然优势,这个在后续融合HIDS(平台后续具备的能力)的时候,就更加简单容易,天然结合。

配置&解释

从docker-compose的配置文件上,就能看到这个采集的用法。

filebeat基础配置

filebeat.inputs:
- type: log
  enabled: true
  fields:
    source: nginx_access_log
  paths:
    - /var/log/nginx/access*.log
  json.keys_under_root: true
  json.overwrite_keys: true

output.kafka:
  hosts: ["kafka:9092"]
  topic: weblogs
  required_acks: 1

这端主要做的是:

  • 把Nginx日志采集到Kafka中,进行存储,用于Golang写的分析工具对日志数据进行分析。
  • 要把Nginx的日志基于Json方式格式化好放进去,好让工具解析。
  • hosts: [“kafka:9092”] 这个地方的「kafka」可以替换成kafka的域名、或者ID,如果有自建的就写自建的就行了,我这里写的是docker-compose里的服务名
  • topic: weblogs 这个「weblogs」可以替换成你想要的日志名称,我建议就用这个,因为默认就是分析Web日志。

Nginx基础配置

在nginx这一端,也要做些轻微改动,如果本身就是JSON格式,对一下配置就可以,主要看 log_formatlog_json这个部分,因为里面的字段都是对应的,如果已经有了Nginx的配置,就加一个这个就行。

这里我们自己用的是openresty,用原生的Nginx也可以的,不限制具体用哪个。

worker_processes  auto;
#error_log         "/opt/bitnami/nginx/logs/error.log";
pid               "/tmp/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" "$http_host" "$request_time" "$upstream_response_time" "$request_body"';
    #access_log    "/opt/bitnami/nginx/logs/access.log" main;
    log_format    log_json '{"@timestamp": "$time_local","request_body":"$request_body","remote_addr":"$remote_addr","http_host":"$http_host","request":"$request","status":"$status","body_bytes_sents":"$body_bytes_sent","req_time":"$request_time","http_user_agent":"$http_user_agent", "http_referer":"$http_referer", "request_method":"$request_method", "http_x_forwarded_for":"$http_x_forwarded_for"}';
    #access_log    "/usr/local/openresty/nginx/logs/access.log" log_json;
    add_header    X-Frame-Options SAMEORIGIN;

    client_body_temp_path  "/tmp/client_body" 1 2;
    proxy_temp_path        "/tmp/proxy" 1 2;
    fastcgi_temp_path      "/tmp/fastcgi" 1 2;
    scgi_temp_path         "/tmp/scgi" 1 2;
    uwsgi_temp_path        "/tmp/uwsgi" 1 2;
    client_body_buffer_size 1024k;
    fastcgi_buffers 32 16k;
    sendfile           on;
    gzip               on;
    gzip_http_version  1.0;
    gzip_comp_level    2;
    gzip_proxied       any;
    gzip_types         text/plain text/css application/javascript text/xml application/xml+rss;
    keepalive_timeout  65;
    client_max_body_size 80M;
    server_tokens off;

    #include  "/opt/bitnami/nginx/conf/server_blocks/*.conf";

    # HTTP Server
    server {
        lua_need_request_body on;
    	access_log    "/usr/local/openresty/nginx/logs/access.log" log_json;
        listen  8080;
        server_name  api.example.com;

        location / {
            proxy_pass "http://www.aidolphins.com";
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	    root html;
	    index index.html index.htm;
        }
    }
}