19

我正在考虑将 StatsD 数据收集添加到我的 grails 应用程序中,并查看现有的库和代码让我对什么是好的可扩展解决方案感到有些困惑。为了把这个问题放到上下文中,我正在做一个在线游戏类型的项目,我自然会监控用户与游戏引擎的交互,这些自然会聚集在 X 用户将在窗口内执行交互的特定时刻一两秒,然后在暂停 10-20 秒后重复。

这是我对今天可用选项的分析。

Etsy StatsD 客户端示例

https://github.com/etsy/statsd/blob/master/examples/StatsdClient.java

“可能工作的最简单的事情”解决方案,我可以将此类拉入我的项目并将单例实例实例化为弹簧 bean 并直接使用它。然而,在注意到 grails-statsd 插件创建了一个客户端实例池之后,我开始怀疑这种方法的可扩展性。

如果许多线程试图同时发送事件,该doSend方法似乎成为瓶颈,但是据我了解,由于发送 UDP 数据包的火和忘记性质,这应该很快发生,避免了巨大的开销我们通常与网络连接相关联。

grails-statsd 插件

https://github.com/charliek/grails-statsd/

有人已经为 grails 创建了一个 StatsD 插件,其中包括一些不错的功能,例如注释和withTimer方法。但是我看到那里的实现缺少示例实现中的一些错误修复,例如在调用String.format. 我也不是为此而引入 apache commons-pool 的忠实粉丝,因为标准 Executor 可以达到类似的效果。

java-statsd-客户端

https://github.com/tim-group/java-statsd-client/

这是一个替代的纯 java 库,它通过维护自己的 ExecutorService 来异步操作。它支持整个 StatsD API,包括集合和采样,但不提供任何用于配置线程池和队列大小的挂钩。在出现问题的情况下,对于诸如监控之类的非关键事物,我认为我更喜欢有限队列和丢失事件,而不是无限队列填满我的堆。

播放 statsd 插件

https://github.com/vznet/play-statsd/

现在我不能直接在我的 grails 项目中使用此代码,但我认为值得一看,看看事情是如何实现的。一般来说,我喜欢代码的StatsdClient.scala构建方式,非常干净易读。似乎也有语言环境错误,但其他功能与 etsy 示例一起完成。有趣的是,除非有一些我不理解的 scala 魔法,否则这似乎会为发送到 StatsD 的每个数据点创建一个新套接字。虽然这种方法很好地避免了对象池或执行线程的必要性,但我无法想象它非常高效,可能会在应该尽快返回给用户的请求线程中执行 DNS 查找。

问题

  1. 从所有其他实现似乎都实现了另一种处理并发的策略这一事实来看,我可以假设 Etsy 示例对于生产使用来说有点太天真了吗?
  2. 我在这里的分析似乎是正确的吗?
  3. 其他人在 java/groovy 中使用 statsd 是什么?

到目前为止,看起来最好的现有解决方案是 grails 插件,只要我可以接受 commons-pool 依赖项,但现在我正在认真考虑在周日编写我自己的版本,该版本结合了每个实现的最佳部分。

4

3 回答 3

9

作为java-statsd-client的主要提交者,以及在生产中使用该库的人,我想尝试减轻您对“有一个无限队列填满我的堆”的担忧。

我认为您对 Etsy StatsD 客户端示例的分析非常准确,当您说“由于发送 UDP 数据包的火灾和遗忘性质,这应该很快发生,避免我们通常与网络连接相关的巨大开销。”

据我了解,java-statsd-client目前的实现方式,对大量出站消息的建立的约束是发送即发即弃的UDP数据包的速度。我不是这方面的专家,但我不知道这可能会阻塞,从而可能会建立无限队列。

当您最初进行评估时,java-statsd-client 存在许多突出问题(例如,区域设置/字符编码不明确,以及缺乏采样支持),但这些问题最近已得到解决。剩下的问题是是否存在填满堆的真正风险。我很想听听社区对这个问题的想法,如果大家一致认为存在问题,我很乐意探索在库中引入限制队列。

于 2014-07-28T15:39:14.463 回答
1

在这个问题上睡了一个星期后,我想我会继续使用现有的 grails StatsD 插件。这样做的基本原理是,虽然我可以使用 Executor 来处理并发性,但如果不使用对象池,它仍然会绑定到单个客户端/套接字实例,这在理论上是应用程序中相当明显的瓶颈。因此,如果我无论如何都需要一个游泳池,我不妨使用其他人已经完成了所有艰苦工作的游泳池:)

于 2013-06-27T06:56:03.317 回答
0

在类似的搜索纯 Java StatsD 客户端的过程中,我在 SLF4J上遇到了 StatsD,并将其与Java StatsD Client进行了比较,您提到它有几个问题。仅仅基于阅读来源,我想出了与这些问题有关的细分。

编辑:下表已针对 java-statsd-client 的 3.0.1 版本进行了更新,其中许多原始问题已得到解决。

                          | java-statsd 客户端 | statsd-over-slf4j
——————————————————————————+——————————————————————— ————————————————————————
消息支持采样| 是的 | 是的
——————————————————————————+——————————————————————— ————————————————————————
实际采样 | 不,留给来电者| 是的,使用 java.util.Random
——————————————————————————+——————————————————————— ————————————————————————
非阻塞 impl worker | 单个守护线程 | 单个守护线程
——————————————————————————+——————————————————————— ————————————————————————
非阻塞 impl 队列 | 无界 | 调用者指定的界限
——————————————————————————+——————————————————————— ————————————————————————
String.format 语言环境 | 无* | 语言环境.US
——————————————————————————+——————————————————————— ————————————————————————
消息字节的字符集 | UTF-8** | 默认,可以覆盖

* 不应用本地化
** 这是 StatsD 读取的字符集
于 2014-05-07T22:22:29.443 回答