主要工作:将四台nginx日志收集并统计分析
架构回顾:
N1~N4:四台nginx机器,分别部署了logstash
A:部署了redis、elasticsearch、logstah、kibana
B、C、D:部署elasticsearch
ABCD组成了elasticsearch集群
数据流向:
【N1~N4】logstash---->【A】redis----->【A】logstash----->【ABCD】elasticsearch集群----->【A】kibana4
ELK各个组件配置:
一.redis配置
这里我们只需要将redis作为一个单纯的缓存队列使用,其实不需要redis的持久化,所以关掉了redis的持久化功能,以提高性能。
redis3.0.4持久化有2种方式:Snapshotting快照和Append-only file 文件跟写,默认是采用快照的方式。
1.关闭Snapshotting快照
- save ""
- #save 900 1
- #save 300 10
- #save 60 10000
2.关闭aof
- appendonly no
3.设置密码
- requirepass redispass123
二.logstash的配置
ELK中除了es集群之外,跟我们日志最紧密的就是logstash的配置,logstah担负着将日志过滤,规整上传的任务。其详细配置可参考:
https://www.elastic.co/guide/en/logstash/1.5/getting-started-with-logstash.html
1.N1~N4上logstash的配置
N1~N4是nginx日志所在的机器,nginx日志是有一定格式的,可以选择直接将nginx日志存储为json格式,这样省去了在logstash中规整格式的麻烦,但是有时候,我们不希望更改nginx日志的存储格式,那么就需要在logstah中处理了。
1.1nginx日志的两种格式
json格式:
- log_format jsonlog '{"@timestamp":"$time_iso8601",'
- '"remote_addr":"$remote_addr",'
- '"request":"$request",'
- '"status":$status,'
- '"bbs":$body_bytes_sent,'
- '"bs":$bytes_sent,'
- '"req_len":$request_length,'
- '"user_agent":"$http_user_agent",'
- '"req_time":$request_time,'
- '"host":"$host"}';
常见格式,非json格式:
- log_format mylog '$remote_addr - $remote_user [$time_local] "$request" ' '$status $bytes_sent $request_length ' '"$http_user_agent" ' '$request_time' ' $host';
1.2logstash的配置
我们这里的logstash配置以nginx日志是非json格式的情况为例,即上面的那种常见格式为例子进行正则匹配,规整出需要上传到【A】redis的数据。
- input {
- file {
- type => "N1" //这里我用type标示出来源机器
- path => "/xxx/access.log" //nginx日志路径
- }
- }
- filter {
- grok {
- match => [
- "message", "%{IPORHOST:client_ip} - (%{USER:user}|-) \[%{HTTPDATE:timestamp}\] \"(?:%{WORD:method} (%{PATH:baseurl}\?%{NOTSPACE:params}|%{NOTSPACE:baseurl}) (?:HTTP/%{NUMBER:http_version})?|-)\" %{NUMBER:sta:int} %{NUMBER:sbytes:int} %{NUMBER:reqbytes:int} %{QS:agent} %{NUMBER:reqtime:float} %{IPORHOST:reqhost}"
- ]
- } //正则匹配成json格式
- kv {
- source => "params" //匹配来源
- prefix => "req." //匹配后生成key的前缀
- field_split => "&" //匹配域用的分隔符
- value_split => "=" //匹配值的分隔符
- include_keys => ["person","name","area","modifier","appid","category"] //只保留这些传参
- } //将params中的传参匹配出来,只保留incude_keys中参数
- urldecode {
- all_fields => true //对url编码
- }
- geoip {
- source => "client_ip"
- fields => ["real_region_name","city_name","location"]
- } //使用geoip地址库 对来源ip解析生成地理坐标
- date {
- match => ["timestamp","dd/MMM/YYYY:HH:mm:ss Z"]
- target => "@timestamp"
- } //将日志中的时间换成logstash的时间戳
- mutate {
- remove_field => ["@version","timestamp","host","path","user","method","http_version","params"]
- } //去除一些暂时不关心的key
- }
- output { //输出到redis
- redis {
- batch => true
- batch_events =>500
- batch_timeout => 5
- host => "xxx.xx.xxx.xx" //【A】的地址
- port => 6379 // redis的端口
- password => " redispass123" //上面设置的redis的密码
- data_type => 'list' //以list形式上传数据
- key => 'test' //设置key,最好是有意义的名称
- workers => 10
- }
- }
2.A上的logstash的配置
A上的logstash的作用是从redis中获取数据,可以进一步过滤数据,塞进es集群中
2.1 logstash的配置
- input {
- redis {
- batch_count => 500
- threads => 5
- host => "xxx.xx.xxx.xx" //redis的ip地址
- port => 6379 //redis的端口号
- password => "redispass123" //上面设置的redis的密码
- data_type => 'list' //数据组织形式为list
- key => 'test' //获取key为test的数据
- type => 'redis-input'
- }
- }
- filter {
- mutate {
- remove_field => ["@version","host"] //去掉一些不关心的字段key
- }
- }
- output {
- elasticsearch {
- workers => 5
- host => "xxx.xx.xxx.xx" //es集群的ip地址(这里选用主节点ip地址,在后面配置es的时候,人为限定了主节点)
- port => 9200
- codec => "json" //以json形式
- index => "logstash-%{+YYYY.MM.DD}"" //设置索引文件按天存储
- template => "/usr/local/logstash-1.5.4/nginx_template.json" //自己定义的es的mapping
- template_name => "nginx_template.json" //有多个mapping的时候必须要指定名称
- template_overwrite => true
- protocol => "http" //使用http协议
- }
- }
2.2 自定义的mapping,logstash自己有默认的mapping,在数据格式比较稳定的时候,可以自己定义mapping,如下:
- {
- "order" : 1, //order值越大,优先度越高
- "template" : "logstash-*", //设置匹配的索引
- "settings" : {
- "index.refresh_interval" : "5s" //设置索引刷新频率
- },
- "mappings" : {
- "_default_" : {
- "_all" : {"enabled" : true, "omit_norms" : true},
- "dynamic_templates" : [ {
- "message_field" : {
- "match" : "message",
- "match_mapping_type" : "string",
- "mapping" : {
- "type" : "string", "index" : "not_analyzed"
- }
- }
- }, {
- "string_fields" : {
- "match" : "*",
- "match_mapping_type" : "string",
- "mapping" : {
- "type" : "string", "index" : "analyzed", "omit_norms" : true, //默认都分词
- "fields" : {
- "raw" : {"type": "string", "index" : "not_analyzed", "ignore_above" : 256, "doc_values" : true } //对每个str的key建一个不分词的key 使用doc_values
- }
- }
- }
- } ],
- "properties" : {
- "@version": { "type": "string", "index": "not_analyzed" },
- "geoip" : {
- "type" : "object",
- "dynamic": true,
- "properties" : {
- "location" : { "type" : "geo_point" }
- }
- }
- }
- }
- }
- }
三.ES的配置
es的配置主要是四个方面:
1.内存的分配,包括GC的选择
2.mapping的策略
3.缓存策略
4.节点策略
入门可参考:http://www.tuicool.com/articles/YbIR7j
http://elasticsearch.cn/question/284
http://zhaoyanblog.com/archives/319.html
我们这里指定了A为主节点,指定了主节点通信,延长了节点心跳判断丢失的时间,设置了内存,设置了node节点缓存,设置了mapping,如下:
cluster.name: mytest
node.name: B
node.maste: false
node.data: true
indices.fielddata.cache.size: 40%
这个是node级别的设置,当缓存的数据达到heap的40%的时候 就启用自动清理旧的缓存数据,如果不设置,es默认是无限大的。
discovery.zen.ping.timeout: 120s
discovery.zen.ping.retries: 6
discovery.zen.ping.interval: 30s
discovery.zen.ping.retries: 6
discovery.zen.ping.interval: 30s
设置这些参数是为了防止过于频繁的节点掉线
discovery.zen.ping.unicast.hosts: ["xxx.xx.xxx.xx"] A的ip地址
内存及GC的设置在bin/elasticsearch.in.sh中进行设置
修改内存为机器内存的40%,这里为
ES_MIN_MEM=10g
ES_MAX_MEM=10g
这里设置成一样,避免引发长时间GC
es默认是CMS的垃圾收集,网上传言G1的GC性能上要优于CMS,可以考虑更换,目前4台机器日处理120G日志量并没有出现GC问题,所以没有替换GC