Какой клиент StatD следует использовать для проекта java/grails?
Я смотрю на добавление коллекции данных StatD в мое приложение grails и оглядываясь на существующие библиотеки и код, оставив меня немного запутанным относительно того, что будет хорошим масштабируемым решением. Чтобы немного поставить вопрос в контекст, я работаю над проектом типа онлайн-игр, где я, естественно, буду следить за взаимодействием пользователей с движком игры, они, естественно, будут группироваться вокруг определенных моментов времени, когда пользователи X будут выполнять взаимодействия внутри окна секунды или два, затем повторяется после паузы в 10-20 секунд.
Вот мой анализ опций, доступных сегодня.
Пример клиента Etsy StatsD
https://github.com/etsy/statsd/blob/master/examples/StatsdClient.java
"Самое простое, что могло бы работать", я мог бы поместить этот класс в свой проект и запустить экземпляр singleton как spring bean и использовать его напрямую. Однако, заметив, что плагин grails-statsd создает пул клиентских экземпляров, я начал задаваться вопросом о масштабируемости этого подхода.
Похоже, что метод doSend
может стать узким местом, если многие потоки пытаются отправлять события в одно и то же время, однако, насколько я понимаю, из-за пожара и забывания о природе отправки пакетов UDP это должно произойти быстро, избегая огромных накладных расходов, которые мы обычно связываем с сетевыми подключениями.
плагин grails-statsd
https://github.com/charliek/grails-statsd/
Кто-то уже создал плагин StatD для grails, который включает в себя некоторые интересные функции, такие как аннотации и withTimer
. Однако я вижу, что в реализации отсутствует некоторые исправления ошибок из примера реализации, такие как указание локали при вызовах String.format
. Я также не являюсь огромным фанатом в том, чтобы потянуть в пул Apache только для этого, когда стандартный Executor смог добиться аналогичного эффекта.
Java-statsd-клиент
https://github.com/tim-group/java-statsd-client/
Это альтернативная чистая Java-библиотека, которая работает асинхронно, поддерживая собственный ExecutorService. Он поддерживает весь API статистики, включая наборы и выборку, но не предоставляет никаких привязок для настройки пула потоков и размера очереди. В случае проблем для некритических вещей, таких как мониторинг, я думаю, что предпочел бы конечную очередь и проиграл бы события, чем иметь бесконечную очередь, которая заполняет мою кучу.
Воспроизвести плагин statsd
https://github.com/vznet/play-statsd/
Теперь я не могу использовать этот код непосредственно в моем проекте grails, но я подумал, что стоит посмотреть, как все было реализовано. В общем, мне нравится способ создания кода в StatsdClient.scala
, очень чистый и читаемый. Также появляется ошибка локали, но в остальном функция в комплекте с образцом etsy. Интересно, что, если не существует магии scala, которую я не понял, создается впечатление, что создается новый сокет для каждой точки данных, которая отправляется в StatD. Хотя этот подход хорошо избегает необходимости в пуле объектов или потоке исполнителей, я не могу представить, что это ужасно эффективно, потенциально выполняя поиск DNS в потоке запроса, который должен как можно скорее вернуться к пользователю.
Вопросы
- Судя по тому, что во всех других реализациях реализована еще одна стратегия обработки concurrency, могу ли я предположить, что пример Etsy слишком наивен для использования в производстве?
- Является ли мой анализ здесь правильным?
- Что другие люди используют для statsd в java/ groovy?
До сих пор похоже на лучшее существующее решение - плагин grails, пока я могу принять зависимость от сообщества, но сейчас я серьезно рассматриваю возможность потратить воскресенье на мою собственную версию, которая объединяет лучшие части каждой реализации.
Ответы
Ответ 1
После сна в течение недели я думаю, что я собираюсь пойти и использовать существующий плагин Grails StatD. Обоснованием для этого является то, что, хотя я мог бы добиться аналогичного эффекта с помощью Executor для обработки concurrency, не используя пул объектов, это все равно будет привязано к одному экземпляру клиента/сокета, теоретически довольно очевидное узкое место в приложении. Поэтому, если мне все равно нужен пул, я также могу использовать тот, где кто-то еще проделал всю тяжелую работу:)
Ответ 2
Говоря как первичный коммиттер java-statsd-client, а также тот, кто использует эту библиотеку в производстве, я хотел бы попытаться смягчить ваши опасения относительно "имея бесконечную очередь, которая заполняет мою кучу".
Я думаю, что вы в значительной степени прибивали его при анализе примера клиента Etsy StatsD, когда вы сказали "из-за пожара и забыть природу отправки пакетов UDP, это должно произойти быстро, избегая огромных накладных расходов, которые мы обычно связываем с сетью соединения".
Насколько я понимаю, способ, которым в настоящее время реализуется java-statsd-клиент, является ограничением для наращивания большой очереди исходящих сообщений, это скорость отправки и отправки пакетов UDP. Я не эксперт в этой области, но я не знаю, каким образом это может блокировать, чтобы создать бесконечную очередь.
Когда вы изначально сделали свою оценку, было много нерешенных проблем с java-statsd-клиентом (например, неоднозначность языка/символа кодировки и отсутствие поддержки выборки), но в последнее время они были устранены. Остается вопрос о том, существует ли реальный риск заполнения кучи. Я бы хотел услышать мысли сообщества по этому вопросу, и, если консенсус в том, что есть проблема, я был бы рад изучить введение ограничительной очереди в библиотеку.
Ответ 3
Я столкнулся с StatsD над SLF4J во время аналогичного поиска чистого клиента Java StatsD и сравнил его с Java StatsD Client, о котором вы говорили, имело несколько проблем. Просто основанный на чтении источника, я придумал эту разбивку, связанную с проблемами.
EDIT: приведенная ниже таблица обновлена для версии 3.0.1 java-statsd-client, в которой исправлены многие исходные проблемы.
| java-statsd-client | statsd-over-slf4j
——————————————————————————+————————————————————————+————————————————————
messages support sampling | yes | yes
——————————————————————————+————————————————————————+————————————————————
actual sampling performed | no, left to caller | yes, using java.util.Random
——————————————————————————+————————————————————————+————————————————————
nonblocking impl worker | single daemon thread | single daemon thread
——————————————————————————+————————————————————————+————————————————————
nonblocking impl queue | unbounded | caller-specified bound
——————————————————————————+————————————————————————+————————————————————
String.format locale | none* | Locale.US
——————————————————————————+————————————————————————+————————————————————
charset for message bytes | UTF-8** | default, can be overridden
* no localisation is applied
** this is the charset that StatsD reads with