最新記錄:11臺ES(12核64G機械盤),天天日誌量在37.4億條,Primary Shard大小1.7T,最高索引速度每秒8萬左右。php
此文爲原標題「玩兒透日誌分析集羣搭建.調優.管理rsyslog->kafka->spark->elk」的更改版。html
實時日誌分析做爲掌握業務狀況、故障分析排查的一個重要手段,目前使用最多最成熟的莫過於ELK方案,總體方案也有各類架構組合,像rsyslog->ES->kibana、rsyslog->Redis->Logstash->ES->kibana、rsyslog->kafka->Logstash->ES->kibana等等,複雜點的有spark的引用。每種方案適合不一樣的應用場景,沒有優劣之分,我目前用的是rsyslog->kafka->(Logstash/spark)->ES->kibana和rsyslog->rsyslog中繼->kafka->(Logstash/spark)->ES->kibana方案,中間使用spark對日誌進行再次聚合。前端
從總體架構進行抽象總結,其實就是採集->清洗匯聚->索引->展示四個環節,再去考慮各環節中緩存、隊列的使用,每一個環節點用不一樣的軟件來實現。下面介紹一下我目前方案集羣的搭建和配置,但願對同行有所幫助,也算是積福德消業,在ELK探索過程當中多謝遠川和馮超同窗的奉獻交流。附上我目前使用的方案選型架構圖以下:node
工做中對不一樣場景的各類架構進行了梳理,詳見博文:運維數據分析平臺建設的4個段位——架構演進linux
1、採集(使用rsyslog)nginx
客戶端使用rsyslog8.19.0作的收集,直接centos安裝rpm包,安裝詳細見:redis
http://www.rsyslog.com/rhelcentos-rpms/shell
將yum源配置好後:apache
yum install rsyslog yum install rsyslog-kafka
安裝好後對應rsyslog的配置文件以下:centos
module(load="imfile") module(load="omkafka") $PreserveFQDN on main_queue( queue.workerthreads="10" # threads to work on the queue queue.dequeueBatchSize="1000" # max number of messages to process at once queue.size="50000" # max queue size ) ##########################nginx log################################ $template nginxlog,"%$myhostname%`%msg%" if $syslogfacility-text == 'local6' then { action( broker=["10.13.88.190:9092","10.13.88.191:9092","10.13.88.192:9092","10.13.88.193:9092"] type="omkafka" topic="cms-nginx" template="nginxlog" partitions.auto="on" ) stop } ############################redis log######################### $template redislog,"%$myhostname%`%msg%" ruleset(name="redis7215-log") { action( broker=["10.13.88.190:9092","10.13.88.191:9092","10.13.88.192:9092","10.13.88.193:9092"] type="omkafka" topic="redis-log" template="redislog" partitions.auto="on" ) } input(type="imfile" File="/data1/ms/log/front/redis7215.log" Tag="" ruleset="redis7215-log" freshStartTail="on" #start tailf reopenOnTruncate="on" #Truncate reopen ) input(type="imfile" File="/data1/ms/log/front/redis7243.log" Tag="" ruleset="redis7215-log" freshStartTail="on" reopenOnTruncate="on" ) ############################php curl log############################# $template phpcurl-log,"%$myhostname%`%msg%" ruleset(name="phpcurl-log") { action( broker=["10.13.88.190:9092","10.13.88.191:9092","10.13.88.192:9092","10.13.88.193:9092"] type="omkafka" topic="phpcurl-log" template="phpcurl-log" partitions.auto="on" ) } input(type="imfile" File="/data1/ms/log/php_common/php_slow_log" Tag="" ruleset="phpcurl-log" freshStartTail="on" reopenOnTruncate="on" )
爲了不在日誌發送錯誤時,丟在message日誌裏,瞬間將磁盤佔滿,同時配置丟棄策略
*.info;mail.none;authpriv.none;cron.none;local6.none /var/log/messages
目前收集了nginx、redis、php curl三種日誌,說一下收集方案。
一、對於nginx
方案1:採用nginx的rsyslog模塊將日誌打到local6,對應nginx的配置以下
##########elk############################# access_log syslog:local6 STAT;
而後經過如上rsyslog的配置,將日誌直接入kafka隊列,kafka集羣是4個broker。
方案2:線上還有另外一個傳輸方案,rsyslog設置一箇中繼,經過udp的方式將日誌傳到中繼的rsyslog,由中繼rsyslog入kafka,這麼作的目的是方便了管理,當時還有個考慮是udp不會堵,但通過多輪測試後,nginx的rsyslog模塊也是很健壯,不會堵的。
二、對於redis、php curl的日誌
經過rsyslog的imfile模塊,直接對文件監聽,配置見上面的rsyslog配置,在日誌輪轉時經過超連接的方式進行新文件的鏈接,對應的超鏈接計劃任務以下,天天0點5分執行:
5 0 * * * root sh /usr/local/script/php_slow_log.sh &> /dev/null
對應的php_slow_log.sh的腳本以下:
#!/bin/bash DATE=`date +%F` ln -sf /data1/ms/log/php_common/curl-$DATE /data1/ms/log/php_common/php_slow_log
備註:
a、rsyslog向kafka推送消息時,輪詢發送消息到broker上的leader partition;
b、rsyslog經過udp或tcp向外轉發日誌時,會默認加上時間、主機名、主機ip的屬性。
c、rsyslog的其他知識博文詳見:
博文1:巧用rsyslog收集多套日誌並作單套日誌的過濾分離
2、隊列(kafka+zookeeper)
隊列用的是kafka,kafka集羣使用zookeeper管理,咱們用了4臺服務器混裝了4個kafka和3個zookeeper,kafka和zookeeper的安裝地址以下:
http://kafka.apache.org/downloads 注意:下載Binary downloads版本,別下錯了,解壓後就能用
http://zookeeper.apache.org/ 注意:安裝過程很簡單,按照文檔來便可,不在說明
kafka管理能夠用kafka-manager詳見博文:kafka與zookeeper管理之kafka-manager踩坑小記
kafka原理介紹推薦:Kafka設計與原理詳解
一、關於kafaka
a、配置比較簡單,基本默認便可,常調整的配置項以下:
配置文件:server.properties broker.id=190 #id num.partitions=20 #默認kafka的partion數量 log.dirs=/data1/kafka-logs #日誌文件存放目錄 log.retention.hours=3 #日誌保留時間長短 zookeeper.connect=10.13.88.190:2181,10.13.88.191:2181,10.13.88.192:2181 #zookeeper指定 delete.topic.enable=true #topic是能夠刪除的
b、安裝後測試(假設kafka和zookeeper都裝了):
開兩個終端,兩個終端分別運行以下命令
啓動:./bin/kafka-server-start.sh /usr/local/kafka/config/server.properties & 關閉:./bin/kafka-server-stop.sh 終端1:./bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test 終端2:./bin/kafka-console-consumer.sh --zookeeper localhost:2181 --from-beginning --topic test
注意兩個終端的topic要一個名字,這時你在終端1輸入任何數據,在終端2是同步的,證實你安裝成功。
c、kafka經常使用管理命令
建立topic:./bin/kafka-topics.sh --create --topic test --replication-factor 1 --partitions 32 --zookeeper localhost:2181 刪除topic:./bin/kafka-topics.sh --delete --topic test --zookeeper localhost:2181 查看topic列表:./bin/kafka-topics.sh --list --zookeeper localhost:2181 查看某個topic詳細:./bin/kafka-topics.sh --describe --topic test --zookeeper localhosts:2181 監控某個topic的消費:./bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic test 指定消費組查看消費狀況:./bin/kafka-consumer-offset-checker.sh --zookeeper localhost:2181 --group test
d、kafka集羣消費吞吐量性能測試以下,每秒能夠支持消費50萬條信息,咱們目前的QPS遠遠是沒問題的
備註:topic下partitions的數量決定了併發消費的數量,在設置上要根據消息的QPS和硬盤狀況合理配置。
二、關於zookeeper
a、配置比較簡單,大多數默認項,最好奇數個,半數以上zookeeper存活可用
配置文件:zoo.cfg dataDir=/data1/zookeeper server.1=10.13.88.190:3888:4888 server.2=10.13.88.191:3889:4888 server.3=10.13.88.192:3889:4888
注意:要在數據目錄手動創建myid,myid的值是server後面的數字,數字是有範圍限制的1~255
b、zookeeper的經常使用管理命令
zookeeper我主要是看下它的總體狀態,寫了個簡單腳本獲取zookeeper的狀態,執行結果以下:
腳本內容以下:
#!/bin/sh #writer:gaolixu [ -z $1 ] && echo "Please specify zoo.cfg like /usr/local/zookeeper/conf/zoo.cfg " && exit cat $1 |grep "^server" |awk -F'[:|=]' '{print $2}' | while read line do echo -ne "$line\t" echo stat|nc -w 2 $line 2181 |egrep "^(Node|Zxid|Mode|Connections)" |tr "\n" "\t" echo stat|nc -w 2 $line 2181 |egrep "^(Node|Zxid|Mode|Connections)" &>/dev/null || echo -n "host is done." echo done 使用方式:zkstat.sh /配置文件zoo.cfg的位置
zookeeper是至關穩定的,基本不用管。
備註:zookeeper配置文件裏不能有漢字,不然啓動不起來。
3、清洗匯聚(logstash/spark)
logstash用作清洗,而且將處理好的日誌推送到es裏,安裝過程很簡單詳見網址:
https://www.elastic.co/guide/en/logstash/current/installing-logstash.html#package-repositories
我線上的nginx的配置文件以下:
input { kafka { zk_connect => "10.13.88.190:2181,10.13.88.191:2181,10.13.88.192:2181" topic_id => "cms-nginx" group_id => "cms-nginx" consumer_threads => 1 reset_beginning => false decorate_events => false } } filter { ruby { init => "@kname = ['host-name','front','http_x_up_calling_line_id','request','http_user_agent','status','remote_addr_1','id','http_referer','request_time','body_bytes_sent','http_deviceid','http_x_forwarded_for','domain','cookie']" code => "event.append(Hash[@kname.zip(event['message'].split('`'))]) " remove_field => ["@version","_score","id","tags","key","message","http_deviceid","http_x_up_calling_line_id","","cookie"] } if [front] { grok { match => ["front","%{HTTPDATE:logdate}"] } date { match => ["logdate", "dd/MMM/yyyy:HH:mm:ss Z"] target => "@timestamp" remove_field => ["front","logdate"] } } if [request] { ruby { init => "@kname = ['method','uri','verb']" code => "event.append(Hash[@kname.zip(event['request'].split(' '))])" remove_field => [ "request","method","verb"] } } if [remote_addr_1] { grok { match => [ "remote_addr_1", "%{IPV4:remote_addr}" ] remove_field => ["remote_addr_1"] } } mutate { convert => [ "body_bytes_sent" , "integer", "status" , "integer", "request_time" , "float" ] } } output { elasticsearch { hosts => ["10.39.40.94:9200","10.39.40.95:9200","10.39.40.96:9200","10.39.40.97:9200"] workers => 1 index => "logstash-cms-nginx-%{+YYYY.MM.dd.hh}" } #stdout { codec => dots #workers => 5 #} #測試性能時使用 #stdout { codec => rubydebug } #調試時使用 } 啓動命令:./bin/logstash -w 4 -b 1000 -f /etc/logstash/conf.d/kafka_logstash_cms_nginx.conf & -w 後面的worker數是根據cpu的核心數大概算一下,我這裏一臺服務器開三個logstash,每一個起4個worker
配置文件看着很長,其實閱讀性很好,很易懂上手編寫,無非就是定義切割點,若是大切割點下須要繼續切割,就加if判斷,繼續切割,吐個槽裏面threads和workers的數量好像無論用,我壓測時去看線程數對不上,看的方法是top -H -p logstash的pid。
再就是看看哪些須要計算的變成數字型,還有個timestamp的處理,這個能夠看看上面的代碼,對於nginx打印的時間符合ISO8601標準,能夠用他作es的時間索引,這樣有個好處,若是某個環節慢索引趕不上的話,日誌不會錯序。時間標準詳細可見:http://udn.yyuap.com/doc/logstash-best-practice-cn/filter/date.html
備註:
a、儘可能去掉沒用的字段,精簡索引,很是重要;
b、nginx打印出來的時間是標準化的,能夠用它傳到es做爲timestamp建索引;
c、對於響應時間、響應內容大小、狀態碼要轉換成數字類型,方便在kibana裏作計算等操做;
d、切割雙引號可使用以下配置
code => "event.append(Hash[@kname.zip(event['message'].split(34.chr))])"
e、抓包後發現,logstash向es推數據是輪訓的,從zookeeper取broker的相關信息並不輪訓,最終logstash從zookeeper只是拿到broker的信息,而後到kafka的broker上進行數據消費讀取。
f、儘可能按照官方以下寫法創建多個索引向es推送,防止單個索引巨大,search時計算不出來
index => "logstash-cms-nginx-%{+YYYY.MM.dd.hh}"
g、測試性能方法以下
因爲沒有現成工具,咱們用了打點計量的方式進行壓測,摘掉es後將輸出變爲一個點,每處理一條信息打一個點,而後將打出的點用pv命令統計出字節流量,反推出logstash的吞吐量。
cp一個配置文件,修改output以下:
output { stdout { codec => dots workers => 1 } }
同時爲了避免影響線上業務,修改group_id,這樣的話測試消費和線上消費互不影響,配置文件修改以下:
kafka { zk_connect => "10.13.88.190:2181,10.13.88.191:2181,10.13.88.192:2181" topic_id => "nginx" group_id => "test001" consumer_threads => 12 reset_beginning => false decorate_events => flase }
測試時執行命令:/opt/logstash/bin/logstash -f /tmp/kafka_test.conf |pv -abt > /dev/null
壓測結果以下:
每一個點是一個byte,等到數據穩定後,計算每s的吞吐量爲2.93*1024=3000,也就是這一個logstash最大吞吐量爲能處理3000條信息每s。
4、索引(es)
ES升級調優5.2.1詳見博文:**ELK之ES2.4.1雙實例平滑升級調優至5.2.1踩坑並supervisor管理記**
ES工做原理及集羣調優見博文:**深刻淺出剖析Elasticsearch的工做原理**
線上業務最先使用的是es2.x版本,後來升級到了es5.x版本,變化是比較大的,不少配置點都不同了,但道法天然而術變萬千,不論是哪一個版本,全部的調整中遵循着不變的法則,從中總結概括,其實分爲下面幾個層次:
一、系統層:
HEAP、GC、文件描述符、進程數調整、關閉交換分區、進程管理最大內存、系統內存回收機制調優。
二、結構層:
a、master、client節點分離;
b、冷、熱數據分羣,共用一個client管理。
三、業務層:
a、index調優(複製分片數、shard數、刷新時間)
b、flush調優(translog控制flush頻率、同步異步)
c、merge調優(segment相關參數、觸發條件)
d、空閒時間強制merge(減小segment的數量)
e、內存請求熔斷調優(fielddata、request內存)
f 、數據保留7天,限制查詢1天(開關索引實現)
g、跟進官方新版本,並及時升級。
四、硬調優:
a、磁盤換ssd。
es的安裝也是比較簡單詳見:https://www.elastic.co/guide/en/elasticsearch/reference/current/rpm.html
es的節點類型相關說明詳見:https://my.oschina.net/secisland/blog/618911
經常使用es的集羣管理命令,固然只是看信息的能夠瀏覽器裏直接輸入查看
curl http://10.39.40.94:9200/_cat/nodes?v #節點概況 curl http://10.39.40.94:9200/_cat/shards?v #查看shards的信息 curl http://10.39.40.94:9200/_cat/indices?v #查看索引信息,若是新推的日誌,能夠看這個確認是否索引成功 curl -X DELETE "http://10.39.40.94:9200/索引名稱" #刪除指定歷史索引,速度很快
對於咱們線上的日誌,默認保存7天,天天晚上清除一次,並關索引,僅能查看一天的日誌數據,清除的腳本以下:
#!/bin/bash DATE=`date +%Y.%m.%d.%I` DATA1=`date +%Y.%m.%d -d'-2 day'` DATA2=`date +%Y.%m.%d -d'-7 day'` curl -XPOST -u elastic:elastic "http://10.39.40.94:9220/logstash*${DATA1}*/_close?pretty" curl -XDELETE -u elastic:elastic "http://10.39.40.97:9220/logstash*${DATA2}*?pretty"
5、展示(kibana)
展示kibana沒什麼可說的,直接安裝後,配置好es的地址就能夠用,安裝很簡單有rpm包,前端能夠用nginx作個代理,作限制,安裝詳見:https://www.elastic.co/downloads/kibana
安裝後模型搭建也比較人性化,用幾回就熟練了。
備註:像logstash、kafka這種加&號啓動的服務(有些啓動後本身fork新進程而後退出的其實不合適)能夠用supervisor管理,比較方便。配置至關簡單,能夠在瀏覽器看狀態,後使用supervisor monitor統一管理,截屏以下: