Observability:如何有效地将应用日志发送到 Elasticsearch

 在今天的文章中,我们将探讨使用 3 种不同的架构发送应用的日子到 Elasticsearch。我们将详述它们的优缺点。更多关于日志架构的介绍,请参考 “Elastic:开发者上手指南” 中的 “Elastic Stack 架构” 部分。

介绍

采用 Elastic Stack,应用程序日志发送到 Elasticsearch 有三种不同架构,每种架构各有优缺点:

  • 应用程序 -> Filebeat -> Logstash -> Elasticsearch
  • 应用程序 -> Filebeat -> Elasticsearch
  • 应用程序 (Java) + Logstash-logback-encoder -> Logstash -> Elasticsearch

虽然可能还有其他发送日志的方法,但根据我的经验,将这些方法结合起来可以满足任何业务需求。

1)Application -> Filebeat -> Logstash -> Elasticsearch

这是将日志发送到 Elasticsearch 的标准方法,因为它为你提供了很多控制权。 你甚至可以更改将日志发送到另一个 Logstash 或 Elasticsearch 服务器的路径。 这是示例 filebeat.yml 配置文件:

filebeat.inputs:
- type: log
  paths:
    - "myapp.log"

output.logstash:
  hosts: ["192.168.1.1:4561"]

以及用于接收 Filebeat 日志的 logstash.conf 文件:

input {
  beats {
    port => "4561"
    host => "0.0.0.0"
  }
}

filter { }

output {
  elasticsearch {
    hosts => ["0.0.0.0:9200"]
    index => "app-logs-%{+YYYY.MM.dd}"
  }
}

这种架构的优点是:

  • 控制:你对日志采用的路径有很多控制权。我们可以在 Filebeat 中使用 Beat processors 来对数据进行处理,也可以使用 Logstash 丰富的过滤器来对数据进行加工。Logstash 可以对数据的摄入进行缓冲,并使用永久行队列对数据进行至少一次的发送。
  • 无需修改代码:你无需更改应用程序代码即可发送日志。

这种架构的缺点是:

扫描二维码关注公众号,回复: 15320998 查看本文章
  • 性能问题:存储日志涉及多个步骤,这会影响性能。
  • 磁盘加载:应用程序将日志写入文件,Filebeat 读取该文件。 当应用程序实例数量增加时,这可能会导致磁盘负载过重。

2)Application -> Filebeat -> Elasticsearch

使用这种方法,你可以从日志发送路径中消除 Logstash,并将日志直接发送到 Elasticsearch。 如果你的日志是 JSON 格式并且已清理,则此方法效果很好。

下面是一个示例 filebeat.yml 配置文件,它读取日志文件并将它们发送到 Elasticsearch:

filebeat.inputs:
- type: log
  paths:
    - "myapp.log"

output.elasticsearch:
  hosts: ["http://192.168.1.1:9200"] 

这种方法的优点:

  • 提高性能:通过消除 Logstash,你可以减少日志发送路径中的一个步骤。
  • 无需修改代码:你无需更改应用程序代码即可发送日志。

这种方法缺点:

  • 对日志修改的控制有限:Logstash 提供了许多工具,用于在将日志存储到 Elasticsearch 之前解析和清理日志。 没有它,你对日志修改的控制就会减少。

 3)Application (Java) + Logstash-logback-encoder -> Logstash -> Elasticsearch

如果你有 Java 应用程序,则可以使用这种方法将日志直接发送到 Logstash,而无需任何解释器。 确实可以在不需要 Filebeat 或其他节拍的情况下发送日志。

 为了能够将日志发送到 Logstash,你需要配置您的 Java 应用程序。 首先,将此依赖项添加到你的 pom.xml 文件中:

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.3</version>
    <scope>runtime</scope>
</dependency>

然后你需要像这样向你的 logback.xml 文件添加一个新的附加程序

<property name="STACK_TRACE_COUNT" value="15"/>
<property name="CLASS_NAME_LENGTH" value="40"/>

<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
   <destination>192.168.1.1:4560</destination>
   <addDefaultStatusListener>false</addDefaultStatusListener>

    <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
       <providers>
           <pattern>
               <pattern>{"app_name": "myapp", "app_version":"1.0.0", "hostname": "${HOSTNAME}"}</pattern>
           </pattern>
           <mdc/>
           <timestamp/>
           <message/>
           <threadName/>
           <logLevel/>
           <callerData/>
           <stackTrace>
               <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
                   <maxDepthPerThrowable>${STACK_TRACE_COUNT}</maxDepthPerThrowable>
                   <shortenedClassNameLength>${CLASS_NAME_LENGTH}</shortenedClassNameLength>
                   <rootCauseFirst>true</rootCauseFirst>
               </throwableConverter>
           </stackTrace>
       </providers>
   </encoder>
</appender>


<root level="${ROOT_LEVEL}">
   <appender-ref ref="CONSOLE"/>
   <appender-ref ref="LOGSTASH"/>
</root>

我们使用 LogstashTcpSocketAppender 类而不是 UDP 类,因为我需要确保在将日志发送到 Logstash 的过程中不会丢失任何日志。 但是,如果你不关心这种级别的可靠性,则可以使用 UDP。

另一方面,Logstash 应该配置为接收日志,并将它们存储在 Elasticsearch 等位置。 这是我当前使用的示例 Logstash 配置:

input {
    tcp {
        port => 4560
        codec => json_lines
    }
}

filter { }

output {
    
    elasticsearch {
        hosts  => ["http://elasticsearch:9200"]
        index  => "operationlog-%{app_name}-%{+YYYY-MM-dd}"
    }   
}

这个方法的优点:

  • 性能提升:通过将日志直接发送到 Logstash 而不是将它们存储在磁盘上,这种方法与以前的方法相比具有更少的开销。

这个方法的缺点:

  • 限制:logstash-logback-encoder 只能与 Java 应用程序一起使用。
  • 代码修改要求:要使用这种方法,你需要修改应用程序代码。
     

针对 Python 应用,你可以参考文章 “Elasticsearch:运用 Python 实时通过 Logstash 写入日志到 Elasticsearch

其它方法

结论

你可以将上述所有方法组合到一个架构中,如下所示:

如果要从 Java 应用程序发送日志,可以使用 logstash-logback-encoder 将它们直接发送到 Logstash,而无需将它们存储在磁盘上。

清理 Python 或 NodeJS 应用日志路径中的数据,可以结合使用 Filebeat 和 Logstash。 但是,如果你的数据已经是 JSON 格式,则无需使用 Logstash。 你只需将日志发送到 Filebeat,然后 Filebeat 会将它们存储在 Elasticsearch 中。

特别指出:针对日志中的数据处理,除了使用 Filebeat 中的 processors 以及 Logstash 中的过滤器,我们还可以使用 Elasticsearch 摄入节点所提供的 ingest pipeline 来对数据进行清洗。

更多阅读:Beats:Elastic Beats 介绍 及和 Logstash 的比较​​​​​​​

猜你喜欢

转载自blog.csdn.net/UbuntuTouch/article/details/131100088