扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
作为中国最大的在线教育站点,目前沪江日志服务的用户包含网校,交易,金融,CCTalk 等多个部门的多个产品的日志搜索分析业务,每日产生的各类日志有好十几种,每天处理约10亿条(1TB)日志,热数据保留最近7天数据,冷数据永久保存。
成都创新互联服务项目包括召陵网站建设、召陵网站制作、召陵网页制作以及召陵网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,召陵网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到召陵省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
首先,什么是日志? 日志就是程序产生的,遵循一定格式(通常包含时间戳)的文本数据
通常日志由服务器生成,输出到不同的文件中,一般会有系统日志、 应用日志、安全日志。这些日志分散地存储在不同的机器上。
通常当系统发生故障时,工程师需要登录到各个服务器上,使用 grep / sed / awk 等 Linux 脚本工具去日志里查找故障原因。在没有日志系统的情况下,首先需要定位处理请求的服务器,如果这台服务器部署了多个实例,则需要去每个应用实例的日志目录下去找日志文件。每个应用实例还会设置日志滚动策略(如:每天生成一个文件),还有日志压缩归档策略等。
这样一系列流程下来,对于我们排查故障以及及时找到故障原因,造成了比较大的麻烦。因此,如果我们能把这些日志集中管理,并提供集中检索功能,不仅可以提高诊断的效率,同时对系统情况有个全面的理解,避免事后救火的被动。
我认为,日志数据在以下几方面具有非常重要的作用:
针对这些问题,为了提供分布式的实时日志搜集和分析的监控系统,我们采用了业界通用的日志数据管理解决方案 - 它主要包括 Elasticsearch 、 Logstash 和 Kibana 三个系统。通常,业界把这套方案简称为ELK,取三个系统的首字母,但是我们实践之后将其进一步优化为EFK,F代表Filebeat,用以解决Logstash导致的问题。下面,我们展开详细介绍。
文中涉及的 ELK stack 版本是:
Elasticsearch 5.2.2
Logstash 5.2.2
Kibana 5.2.2
Filebeat 5.2.2
Kafka 2.10
Logstash:数据收集处理引擎。支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储以供后续使用。
Kibana:可视化化平台。它能够搜索、展示存储在 Elasticsearch 中索引数据。使用它可以很方便的用图表、表格、地图展示和分析数据。
Elasticsearch:分布式搜索引擎。具有高可伸缩、高可靠、易管理等特点。可以用于全文检索、结构化检索和分析,并能将这三者结合起来。Elasticsearch 基于 Lucene 开发,现在使用最广的开源搜索引擎之一,Wikipedia 、StackOverflow、Github 等都基于它来构建自己的搜索引擎。
Filebeat:轻量级数据收集引擎。基于原先 Logstash-fowarder 的源码改造出来。换句话说:Filebeat就是新版的 Logstash-fowarder,也会是 ELK Stack 在 shipper 端的第一选择。
既然要谈 ELK 在沪江系统中的应用,那么 ELK 架构就不得不谈。本次分享主要列举我们曾经用过的 ELK 架构,并讨论各种架构所适合的场景和优劣供大家参考
这种架构下我们把 Logstash 实例与 Elasticsearch 实例直接相连。Logstash 实例直接通过 Input 插件读取数据源数据(比如 Java 日志, Nginx 日志等),经过 Filter 插件进行过滤日志,最后通过 Output 插件将数据写入到 ElasticSearch 实例中。
这个阶段,日志的收集、过滤、输出等功能,主要由这三个核心组件组成 Input 、Filter、Output
Input:输入,输入数据可以是 File 、 Stdin(直接从控制台输入) 、TCP、Syslog 、redis 、Collectd 等
Filter:过滤,将日志输出成我们想要的格式。Logstash 存在丰富的过滤插件:Grok 正则捕获、时间处理、JSON 编解码、数据修改 Mutate 。Grok 是 Logstash 中最重要的插件,强烈建议每个人都要使用 Grok Debugger 来调试自己的 Grok 表达式
grok {
match => ["message", "(?m)\[%{LOGLEVEL:level}\] \[%{TIMESTAMP_ISO8601:timestamp}\] \[%{DATA:logger}\] \[%{DATA:threadId}\] \[%{DATA:requestId}\] %{GREEDYDATA:msgRawData}"]
}
Output:输出,输出目标可以是 Stdout (直接从控制台输出)、Elasticsearch 、Redis 、TCP 、File 等
这是最简单的一种ELK架构方式,Logstash 实例直接与 Elasticsearch 实例连接。优点是搭建简单,易于上手。建议供初学者学习与参考,不能用于线上的环境。
这种架构下我们采用多个 Elasticsearch 节点组成 Elasticsearch 集群,由于 Logstash 与 Elasticsearch 采用集群模式运行,集群模式可以避免单实例压力过重的问题,同时在线上各个服务器上部署 Logstash Agent,来满足数据量不大且可靠性不强的场景。
数据收集端:每台服务器上面部署 Logstash Shipper Agent 来收集当前服务器上日志,日志经过 Logstash Shipper 中 Input插件、Filter插件、Output 插件传输到 Elasticsearch 集群
数据存储与搜索:Elasticsearch 配置默认即可满足,同时我们看数据重要性来决定是否添加副本,如果需要的话,最多一个副本即可
数据展示:Kibana 可以根据 Elasticsearch 的数据来做各种各样的图表来直观的展示业务实时状况
这种架构使用场景非常有限,主要存在以下两个问题
这个架构相对上个版本略微复杂,不过维护起来同样比较方便,同时可以满足数据量不大且可靠性不强的业务使用。
该场景下面,多个数据首先通过 Lostash Shipper Agent 来收集数据,然后经过 Output 插件将数据投递到 Kafka 集群中,这样当遇到 Logstash 接收数据的能力超过 Elasticsearch 集群处理能力的时候,就可以通过队列就能起到削峰填谷的作用, Elasticsearch 集群就不存在丢失数据的问题。
目前业界在日志服务场景中,使用比较多的两种消息队列为 :Kafka VS Redis。尽管 ELK Stack 官网建议使用 Redis 来做消息队列,但是我们建议采用 Kafka 。主要从下面两个方面考虑:
综合上述的理由,我们决定采用 Kafka 来缓冲队列。不过在这种架构下仍然存在一系列问题
这种架构适合较大集群的应用部署,通过消息队列解决了消息丢失、网络堵塞的问题。
随着沪江业务的飞速增长,单机房的架构已经不能满足需求。不可避免的,沪江的业务需要分布到不同机房中,对于日志服务来说也是不小的挑战。当然业界也有不少成熟的方法,比如阿里的单元化、腾讯的 SET 方案等等。单元化在这边不详细展开,大家可以参考微博的【单元化架构】
最终我们决定采用单元化部署的方式来解决 ELK 多机房中遇到的问题(延时、专线流量过大等),从日志的产生、收集、传输、存储、展示都是在同机房里面闭环消化,不存在跨机房传输与调用的问题。因为交互紧密的应用尽量部署在同机房,所以这种方案并不会给业务查询造成困扰。
Logstash、Elasticsearch、Kafka、Kibana 四个集群都部署到同一机房中,每个机房都要每个机房自己的日志服务集群,比如A机房业务的日志只能传输给本机房 Kafka ,而A机房 Indexer 集群消费并写入到A机房 Elasticsearch 集群中,并由A机房 Kibana 集群展示,中间任何一个步骤不依赖B机房任何服务。
Filebeat 是基于原先 logstash-forwarder 的源码改造出来的,无需依赖 Java 环境就能运行,安装包10M不到。
如果日志的量很大,Logstash 会遇到资源占用高的问题,为解决这个问题,我们引入了Filebeat。Filebeat 是基于 logstash-forwarder 的源码改造而成,用 Golang 编写,无需依赖 Java 环境,效率高,占用内存和 CPU 比较少,非常适合作为 Agent 跑在服务器上。
下面看看Filebeat的基本用法。编写配置文件,从 Nginx access.log 中解析日志数据
# filebeat.yml
filebeat.prospectors:
- input_type: log
paths: /var/log/nginx/access.log
json.message_key:
output.elasticsearch:
hosts: ["localhost"]
index: "filebeat-nginx-%{+yyyy.MM.dd}"
我们来看看压测数据
Logstash / Filebeat 读取 350W 条日志 到 console,单行数据 580B,8个进程写入采集文件
项目 | workers | cpu usr | 总共耗时 | 收集速度 |
---|---|---|---|---|
Logstash | 8 | 53.7% | 210s | 1.6w line/s |
Filebeat | 8 | 38.0% | 30s | 11w line/s |
Filebeat 所消耗的CPU只有 Logstash 的70%,但收集速度为 Logstash 的7倍。从我们的应用实践来看,Filebeat 确实用较低的成本和稳定的服务质量,解决了 Logstash 的资源消耗问题。
最后,分享给大家一些血泪教训,希望大家以我为鉴。
突然有一天监控发现日志不消费了,排查下来发现消费Kafka数据的indexer 挂掉了。所以,Indexer 进程也是需要用 supervisor 来监控的,保证它时刻都在运行。
开始我们在通过 grok 切割日志的时候,发现Java 的 Exception 日志输出之后,会出现换行的问题。后来使用 Logstash codec/multiline插件来解决。
input {
stdin {
codec => multiline {
pattern => "^\["
negate => true
what => "previous"
}
}
}
Logstash 2.3版本 date插件配置如下,查看解析结果发现@timestamp比中国时间早了8小时。
解决方案 Kibana 读取浏览器的当前时区,然后在页面上转换时间内容的显示。
date {
match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss.SSS" ]
target => "@timestamp"
}
我们遇到线上node日志突然有几天日志查看不出来。后来拉出原始日志对比才发现生成出来的日志格式不正确,同时包含 JSON 格式和非 JSON格式的日志。但是我们用grok解析的时候采用是json格式。建议大家输出日志保证格式一致同时不要出现空格等异常字符,可以使用在线grok debug (http://grokdebug.herokuapp.com/) 来调试正则。
基于 ELK stack 的日志解决方案的优势主要体现于
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流