为了账号安全,请及时绑定邮箱和手机立即绑定

elkb实践经验,再赠送一套复杂的配置文件

标签:
Java

https://img1.sycdn.imooc.com//5defaed80001473b03650174.jpg

小姐姐味道【ID:xjjdog】
作者:十年架构,日百亿流量经验,与你分享。

宝剑锋从磨砺出,梅花香自苦寒来。

诗人白居易,三月下江南,看到沿路开放的桃花,心潮澎湃,作下了这首流传千秋的诗。表现了诗人对美好事物的向往,以及对其背后苦情的感慨。算了…我编不下去了。

前半句还好,是因果关系。但诗的后半句,却狗屁不通,典型的从结果找原因的思路。哪怕改成“狗屎臭自菊花来”,也比这通畅的多。

这就是理论和实践的区别,只靠臆想,是撑不起现实的骨感的。

本篇文章,将会介绍一个常见的、烂大街的elkb方案,并附赠一套精致的配置文件,以便减少重复工作。


ELKkB

不久之前,elkb还是叫elkbeats系列是最近几年才发展起来的,目的是为了替换flume等收集组件。但为了让这个过程更加平滑具有扩展性,一般会加入一个叫做kafka的组件。所以整体看起来是这样的。

https://img1.sycdn.imooc.com//5defaed90001e51c07570541.jpg

简单点评一下几个组件。

1)filebeat。用于收集日志组件,经测试其使用简单,占用资源比flume更少。但是对资源的占用不是那么智能,需要调整一些参数。filebeat会同时耗费内存和cpu资源,需要小心。

2)kafka。流行的消息队列,在日志收集里有存储+缓冲的功能。kafka的topic过多,会有严重的性能问题,所以需要对收集的信息进行归类。更进一步,直接划分不同的kafka集群。kafka对cpu要求较低,大内存和高速磁盘会显著增加它的性能。

3)logstash。主要用于数据的过滤和整形。这个组件非常贪婪,会占用大量资源,千万不要和应用进程放在一块。不过它算是一个无状态的计算节点,可以根据需要随时扩容。

4)elasticsearch。可以存储容量非常大的日志数据。注意单个索引不要过大,可以根据量级进行按天索引或者按月索引,同时便于删除。

5)kibana。和es集成度非常好的展示组件

选择的组件越多,整个过程会越优雅。尤其是kafka的加入,会让整个链条的头和屁股都变得完美可换,比较魔幻。一个晋级方式就是:ELK->ELKB->ELKkB。


实践旅程

日志格式

为了串联我们的这些组件,需要准备一些小小的数据。其中,nginx日志是最常见的,它已经默认成为了http服务的负载均衡器。

首先,需要对它的日志格式进行一下规整,我这里有一个比较好用的配置。

log_format  main 
'$time_iso8601|$hostname|$remote_addr|$upstream_addr|$request_time|''$upstream_response_time|$upstream_connect_time|$status|$upstream_status|''$bytes_sent|$remote_user|$uri|$query_string|$http_user_agent|$http_referer|$scheme|''$request_method|$http_x_forwarded_for' ;access_log logs/access.log main;

最终,生成的日志可能会长下面这个样子,内容还是比较全的。这种格式的日志,无论是交给程序处理,还是使用脚本处理,都方便的多。

2019-11-28T11:26:24+08:00|nginx100.server.ops.pro.dc|101.116.237.77|10.32.135.2:41015|0.062|0.060|0.000|200|200|13701|-|/api/exec|v=10&token=H8DH9Snx9877SDER5627|-|-|http|POST|112.40.255.152

收集器

接下来,需要配置filebeat组件。上面也提到了,由于这个东西是部署在业务机器上的,那就需要严格控制它的资源。完整配置文件可以在附件中获取。

比如cpu资源限制。

max_procs: 1

内存资源限制。

queue.spool:
 file:
   path: "${path.data}/spool.dat"
   size: 512MiB
   page_size: 32KiB
 write:
   buffer_size: 10MiB
   flush.timeout: 5s
   flush.events: 1024

另外,还可以增加一些额外的字段。

fields:
 env: pro

接下来需要配置kafka。由于日志量级一般都比较大,又没有非常明显的意义,所以副本数超过2,没有什么用处,反而会增加故障恢复的时间。

过滤器

logstash的配置可能是最让人迷惑的地方了,这也是我们主要介绍的点。因为上面的nginx日志,将会被解析成elasticsearch能够识别的json串。

通过input部分,就可以接入一些数据源。在这里,我们的数据源变成了kafka。如果你有多个kakfa,或者多个数据源,都可以在这里定义。

然后,就可以在filter部分,定义一些数据的清洗动作。这里有着非常蛋疼的语法,用着非常蹩脚的api,尤其是日期处理方面。如果代码没有格式化,嵌套的层次会让人发晕。据说使用的是ruby语法。

注意,event是个内置变量,代表的是当前的一行数据,包括一些基础属性。可以通过get方法获取一些值。

比如,获取最主要的body信息,也就是具体的行信息。

body = event.get('message')

然后,把它解析成相应的key/value值。这个分隔符|就是我们nginx日志的分割符。有没有一股蓬勃而出的冲动?

reqhash = Hash[@mymapper.zip(message.split('|'))]

query_string = reqhash['query_string']

reqhash.delete('query_string')

日期处理也是让人心碎的旅程。

time_local = event.get('time_local')
datetime = DateTime.strptime(time_local,'%Y-%m-%dT%H:%M:%S%z')
source_timestamp = datetime.to_time.to_i * 1000
source_date = datetime.strftime('%Y-%m-%d')      event.set('source_timestamp',source_timestamp)
event.set('source_date',source_date)

假如想要解析query param,这个也是有的,不过依然比较绕。

query_string = reqhash['query_string']
query_param = CGI.parse(query_string)
query_param.each { |key,value| query_param[key]=value.join() }
reqhash['query_param'] = query_param
buffer_map = LogStash::Event.new(reqhash)
event.append(buffer_map)

这么多奇形怪状的函数,是从何而来呢?logstash不会告诉你,我是从ruby官方查的。可能是L并不屑于与我们交流。

https://ruby-doc.org/core-2.5.1/

如果你的日志格式定义的比较怪异,或者嵌套层次比较深,要注意了。注定解析是要下一番功夫了。

https://img1.sycdn.imooc.com//5defaed90001800907570252.jpg

不过logstash有一个output,叫做stdout,可以实时的调试这个过程,你需要肉眼判断结果。这就比较考验一次性编程成功的能力了。

End



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消