【问题标题】:Application logging with ELK stack使用 ELK 堆栈进行应用程序日志记录
【发布时间】:2017-04-09 23:35:34
【问题描述】:

使用 NLog 和 Elasticsearch target 将日志转发到 AWS Elasticsearch as a Service 集群,以便在 Kibana 中进行可视化。

这工作正常,但由于 ES 集群可用性和集群故障转移的影响,当日志通过 HTTP 使用 elasticsearch-net client 发送时,我担心在生产中使用它。

我正在考虑为 NLog 使用不同的目标,将日志发送到更可靠的目的地(文件、S3?),然后让其他东西(Logstash、AWS Lambda)接收它们并将它们发送到 ES,这样可以最大限度地减少应用程序本身的风险。

想听听你的想法

更新

主要关注的是应用可用性,并使用辅助目标来防止丢失日志。

Using latest NLog 和 throwExceptions 设置为 false,此时不使用异步目标,但考虑到这一点,因为我们有很多异步代码。

为了提供更多上下文,“应用程序”是一组 API(WebAPI 和 WCF),它们的转速为 10 - 15K RPM。

场景

请求进来,ES集群不可用。

案例 1 - 没有异步目标的 NLog

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
        autoReload="true"
        throwExceptions="false"
        internalLogLevel="Off"
        internalLogFile="c:\temp\nlog-internal.log">

    <targets>
      <target name="elastic"
              xsi:type="BufferingWrapper"
              flushTimeout="5000">
        <target xsi:type="ElasticSearch"
                layout="${logger} | ${threadid} | ${message}"
                index="logstash-${date:format=yyyy.MM.dd}"
                includeAllProperties="true"
                uri="...">

          <field name="user"
                 layout="${windows-identity:userName=True:domain=False}"/>
          <field name="host"
                 layout="${machinename}"/>
          <field name="number"
                 layout="1"
                 layoutType="System.Int32"/>

        </target>
      </target>
    </targets>
    <rules>
      <logger name="*"
              minlevel="Debug"
              writeTo="elastic" />
    </rules>
  </nlog>

问:

  • 当无法达到目标时,主线程会发生什么?

案例 2 - 带有异步目标的 NLog

对带有 queueLimit="10000" batchSize="100" 的弹性搜索目标使用异步包装器

问:

  • 是否创建了另一个线程[B]?
  • 后续请求是否会重用线程 [B] 并对日志记录请求进行排队?
  • 达到 queueLimit 时会发生什么?
  • 是否会启动其他线程 [B1 ... Bn]? (这将淹没连接池)

【问题讨论】:

    标签: .net amazon-s3 scalability nlog elastic-stack


    【解决方案1】:

    好问题。

    没什么好担心的,但是正确配置 NLog 很重要。

    不确定什么应该是可靠的,运行程序或不丢失日志消息,所以对于这些情况:

    • 如果你害怕丢失一些日志消息

      • 写入多个目标(来自 NLog),例如文件 Elasticsearch。
      • 可选,使用 fallbackgroupwrapper(以防写入目标时出错)
      • 如果启用异步,check the overflow/queue settings - 默认启用丢弃(以防止 CPU 或内存过载)
    • 如果您担心日志记录会破坏您的应用程序:

      • 使用最新的稳定版 NLog
      • 不要启用throwExceptions(默认禁用)
      • 如果您启用async,错误将写入另一个线程中的目标,因此它不会破坏您的应用程序。
      • 当使用asynccheck the overflow and queue settings

    更新

    案例一,

    当无法达到目标时,主线程会发生什么?

    什么都没有。主程序将消息排入缓冲区。另一个 (Timer) 线程正在处理这些消息。如果这将失败,并且throwException 未启用,则只会将错误写入 internalLog(启用时)。所有异常都会被捕获。写入目标失败时,您将丢失消息。

    案例 2,

    是否创建了另一个线程[B]?

    将创建一个Timer。这将创建一个线程来处理消息。

    后续请求是否会重用线程 [B] 并将日志记录请求排队?

    是的,但不能保证它会是同一个线程。计时器将从池中创建一个线程。注意:只有一个线程会同时处于活动状态。

    达到 queueLimit 时会发生什么?

    取决于您的配置。默认情况下,它会默认丢弃,如上所述。见check the overflow/queue settings。就内存和 CPU 而言,这是最安全的选择。您可以选择丢弃、阻塞(停止主线程)或增加队列(通过了解内存使用情况)。

    会启动额外的线程 [B1 ... Bn] 吗? (这将淹没连接池)

    没有。 1个定时器,1个线程池。详情请查看MSDN page for Timerreference source

    【讨论】:

    • 没有考虑 throwExceptions 标志。感谢您指出了这一点!我已经更新了问题,你能再看看吗?
    猜你喜欢
    • 2019-11-26
    • 2015-09-28
    • 2016-08-27
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    相关资源
    最近更新 更多