内容来源:2017年6月10日,南京云利来软件科技有限公司张立丹在“Elastic Meetup 南京”进行《基于ES的SQL报警引擎》演讲分享。IT 大咖说作为独家视频合作方,经主办方和讲者审阅授权发布。
阅读字数:1499 | 4分钟阅读
摘要
一般来说,ES的查询语言在使用过程中会比较麻烦,来自南京云利来软件科技有限公司的张丹立老师从四个方面来分析把ES换成SQL后的状态。
概述
ES的聚合能力非常强,延迟低;而SQL相对于DSL来说有较高的抽象层次,更为大众所熟悉。在做报警引擎的时候我们发现,纯用ES难以解决我们的问题,必须要在ES计算后进行第二次处理。RDL用“规则描述语言”,提供计算机辅助功能。
SQL及扩展
过滤
过滤表达式:inbyte + outbyte > 10000 AND sip = ‘192.168.0.55’
过滤表达式有基本的四则运算,并对ES支持的某些脚本添加了一些抽象函数。
ES也是基于时间线的,无论是做日志采集还是数据监控,都要指定一个时间域。我们做报警时首先要解决的就是时间模型,需要把时间模型抽象出一些函数。
过滤函数:last(5m)、last_days(3,5m)、last_weeks(4,5m)、last_weekdays(3,10m)、range(flows,[100,1000])、ip_range(sip,’192.168.0.0/24’)、date_range(…)
query_string(‘sip:[192.168.0.100TO 192.168.0.200]’)
以上的过滤函数都是按照ES提供的函数来进行抽象。
聚合
聚合函数:count(*)、count(sip)、count(UNIQUE url)、count(inbyte + outbyte)
sum()、min()、max()、avg()
stdve()、squares()、variance()
聚合函数是根据ES提供的聚合功能来进行抽象。
我们在对网络数据进行报警的时候,需要对流量进行报警。流量有内部局域网访问的流量,也有访问外部的局域网。
ES里有一个桶聚合的功能叫做filters,在filters里面可以把ip_range当成一个filters来做。
RDL脚本
通过SQL查询ES之后,还要做进一步的处理。因为虽然ES的聚合能力很强,但它聚合后的结果处理能力还是比较弱的。
我们在报警模块中开发了一套脚本语言,这个脚本语言和大部分脚本语言长得非常接近,它的主要功能就是负责查询ES并做一些简单的运算处理,再把报警输出。当然也少不了一些逻辑判断。这个脚本兼顾了一些对ES的配置功能以及运算功能,它还提供了通过SQL语句进行查询的功能,查询完之后可以进行输出。
当时有人质疑为什么不用python。首先python的并发实现起来不太人性化,如果是线程并发可能会是一个伪线程,没有完全并发出来;如果用进程的话,写了很多报警规则,在调度的时候python可能就会挂了。于是我们开发了这一套脚本,在并发上达到几十万是没有问题的,这个脚本还可以根据它的语法自己定义功能。提供这个功能可以提高规则复用的程度。
规则
在报警的时候SQLAlert有两种工作方式,第一种是当作程序来跑,写完规则后在配置文件中加入,它自己就会慢慢进行调度,基本上300秒调度一次。另一个工作方式就是它作为代理,由用户来写代码,向SQLAlert发出请求,由它对ES进行查询,得到查询结果再返回给请求者。
实例一
固定阀值报警的时间范围是过去五分钟,报警条件是字节数超过200M或者总包数超过10000个。
如图所示,前两行是定义ES的主机地址和报警输出的索引信息。中间两行是定义阀值200M和10000个数据包。SQL语句用来计算总字节数和总包数。在查询后的返回语句是过去五分钟所有的SIP和DIP聚合之后的数据。在聚合的基础上还有一个过滤功能,就是总字节数和总包数大于定义的阀值,才会把结果输出来再写回到ES里面。
实例二
我们也不知道网络中的数据量到底有多大,只知道过去有相同的访问数据。这个示例的时间范围还是对过去五分钟的数据进行报警,参考时间是昨天的当前时间段之前的五分钟。报警条件是总字节数超过200M或者总包数超过10000个,且超过历史数据的50%。
实例三
这个示例是对一段数据的变化率进行报警。参考时间是过去四周内相同时刻的30分钟时间段,参考数据是历史数据的90%的百分位数。当变化率超过参考数据的2倍时会进行报警。
在一个公司内部网络流量波动非常大的情况下,可以把当前的变化率和昨天的变化率进行对比,如果超过了昨天的变化率可能就是一个报警。
总结
我们做的SQLAlert模块主要是对报警和报警风暴的抑制,报警风暴主要是通过ES本身来进行抑制。我们对报警输出做了两次输出,第一次输出的是接受者的ES,通过SQLAlert查询ES的告警索引,再进行第二次输出,这样输出的数量就大大减少了。
我今天的分享就到这里,谢谢大家!