繁体   English   中英

Java - 记录多节点环境中的最佳实践

[英]Java - Logging best practices in multi-node environment

在我的公司,我在一个多节点基础设施中管理一个大型应用程序(> 100k用户),由3个(但可能更多)应用程序服务器组成。 每个应用程序服务器都有5个不同的日志文件,其中几乎记录了有关http / s(REST或SOAP)请求和对其他(外部)子系统的响应的每个信息。 我使用Apache Http客户端来处理REST流,将wsimport生成的客户端用于SOAP请求,使用Logback作为日志记录技术。

目前,当我被要求调试某些东西时,我要做的最复杂和最耗时的任务是确定我必须调试的节点。 在那之后,为了发现发生了什么,我必须实际上使用大量的线条。 说实话,我发现它非常无聊和过时,也很复杂。

为了让我的生活更轻松,让我的日志变得更有趣,我过去几天在弹性搜索堆栈(elasticsearch,logstash,kibana)上看了一下,并使用他们的docker图像进行了游戏。 我发现它们非常有趣,我想在我的应用程序中介绍它们但在此之前我想知道是否有最佳实践/模式来做类似的事情。

这些是我的疑惑:

  • 是否有一种最佳实践来记录Http / s REST和SOAP请求/响应(我需要查看所有内容:url,headers,path,body,cookies,...),格式可以通过logstash / elasticsearch轻松解析?
  • 考虑到我的基础设施,我应该使用elasticsearch appender进行我的logback实现,还是使用Logstash作为日志处理器(我想每个应用服务器都有一个)?
  • 是否有有效的logback和elasticsearch技术替代方案来满足我的要求?

我不指望一个简单易行的答案。 我想了解不同的经验,以便做出最适合我的解决方案的选择

谢谢!

这是一个复杂的答案:) ELK堆栈绝对可以让你的生活在分布式环境中更容易。 但是,为了从中受益,您可以考虑以下做法:

  • 在ElasticSearch的日志消息中,您应该看到以下内容(除了明显的时间,级别,消息本身):

    • 生成大量消息的服务器
    • 发起请求的用户
    • 如果您的申请是多租户 - 请求已经进行的租户
  • 所有消息应该具有相同的结构(布局)

  • 由于您使用Java,异常可能成为一个潜在的问题(它们是多线的),因此需要特殊处理。 Logstash可以处理它

  • 如果您的流可以分布在不同的服务器上(您说您有3个且可能更多),请考虑为每个请求生成一个特殊的相关ID。 一些可以识别流量的随机数。

所有这些都有助于应用过滤器并从Elastic Search中获益更多。

考虑将TTL用于日志。 可能您不需要在超过一周或两周之前保留创建的日志。

现在关于HTTP请求。 通常只记录所有内容可能是一个安全问题,因为您无法确定是否会记录某些“敏感”信息。 所以你要保持这种保护(至少你的安全人员会想:))。 可能记录URL,服务器,http方法和一些用户标识符(或者如果需要的话,租户)就足够了,但这完全是我的意见。

现在关于appender vs logstash(文件)方法。 这两种方法都有优点和反差。 例如:如果使用logstash方法,则必须解析日志文件的每一行。 如果您的应用程序生成许多日志,它可能会影响性能,因为解析可以通过CPU costy(特别是如果您在logstash中使用grok过滤器)。 另一方面 - appenders允许完全避免解析(你将在java中的内存中获得所有信息)。

另一方面,应仔细设置appender。 我没有使用logback Elasticsearch appender的经验,但我认为它至少应该是:

  • 异步(否则您的业务流程可能会卡住)
  • 能够应对失败(你不会因为当前的ES不可用或其他东西而抛出异常。最终用户不应该真正感受到这一点)。
  • 可能维护一些队列/使用干扰器,只是因为你可以产生比你的appender可能发送给ES更多的日志,所以最终日志消息将丢失。 例如,如果您有一个大小为1000的队列,并且日志中有超过1000条消息,则可以映像FIFO将执行的操作。

还有一件事需要考虑:让我们想象一下,由于某些原因,其中一个应用服务器存在问题。 所以你可能想要重新启动它(优雅与否)。 如果你使用im-memory appender这些消息会发生什么? 你想在ElasticSearch中看到它们来分析post mortum吗? 因此,底线内存中的方法无法处理重启。

另一方面,logstash进程将很乐意处理存储在文件中的任何内容。

至于appender与logstash的替代方法,您可能会考虑使用Apache Flume作为传输。 如果你采用appender方法,你可以使用嵌入式水槽代理,并在它上面写一个非常好的appender。 Flume将提供基于磁盘的持久性,像api这样的事务等等。

话虽如此,据我所知,很多人只是采用了logstash方法。

还有一件事,可能是我想到的最后一件事:

  • 你不应该直接写ElasticSearch。 而是使用一些中间服务器(在logstash中它可以是Redis或RabbitMQ)。 在水槽方法中,您可以使用其他水槽工艺(开箱即用的扩展选项支持)。

这将允许您在架构方面抽象ElasticSearch并在日志存储服务器上应用一些额外的处理(它可以从RedM获取数据/从RabbitMQ获取接收消息)。 在水槽中,类似的行为也是可以实现的。

啤酒花有帮助

是否有最佳实践[/]格式[/ protocol]?

我不知道任何已有您想要的字段的日志标准。 所以你需要一种可以存储自定义元数据的格式。 您可以使用RFC5424格式向syslog消息添加元数据。 我还看到各种日志服务通过套接字连接接受JSON格式的消息。

我应该使用elasticsearch appender吗?

我建议直接发送到logstash,而不是直接发送到ElasticSearch。

  1. Logstash旨在以各种格式接收和解析消息,因此以logstash理解的格式比以ElasticSearch理解的格式更容易发送消息。
  2. 随着您的日志记录需求的发展:您将能够在一个地方进行更改 - Logstash - 而不是重新配置您的每个应用程序实例。

    • 这包括操作更改,例如更改ElasticSearch集群的地址。
  3. Logstash可以执行诸如审查日志之类的操作(删除看起来像密码或地址的内容)

  4. Logstash可以将日志发送到各种下游服务。 例如:如果遇到重要错误,它可以触发PagerDuty通知或Slack消息。
  5. Logstash可以使用其他元数据丰富日志消息(例如,从IP地址解密地理坐标)

也可能存在规模问题。 我不足以对这些进行评论,但这是我的直觉:我希望Logstash能够很好地处理大量连接(以及优雅地处理连接失败)。 我不知道这在ElasticSearch集群的设计中是否具有类似的优先级,或者ElasticSearch的搜索性能是否会受到同时连接到它的大量代理的影响。 我更有信心Logstash的设计考虑到了这种用途。

您可能还发现ElasticSearch appender存在局限性。 appender需要对许多事情有很好的支持。 首先想到的是:

  • 协议选择,加密
  • 选择压缩
  • 完全控制日志消息的格式(包括自定义字段)
  • 控制特殊消息(例如异常)被发送

您可以通过坚持一个良好支持的标准(例如syslog appender)来避免技术特定的appender的任何限制。

是否有有效的logback和elasticsearch技术替代方案来满足我的要求?

你的意思是说logstash (即“是否有替代ELK堆栈”?)如果这是你的意图,那么我没有答案。

但就logback的替代方案而言......我使用log4j2。 它提供异步日志记录,以减轻应用程序的性能负担。 也许logback也有这个功能。 在log4j2日志消息中发送自定义字段很难(目前很难支持转义JSON。插件可用,但您的构建需要正确设置才能支持这些)。 对我来说最简单的方法是使用RFC5424 syslog appender。

考虑设计Java应用程序以调用日志记录(即SLF4J),而不是直接调用logback。 这使您可以在将来轻松切换到其他日志记录提供程序。

我和你有同样的问题,并决定避免任何中间日志收集器(如Logstash / Flume)。

https://github.com/internetitem/logback-elasticsearch-appender目前并不理想但它的配置更具弹性然后https://github.com/logstash/logstash-logback-encoder

例如, logstash-logback-encoder修复了https://logback.qos.ch/apidocs/ch/qos/logback/classic/spi/ILoggingEvent.html标准字段的名称

如果响铃已满并且缺少对可用ES服务器的迭代(目前只能指定一个),则logback-elasticsearch-appender当前缺乏对本地FS存储的持久性。

请注意,默认情况下,Logstash不是故障安全的,来自https://www.elastic.co/guide/en/logstash/current/persistent-queues.html

默认情况下,Logstash在管道阶段(输入→管道工作者)之间使用内存中有界队列来缓冲事件。 这些内存中队列的大小是固定的,不可配置

因此,您需要使用Redis,RabbitMQ或Kafka创建一些模式。 在我看来,ES集群比Logstash(ES安全在Elasic.io广告中)更安全。

另请注意Logstash在Ruby中实现,因此单线程应用程序 我们不能在这里谈论可扩展性。 期望高达10000 req / s(这是我在Internet上找到的性能报告中的典型数字)。

水槽有更好的性能。 我看到它缺乏文档。 准备好在邮件列表上提问))

有很多商业优惠:

  • Splunk <http://www.splunk.com/en_us/products/splunk-light.html>
  • Scalyr <https://www.scalyr.com/pricing>
  • Graylog <https://www.graylog.org/support-packages/>
  • Loggly <https://www.loggly.com/product/>
  • Motadata <https://www.motadata.com/elk-stack-alternative/>

由于明智的原因,它们每年花费数千美元。

您可以检查一个日志收集供应商如何设计好的appender: https//logz.io/blog/lessons-learned-writing-new-logback-appender/

使用集中式日志记录解决方案,您应该更改记录方式:

  • 将上下文添加到https://www.slf4j.org/api/org/slf4j/MDC.html这可以是客户电话号码,IP地址,票号或其他任何内容。 您需要一种快速过滤重要数据的方法

  • 开始使用https://www.slf4j.org/api/org/slf4j/Marker.html进行需要立即反应的意外事件。 不要隐瞒或忽视问题

  • 计划如何命名MDC参数和标记并记录它们,以便操作团队知道发生了什么,而不是在午夜打电话给你。

  • 在ES群集中​​设置复制。 这允许您关闭部分ES节点以进行维护。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM