我正在考虑将 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 查找。
问题
- 从所有其他实现似乎都实现了另一种处理并发的策略这一事实来看,我可以假设 Etsy 示例对于生产使用来说有点太天真了吗?
- 我在这里的分析似乎是正确的吗?
- 其他人在 java/groovy 中使用 statsd 是什么?
到目前为止,看起来最好的现有解决方案是 grails 插件,只要我可以接受 commons-pool 依赖项,但现在我正在认真考虑在周日编写我自己的版本,该版本结合了每个实现的最佳部分。