Logstash-2.2.2+Kibana-4.5.0+Elasticsearch-2.3.1+Mac10.10.3收集、监控Nginx日志最佳实践

Logstash-2.2.2+Kibana-4.5.0+Elasticsearch-2.3.1+Mac10.10.3收集、监控Nginx日志最佳实践

目录

基础知识

介绍

Logstash、Kibana、Elasticsearch分别是什么?

Logstash
  简单来说,Logstash一个完全开源的工具,可以进行数据收集、分析,并将其存储供以后使用。
  虽然网上有人拿FlumnKafka做比较,但个人觉得Logstash反而和Flumn比较像,都是收集、处理数据的。如果最终你的数据流向是Elasticsearch,那么使用Logstash是最合适不过的,因为他们版本的升级非常接近。

Kibana
  Kibana是一个基于浏览器页面的Elasticsearch前端展示工具。Kibana全部使用HTML语言和Javascript编写的。

Elasticsearch
  Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎。它能帮助你搜索、分析和浏览数据。无论你是需要全文搜索、结构化数据的实时统计以及分析,Elasticsearch都可以完成。
  Elasticsearch并不只是面向大型企业的,它还帮助了很多类似 DataDog 以及 Klout 的创业公司进行了功能的扩展。Elasticsearch 可以运行在你的笔记本上,也可以部署到成千上万的服务器上,处理PB级别的数据。
  

安装

下载地址
* Logstash下载地址

https://download.elastic.co/logstash/logstash/logstash-2.3.1.zip

  • Kibana下载地址

https://www.elastic.co/downloads/kibana

  • Kibana MAC版本下载地址(本文也主要在Mac上做演示)

https://download.elastic.co/kibana/kibana/kibana-4.5.0-darwin-x64.tar.gz

  • Elasticsearch下载地址

https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/zip/elasticsearch/2.3.1/elasticsearch-2.3.1.zip

安装
  上面这些包,你可能更偏向使用 rpm,dpkg 等软件包管理工具来安装,可以自行在官网下载,如果要在老的系统上安装,那就需要下载源码自己编译了

➜ /Users/lion/tar >unzip logstash-2.2.2.zip
➜ /Users/lion/tar >tar -xzvf kibana-4.5.0-darwin-x64.tar.gz
➜ /Users/lion/tar >unzip elasticsearch-2.3.1.zip

  很简单吧,解压一下就安装好了。

  为了便于后面看到Elasticsearch导入的效果,可以安装ElasticSearch Head插件

➜ /Users/lion/tar/elasticsearch-2.3.1 >cd bin
➜ /Users/lion/tar/elasticsearch-2.3.1/bin >./plugin install mobz/elasticsearch-head

  安装以后,在浏览器中输入http://localhost:9200/_plugin/head/可以查看效果

运行

  • Logstash的运行方式

运行后,输入『Hello idoall.org』可以看到效果

➜ /Users/lion/tar/logstash-2.2.2 >bin/logstash -e 'input{stdin{}}output{stdout{codec=>rubydebug}}'
Settings: Default pipeline workers: 8
Logstash startup completed
Hello idoall.org
{
       "message" => "Hello idoall.org",
      "@version" => "1",
    "@timestamp" => "2016-03-28T06:38:13.269Z",
          "host" => "liondeMacBook-Pro.local"
}
  • Elasticsearch的运行方式
➜ /Users/lion/tar/elasticsearch-2.3.1 >bin/elasticsearch
[2016-04-09 13:59:19,105][INFO ][node                     ] [Executioner] version[2.3.1], pid[61836], build[bd98092/2016-04-04T12:25:05Z]
[2016-04-09 13:59:19,106][INFO ][node                     ] [Executioner] initializing ...
[2016-04-09 13:59:19,668][INFO ][plugins                  ] [Executioner] modules [reindex, lang-expression, lang-groovy], plugins [head], sites [head]
[2016-04-09 13:59:19,687][INFO ][env                      ] [Executioner] using [1] data paths, mounts [[/ (/dev/disk1)]], net usable_space [141.6gb], net total_space [429.2gb], spins? [unknown], types [hfs]
[2016-04-09 13:59:19,687][INFO ][env                      ] [Executioner] heap size [989.8mb], compressed ordinary object pointers [true]
[2016-04-09 13:59:19,688][WARN ][env                      ] [Executioner] max file descriptors [10240] for elasticsearch process likely too low, consider increasing to at least [65536]
[2016-04-09 13:59:21,139][INFO ][node                     ] [Executioner] initialized
[2016-04-09 13:59:21,139][INFO ][node                     ] [Executioner] starting ...
[2016-04-09 13:59:21,205][INFO ][transport                ] [Executioner] publish_address {127.0.0.1:9300}, bound_addresses {[fe80::1]:9300}, {[::1]:9300}, {127.0.0.1:9300}
[2016-04-09 13:59:21,209][INFO ][discovery                ] [Executioner] elasticsearch/hg1GWa2rT1arE1r0bPYvXQ
[2016-04-09 13:59:24,245][INFO ][cluster.service          ] [Executioner] new_master {Executioner}{hg1GWa2rT1arE1r0bPYvXQ}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
[2016-04-09 13:59:24,257][INFO ][http                     ] [Executioner] publish_address {127.0.0.1:9200}, bound_addresses {[fe80::1]:9200}, {[::1]:9200}, {127.0.0.1:9200}
[2016-04-09 13:59:24,257][INFO ][node                     ] [Executioner] started
[2016-04-09 13:59:24,307][INFO ][gateway                  ] [Executioner] recovered [3] indices into cluster_state
[2016-04-09 13:59:24,842][INFO ][cluster.routing.allocation] [Executioner] Cluster health status changed from [RED] to [YELLOW] (reason: [shards started [[.kibana][0]] ...]).

  运行Elasticsearch后,可以浏览http://localhost:9200/,看到如下效果,说明Elasticsearch启动成功:

{
  "name" : "Executioner",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.3.1",
    "build_hash" : "bd980929010aef404e7cb0843e61d0665269fc39",
    "build_timestamp" : "2016-04-04T12:25:05Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0"
  },
  "tagline" : "You Know, for Search"
}
  • Kibana的运行方式
➜ /Users/lion/tar/kibana-4.5.0-darwin-x64 >bin/kibana
  log   [14:00:15.242] [info][status][plugin:kibana] Status changed from uninitialized to green - Ready
  log   [14:00:15.277] [info][status][plugin:elasticsearch] Status changed from uninitialized to yellow - Waiting for Elasticsearch
  log   [14:00:15.291] [info][status][plugin:kbn_vislib_vis_types] Status changed from uninitialized to green - Ready
  log   [14:00:15.296] [info][status][plugin:markdown_vis] Status changed from uninitialized to green - Ready
  log   [14:00:15.299] [info][status][plugin:metric_vis] Status changed from uninitialized to green - Ready
  log   [14:00:15.305] [info][status][plugin:spyModes] Status changed from uninitialized to green - Ready
  log   [14:00:15.310] [info][status][plugin:statusPage] Status changed from uninitialized to green - Ready
  log   [14:00:15.317] [info][status][plugin:table_vis] Status changed from uninitialized to green - Ready
  log   [14:00:15.324] [info][listening] Server running at http://0.0.0.0:5601
  log   [14:00:15.363] [info][status][plugin:elasticsearch] Status changed from yellow to green - Kibana index ready

  运行Kibanan后,浏览http://localhost:5601/status可以看到Kibanan的运行状态:
  mshk.top
  

日志收集、监控实际操作

0.1、对Nginx的日志格式化重新配置

  如果要对Nginx的日志进行收集,那么我们需要先要让Nginx按我们设定的格式去打印,我们才知道日志中每一段的含义

配置实例

下面是我的Nginx配置,重点是log_format部分:

user  nobody;
# 这里的数值不能超过 CPU 的总核数,因为在单个核上部署超过 1 个 Nginx 服务进程并不起到提高性能的作用。
worker_processes  auto;


# Nginx 最大可用文件描述符数量,同时需要配置操作系统的 "ulimit -n 200000",或者在 /etc/security/limits.conf 中配置。 
#     worker_rlimit_nofile 200000;


pid             /usr/local/var/run/nginx.pid;

# 配置单个 Nginx 单个进程可服务的客户端数量,(最大值客户端数 = 单进程连接数 * 进程数 )
# 最大客户端数同时也受操作系统 socket 连接数的影响(最大 64K )
events {
    worker_connections  65535;
}

http {
    include       /usr/local/etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_iso8601] "$request" '
                                        '$status $body_bytes_sent "$http_referer" '
                                        '"$http_user_agent" "$http_x_forwarded_for" '
                                        '"$gzip_ratio" $request_time $bytes_sent $request_length '
                                        '"$upstream_addr" $upstream_status $upstream_response_time';
    log_format cache '***$time_local ' '***$upstream_cache_status ' '***Cache-Control: $upstream_http_cache_control ' '***Expires: $upstream_http_expires ' '***"$request" ($status) ' 

    # 只记录warn级别的错误,此外还有critical 级别的错误日志crit
    error_log       /Users/lion/logs/nginx_error.log warn;

    # Linux 关键配置,允许单个线程处理多个客户端请求。
    #use epoll;

    # 允许尽可能地处理更多的连接数,如果 worker_connections 配置太低,会产生大量的无效连接请求。
    #multi_accept on;

    # 缓存高频操作文件的FDs(文件描述符/文件句柄)
    # 在我的设备环境中,通过修改以下配置,性能从 560k 请求/秒 提升到 904k 请求/秒。
    # 我建议你对以下配置尝试不同的组合,而不是直接使用这几个数据。
    open_file_cache max=200000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # 将日志写入高速 IO 存储设备,或者直接关闭日志。
    # access_log /var/log/nginx/access.log main buffer=16k;
    # access_log off;
    access_log      /Users/lion/logs/nginx_access.log main buffer=16k;

    charset utf-8;
    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    client_body_buffer_size 512k;
    large_client_header_buffers 4 32k;
    client_max_body_size 300m;
    # 开启 sendfile 选项,使用内核的 FD 文件传输功能,这个比在用户态用 read() + write() 的方式更加高效。
    sendfile on;

    # 打开 tcp_nopush 选项,Nginux 允许将 HTTP 应答首部与数据内容在同一个报文中发出。
    # 这个选项使服务器在 sendfile 时可以提前准备 HTTP 首部,能够达到优化吞吐的效果。
    tcp_nopush on;

    # 配置连接 keep-alive 超时时间,服务器将在超时之后关闭相应的连接。
    keepalive_timeout 65;

    # 单个客户端在 keep-alive 连接上可以发送的请求数量,在测试环境中,需要配置个比较大的值。
    keepalive_requests 100000;

    # 允许服务器在客户端停止发送应答之后关闭连接,以便释放连接相应的 socket 内存开销。
    reset_timedout_connection on;

    # 配置客户端数据请求超时时间,默认是 60 秒。
    client_body_timeout 10;

    # 客户端数据读超时配置,客户端停止读取数据,超时时间后断开相应连接,默认是 60 秒。
    send_timeout 2;

    # 不要缓存 data-sends (关闭 Nagle 算法),这个能够提高高频发送小数据报文的实时性。
    tcp_nodelay on;

    #fastcgi配置
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 128k;

    #gzip配置
    gzip on;
    gzip_min_length 10240;
    gzip_buffers 4 8k;
    gzip_http_version 1.1;
    gzip_types text/plain application/x-javascript text/xml text/css application/xml;
    gzip_disable "MSIE [1-6]\.";

    ##cache##
    proxy_connect_timeout 5;
    proxy_read_timeout 60;
    proxy_send_timeout 5;
    proxy_buffer_size 16k;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 128k;
    proxy_temp_file_write_size 128k;
    proxy_temp_path /Users/lion/nginxtemp_dir; 
#设置Web缓存区名称为cache_one,内存缓存空间大小为200MB,1天没有被访问的内容自动清除,硬盘缓存空间大小为30GB。
proxy_cache_path /Users/lion/nginxcache levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
##end##

    include /usr/local/etc/nginx/conf.d/*.conf;
}

日志打出出来的结果

111.121.195.156 - - [2016-04-08T14:54:12+08:00] "GET /static/common/static/fonts/glyphicons-halflings-regular_448c34a.woff2 HTTP/1.1" 200 18028 "http://idoall.org/static/common/static/pkg/common_cd4067e.css" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36" "-" "-" 0.078 18281 905 "-" - -
218.80.225.166 - - [2016-04-08T14:56:35+08:00] "GET /user/assets/index HTTP/1.1" 200 6978 "http://idoall.org/user/buy-trade-base/pay-ment?tradelogid=138286031375032" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36" "-" "3.69" 0.070 7275 964 "127.0.0.1:9001" 200 0.070

0.2、对Logstash增加配置文件

  在配置文件中,我们要对Nginx的日志进行收集、处理,同时还要导入到Elasticsearch中。

配置示例(elasticsearche.conf)

input {
    file {
        path => ["/Users/lion/logs/access.log"]
        sincedb_path => "/Users/lion/tar/logstash-2.2.2/sincedb_path/a"
        start_position => "beginning"
    }
}
filter {
    grok {
        match => {
            "message" => "%{IPORHOST:remote_addr} - (%{USER:remote_user}|-) \[%{TIMESTAMP_ISO8601:time_local}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:http_version:float})?|-)\" %{NUMBER:request_status:int} %{NUMBER:bytes:int} \"(%{NOTSPACE:referrer}|-)\" \"(%{DATA:agent}|-)\" \"(%{DATA:http_x_forwarded_for}|-)\" \"(%{NOTSPACE:gzip_ratio}|-)\" %{NUMBER:request_time:float} %{NUMBER:bytes_sent:int} %{NUMBER:request_length:int} \"(%{DATA:upstream_addr}|-)\" (%{NUMBER:upstream_status:int}|-) (%{NUMBER:upstream_status:float}|-)"
        }
    }
    geoip {
        source => "remote_addr"
    }
    #geoip 插件的 "source" 字段可以是任一处理后的字段,比如 "client_ip",但是字段内容却需要小心!geoip 库内只存有公共网络上的 IP 信息,查询不到结果的,会直接返回 null,而 logstash 的 geoip 插件对 null 结果的处理是:不生成对应的 geoip.字段。
#    kv {
#        source => "request"
#        field_split => "&?"
#        value_split => "="
#    }
    urldecode {
        all_fields => true
        remove_field => ["message"]
    }
}
output{
    elasticsearch {
        hosts => ["127.0.0.1:9200"]
        index => "logstash-nginx-%{+YYYY.MM.dd}"
        document_type => "log"
        workers => 1
        flush_size => 20000
        #idle_flush_time => 10
        template_overwrite => true
    }
}

配置参数说明

  • flush_size

表示Logstash会积累到多少条以后,一起发送给Elasticsearch,默认值是是 500 条。

  • idle_flush_time

表示Logstash发送给Elasticsearch的时间,就算没有积累到flush_size设定的值,也会发送一次,默认值是1秒。
很多人改大了 flush_size 也没能提高写入 ES 性能的原因——Logstash 还是 1 秒钟发送一次。

0.3、通过Logstash收集日志并导入到Elasticsearch

  首先你要保证Nginx的日志文件中有数据。
  我们先启动Elasticsearch:

➜ /Users/lion/tar/elasticsearch-2.3.1 >bin/elasticsearch

  然后启动Logstash:

➜ /Users/lion/tar/logstash-2.2.2 >bin/logstash -f elasticsearche.conf
Settings: Default pipeline workers: 8
Logstash startup completed

  通过刚才安装的Elasticsearch Head插件,我们打开浏览器,输入http://localhost:9200/_plugin/head/,可以看到已经将数据导入进去了:
  mshk.top

  点击数据浏览,数据我们创建的logstash-nginx索引,也可以看到详细数据:
  mshk.top

0.4、使用Kibana,对数据进行检索

  启动kibana

➜ /Users/lion/tar/kibana-4.5.0-darwin-x64 >bin/kibana

  打开浏览器,输入http://localhost:5601/,然后在Setting->Indices中进行配置,在Index name or pattern处输入『logstash-nginx-*』,在Time-field name中选择我们要根据哪个时间索引,如下图:
  mshk.top

  最后点击绿色的『Create』按钮,创建成功。

  接下来我们点击最顶部的导航Discover,选择索引logstash-nginx-*,可以看到我们导入的数据,对实时的数据进行监控(如果没有数据的话,请点击右上角的时间进行筛选):
  mshk.top

0.5、使用Kibana对请求状态数据做报表

URL请求状态报表
  点击Visualiz->Pie Chart->From a new search-,在Select an index pattern中选择logstash-nginx-*,然后选择Split Slices,在Aggregation的下拉列表中选择Terms,在Filed中,选择request_status字段,最后点击tab选项卡Data、Option右侧的绿色播放按钮,可以看到下图类似的结果:
  mshk.top
  这时点击搜索框右侧的保存按钮,我们将图表保存为『ruquest_status』

用户来源省份报表
  在『对Logstash增加配置文件』章节中,我们配置了geoip,Logstash会自动对ip地段进行解析。
  配置方式和地区一样,我们在Field字段选择geoip.city_name.raw,生成图表后,我们将结果保存为『city_name』。

0.6、在Kibana仪表盘中对数据进行展示

  点击Dashboard,再点击搜索框右侧带'+'号的按钮,会看到我们之前保存的图表名称,选择『request_status』和『city_name』,可以看到和下图类似的效果,在Dashboard面板中,我们生成的数据报表,可以根据你的需求拖动来改变大小。
  mshk.top

  通过以上实例,我们完成了Logstash、Kibana、Elasticsearch之间的通讯,并实现了对日志的实时监测和管理。通过这个实例,如果你稍微懂一些正则,也可以实现对其他日志的收集和管理,希望能够对你的工作有帮助。

其他

  如果在Logstash中没有对字段做好格式化,导入到Kibana中后发现字段的类型(int,string,date...)不对,可以访问 http://idoall.org:9200/logstash-nginx-XXXX.XX.XX/log/_mapping 查看字段的定义,然后修改mapping。

  修改mapping之前,要把数据都清理掉,不然你就算put了新的mapping,他以前的数据也更正不过来,后进去的数据会跟随旧数据的存储类型。

扩展阅读

  elasticsearch配置小记
  


博文作者:迦壹
博客地址:Logstash-2.2.2+Kibana-4.5.0+Elasticsearch-2.3.1+Mac10.10.3收集、监控Nginx日志最佳实践
写作时间:2016-04-09 19:52
转载声明:可以转载, 但必须以超链接形式标 明文章原始出处和作者信息及版权声明,谢谢合作!


说点什么

您将是第一位评论人!

提醒
avatar
wpDiscuz