Logstash实践: 分布式系统的日志监控

配图:中山公园正门街景 摄影: 怡文圣美

文/怡文圣美
2015.11.04

1. 前言

服务端日志你有多重视?

  1. 我们没有日志
  2. 有日志,但基本不去控制需要输出的内容
  3. 经常微调日志,只输出我们想看和有用的
  4. 经常监控日志,一方面帮助日志微调,一方面及早发现程序的问题

只做到第1点的,你可以洗洗去睡了。很多公司都有做到第2点和第3点,这些公司的服务端程序基本已经跑了很长时间了,已比较稳定,确实无需花太多时间去关注。如果一个新产品,在上线初期,我觉得就有必要做到第4点。

日志怎么看?

  1. 都说了,我们没有日志
  2. 线上日志逐个tail+grep
  3. 编写脚本,下载某个时间范围内的全部日志到本地再搜索

tail+grep或者把日志下载下来再搜索,可以应付不多的主机和不多的应用部署场景。但对于多机多应用部署就不合适了。这里的多机多应用指的是同一种应用被部署到几台服务器上,每台服务器上又部署着不同的多个应用。可以想象,这种场景下,为了监控或者搜索某段日志,需要登陆多台服务器,执行多个tail -Fgrep命令。一方面这很被动。另一方面,效率非常低,数次操作下来,你心情也会变糟。

这篇文章讲的就是如何解决分布式系统的日志管理问题。先给大家看看最终的效果:

日志实时监控效果图

单个屏幕上所有服务器的日志实时滚动着显示。每条日志开头还标明日志的来源(下图)。

每行日志标有来源信息

实现这种效果的原理是后台跑着一个程序,这个程序负责汇总所有日志到一个本地文件中。只要执行tail -f这个文件就可以做到监控日志了。因为所有日志都汇总在一个文件里了,所以日志搜索的时候只要搜索这一个文件就可以了。

本文介绍的,能够汇总日志文件的工具名字叫Logstash。使用JRuby编写,开源,主流,免费,使用简单。

2. Logstash部署架构

Logstash的理念很简单,它只做3件事情:

  1. Collect:数据输入
  2. Enrich:数据加工,如过滤,改写等
  3. Transport:数据输出

别看它只做3件事,但通过组合输入和输出,可以变幻出多种架构实现多种需求。这里只抛出用以解决日志汇总需求的部署架构图:

Logstash部署架构

解释术语:

  • Shipper:日志收集者。负责监控本地日志文件的变化,及时把日志文件的最新内容收集起来,输出到Redis暂存。
  • Indexer:日志存储者。负责从Redis接收日志,写入到本地文件。
  • Broker:日志Hub,用来连接多个Shipper和多个Indexer。

无论是Shipper还是Indexer,Logstash始终只做前面提到的3件事:

  • Shipper从日志文件读取最新的行文本,经过处理(这里我们会改写部分元数据),输出到Redis,
  • Indexer从Redis读取文本,经过处理(这里我们会format文本),输出到文件。

一个Logstash进程可以有多个输入源,所以一个Logstash进程可以应付一台服务器上的所有日志。Redis是Logstash官方推荐的Broker角色“人选”,支持订阅发布和队列两种数据传输模式,推荐使用。输入输出支持过滤,改写。Logstash支持多种输出源,可以配置多个输出实现数据的多份复制,也可以输出到Email,File,Tcp,传递给其他程序作为输入,或者安装插件实现和其他系统的对接,如搜索引擎Elasticsearch。

总结:Logstash概念简单,通过组合可以满足多种需求。

3. Logstash的安装,搭建和配置

3.1. 安装Java

下载JDK压缩包。
一般解压到/user/local/下,形成/usr/local/jdk1.7.0_79/bin这种目录结构。
配置JAVA_HOME环境变量:echo 'export JAVA_HOME=/usr/local/jdk1.7.0_79' >> ~/.bashrc

3.2 安装Logstash

官网下载Logstash的压缩包。
一般也解压到/usr/local/下,形成/usr/local/logstash-1.4.3/bin这种目录结构。

Logstash的运行方式为主程序+配置文件。Collect,Enrich和Transport的行为在配置文件中定义。配置文件的格式有点像json,又有点像php。

3.3. 编写Shipper角色的配置文件:shipper.conf
input {
    file {
        path => [
            # 这里填写需要监控的文件
            "/data/log/php/php_fetal.log",
            "/data/log/service1/access.log"
        ]
    }
}

如上,input描述的就是数据如何输入。这里填写你需要收集的本机日志文件路径。

output {
    # 输出到控制台
    # stdout { }

    # 输出到redis
    redis {
        host => "10.140.45.190"   # redis主机地址
        port => 6379              # redis端口号
        db => 8                   # redis数据库编号
        data_type => "channel"    # 使用发布/订阅模式
        key => "logstash_list_0"  # 发布通道名称
    }
}

如上,output描述的就是数据如何输出。这里描述的是输出到Redis

data_type的可选值有channellist两种。用过Redis的人知道,channel是Redis的发布/订阅通信模式,而list是Redis的队列数据结构。两者都可以用来实现系统间有序的消息异步通信。channel相比list的好处是,解除了发布者和订阅者之间的耦合。举个例子,一个Indexer在持续读取Redis中的记录,现在想加入第二个Indexer,如果使用list,就会出现上一条记录被第一个Indexer取走,而下一条记录被第二个Indexer取走的情况,两个Indexer之间产生了竞争,导致任何一方都没有读到完整的日志。channel就可以避免这种情况。这里的Shipper和下面将要提到的Indexer配置文件中都使用了channel

filter {
    mutate {
        # 替换元数据host的值
        replace => ["host", "10.140.46.134 B[1]"]
    }
}

如上,filter描述的是如何过滤数据。mutate是一个自带的过滤插件,它支持replace操作,可以改写数据。这里改写了元数据中的host字段,替换成了我们自己定义的文本。

Logstash传递的每条数据都带有元数据,如@version,@timestamp,host等等。有些可以修改,有些不允许修改。host记录的是当前的主机信息。Logstash可能不会去获取主机的信息或者获取的不准,这里建议替换成自己定义的主机标示,以保证最终的日志输出可以有完美的格式。

3.4 编写Indexer角色的配置文件:indexer.conf
input {
    redis { 
        host      => "10.140.45.190"    # redis主机地址
        port      => 6379               # redis端口号
        db        => 8                  # redis数据库编号
        data_type => "channel"          # 使用发布/订阅模式
        key       => "logstash_list_0"  # 发布通道名称
    } 
}

如上,input部分设置为从redis接收数据

output { 
    file { 
        path           => "/data/log/logstash/all.log" # 指定写入文件路径
        message_format => "%{host} %{message}"         # 指定写入格式
        flush_interval => 0                            # 指定刷新间隔,0代表实时写入
    }
}

如上,output部分设置为写入本地文件

官方文档里flush_interval为缓冲时间(单位秒)。我实践下来不是秒而是数量,Logstash会等待缓冲区写满一定数量后才输出。这对线上调试是不能接受的,建议上线初期设为0。程序稳定后,随着日志量的增大,可以增大flush_interval的值以提高文件写入性能。

Indexer的配置文件中,我明确指定了message_format的格式,其中%{host}对应的就是之前手动设置的host元数据。

3.5. 启动Logstash
# 先在Indexer主机上启动
nohup /usr/local/logstash-1.4.3/bin/logstash agent -f indexer.conf &>/dev/null &
# 再在Shipper主机上启动
nohup /usr/local/logstash-1.4.3/bin/logstash agent -f shipper.conf &>/dev/null &
# 最后在Indexer上观察日志
tail -f /data/log/logstash/all.log

我们来测试一下,切到Shipper主机上,模拟日志产生:

echo "Hello World" >> /data/log/php/php_fetal.log

再切换到Indexer主机上,如果出现:10.140.46.134 B[1] Hello World,说明Logstash部署成功。

3.6. 日志着色脚本

使用awk配合echo,可以匹配你想要高亮的文本并改变他们的前景色和背景色。就像效果图里的那样。这里附上我写的脚本,把脚本中的关键信息替换成你想要匹配的文本即可:

tail -f /data/log/logstash/all.log | awk '{ 
     if (match($0, /.*(PHP Deprecated|PHP Notice|PHP Fatal error|PHP Warning|ERROR|WARN).*/)) { print "\033[41;37;1m"$0"\033[0m" } 
else if (match($0, /.*关键信息1.*/)) { print "\033[32;1m"$0"\033[0m" } 
else if (match($0, /.*关键信息2.*/)) { print "\033[36;1m"$0"\033[0m" }
else { print $0 } }'

So easy,妈妈再也不用担心我的日志。。。

4. 还有什么

有些公司需要挖掘日志的价值,那仅仅收集和实时显示是不够的,需要把逼格上升到日志分析技术层面。

一个完整的日志分析技术栈需要实时收集,实时索引和展示三部分组成,Logstash只是这其中的第一个环节。Logstash所属的Elastic公司,已经开发了完整的日志分析技术栈,它们是Elasticsearch,Logstash,和Kibana,简称ELK。Elasticsearch是搜索引擎,而Kibana是Web展示界面。

日志分析技术栈

如果你搭建了完整的技术栈,你的老板就可以在图形化界面上按不同的维度去搜索日志了。

Kibana界面

还可以做一些高大上的统计和计算。

Kibana界面

当然,我认为90%的公司是没有必要这么做的,能做到在控制台里监控和搜索就能满足需要了。但我们也可以看看剩下的那10%的公司是怎么做的,比如:新浪是如何分析处理32亿条实时日志的?


参考文献:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • 本期简说提高软件产品质量有三个方面需要把握(本篇文章谈ELK的使用): 一、持续集成 二、自动化 三、ELK日志分...
    隔壁老田_阅读 2,412评论 0 2
  • 概述 监控预警平台, eagle + eye (鹰眼)的合体词, 寓意可以快速发现问题, 并及时作出响应,Eagl...
    Kungfu猫熊阅读 7,333评论 0 52
  • //聊聊Flume和Logstash的那些事儿 - 简书http://www.jianshu.com/p/349e...
    葡萄喃喃呓语阅读 5,372评论 1 12
  • 上个周末,我和孩子一起去参加了杨之光美术中心的写生课。这次的写生活动安排在上海自然博物馆。 这是崽崽...
    solarxue阅读 1,105评论 0 0