ITPub博客

首页 > IT基础架构 > > ELK规范使用

ELK规范使用

作者:格伯纳 时间:2020-05-29 11:36:53 0 删除 编辑

ELK的灵活性、使用场景,在很多文章中都有介绍,包括官方文档。当你看到这篇文章时,我假设你已经知道你要用ELK解决什么问题。

其实,正是ELK提供的灵活性,特别是早期提供的傻瓜式用法(schemaless),让很多人认为使用ELK没有任何约束。有些弊端在数据量小的时候没有感知,有些弊端在非精细化使用时也不会注意到。

这篇文档主要想讨论:在大规模使用下,需要注意的一些基本约定,这些约定对管理和使用体验上的价值。


日志的类型

很多同学其实没有想过这个问题,或者没有站着数据分析的维度去想过这个问题。数据化运营已经是如今互联网公司最核心的能力之一。传统的公司,很多数据分析的数据都是来自数据库。而互联网公司,有大量的数据来自日志,量级可能是数据库的几十到上百倍。所以,从大的方面,日志至少分为两类:

1、业务日志

来自业务需求所做的埋点日志,这种日志类似数据库表,只是通过日志形式收集,提升效率。

2、研发运维日志

(1)研发同学分析系统性能指标等埋点日志

(2)研发同学诊断系统问题的Trace日志、各种开源软件等产生的系统日志

当把日志进行了分类之后,其实日志规范就很容易制定了,而且这样分也方便后续架构改进、容灾降级、故障评估等各种需求,因为毕竟业务日志是最重要的。


日志收集架构

日志收集的架构大同小异,每个组件也会随着需求不断迭代和优化,ELK基本pipeline如下:

用户把日志打到磁盘上,我们通过logstash从磁盘把日志实时的收集放入kafka。在kafka中的日志,平台会根据用户需求选择性的同步到hive和elasticsearch。同步到Elasticsearch的日志,用户可以实时检索和分析。


日志收集规范

存放规范

根据上面的日志分类,对于两类日志,我们按照不同的路径存放,具体存放路径如下:

  • 业务日志:/opt/logs/_data_/{topic_name}/{file_name}.event
  • 研发运维日志:/opt/logs/_logs_/{topic_name}/{file_name}.log

我们会使用{topic_name} 作为kafka上的topic_name和hive上的table_name;

对于第三方系统日志,如mysql,mongodb,redis等,如果能做变更最好也按照研发运维日志规范存放,如果已经投产无法变更,目前只能做hardcode适配;


日志的命名规范

建议日志命名(topic_name)规则为:

{business_name}_{service_name}_{optional}

示例:

业务日志:bike_order_api

研发运维日志:bike_order_error

日志切分和过期处理策略

因为业务日志会动态增长,按照size切割并设置maxBackup可能因为日志量太大存在覆盖写问题。建议使用DailyRollingFileAppender,不限定单个文件大小。


日志内容格式规范

  • 业务日志

预定义schema,统一使用json格式输出

  • 研发运维日志

分三种情况:

(1)应用程序主动打印的debug日志

必须遵循标准的规范日志格式,这样输出的日志易于通过字段过滤、聚合并追踪问题,需要stackTrace的只要把stack做format输出即可。格式如下:

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n

其中msg部分必须json格式化输出

a. 看起来规范的个性化日志

2017-12-07 13:19:09,155 INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping orderId: 1, userId:30; paid:1, exception: failed to ....
2017-12-07 13:19:09,155 INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping orderId=1, userId=30, paid=1, exception: failed to ....

b. 标准的规范日志

2017-12-07 13:19:09,155 INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping {"orderId": 1, "userId":30, "payed":1, "exception":"failed to ....."}

a和b的差别在于:

a 对人友好,但对机器不友好,机器没法自动化识别每个字段的提取规则。为了适配规则,需要花费额外的代价维护规则引擎,并且因为规则引擎没有明确约束,很容易因为用户改变的内容导致引擎失效。例子中,有些日志key,value用“=”号分割,有些用“:”分割,如果整条日志不做切割,对于userId=30这样的查询没法有效执行。

b 可以自解析,不管张三还是李四打的,都可以用一套解析逻辑解析出每个需要的字段,并写入Elasticsearch方便查询。比如:查询userId=30的订单链路;

(2)框架输出日志

这类日志可控性较差,可用的形式需要探索,但也要遵循标准的日志format格式,如有需要,收集的时候可以在头部加上机器hostname等信息

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n

(3)第三方系统日志

目前只能hardcode适配解析,因为格式较为稳定,也不会变更schema。


实践与效果

安装ELK外部已经有各种资料,可以根据自身运维规范选择rpm还是tar包安装,重点讲下对应上面规范进行的配置和使用效果。

logstash配置

input {

    file {
        path => "/opt/logs/_data_/*/*.event"
        type => "data"
    }

    file {
        path => "/opt/logs/_logs_/*/*.log"
        type => "logs"
    }

    file {
        path => "/opt/logs/*-advertisement-*.log"
        type => "advertisement"
        codec => multiline {
                 pattern => "^20"
                 negate => true
                 what => previous
              }
        }
}

filter {

    if [type] == "data" {
        grok {
          match => { "path" => "/opt/logs/_data_/(?<category>[a-zA-Z0-9._-]+)/*" }
        }
    }
    if [type] == "logs" {
        grok {
          match => { "path" => "/opt/logs/_logs_/(?<category>[a-zA-Z0-9._-]+)/*" }
        }
    }

}
output {
    if [type] == "data" {
        kafka {
            codec => plain {
             format => "%{message}"
            }
            topic_id => "%{category}"
            batch_size => 2000
            buffer_memory =>  335544320
            bootstrap_servers =>  "xxxx:9092"
            retries => 3
          }
    }

    else if [type] == "logs" {
        kafka {
            codec => plain {
             format => "%{message} ${HOSTNAME}"
            }
            topic_id => "log.%{category}"
            batch_size => 2000
            buffer_memory =>  335544320
            bootstrap_servers =>  "xxxxx:9092"
            retries => 3
          }
    }
    else  {
        kafka {
            codec => plain {
             format => "%{message}"
            }
            topic_id => "%{type}"
            batch_size => 2000
            buffer_memory =>  335544320
            bootstrap_servers =>  "xxxx:9092"
            retries => 3
          }
    }
}

配置中的path => "/opt/logs/*-advertisement-*.log",就是为了解决第三方系统的日志,大家也知道,如果所有的日志都没有规范路径,每增加一个日志将要变更一次配置,运维成本非常高。

kibana对比效果

(1)日志内容格式不规范,没有切割字段效果

(2)日志内容格式规范,切割字段效果

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31509949/viewspace-3165551/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: BGP漫谈
请登录后发表评论 登录
全部评论
管理员

注册时间:2018-03-30

  • 博文量
    2383
  • 访问量
    984284