Comments 36
Vert.x сейчас находится в зачаточном состоянии и позиционируется как фреймворк для построения реактивных приложений и микросервисов. Естественно он чуть более чем полностью обёртка поверх Netty, а HA класстерные решения строятся поверх Hazelcast'a. Нужно обратить внимание на наличие автоматической кодогенерации, которая генерит Ruby / Groovy / JS API на основе существующих аннотаций Java API, т.е. в первую очередь это мультиязычное решение.
По поводу «Direct-буферов» — Netty имеет свой Arena-аллокатор на подобие того что используется в jemalloc, и самостоятельно производит менеджмент offheap'a.
А я сижу, пишу асинхронный PostgreSQL коннектор на vert.x'e :3 который можно было бы использовать в более-менее продакшенах.
По поводу «Direct-буферов» — Netty имеет свой Arena-аллокатор на подобие того что используется в jemalloc, и самостоятельно производит менеджмент offheap'a.
А я сижу, пишу асинхронный PostgreSQL коннектор на vert.x'e :3 который можно было бы использовать в более-менее продакшенах.
Netty смотрится хорошо на тестах. Мне не приходилось с ней работать но как я понел вам было не совсем просто написать на этом проложения которое берет сообщения с одного сокета и ложет в другой. Есть другие асинхроные более простые решения. Это и Node.js не очень быстрый но дешевый в плане разработки. Есть GO у которого все IO асинхроные и код простой синхронный. Язык быстрый и нет всяких заморочек. Я сам переписывал решение одно с Node.js на GO. Там логики по больше и редис и монго но сейчас это обрабытывает 1350 HTTP в секунду 3 сервера(меньше двух не ставим и так) по 4 ядра. Думаю с TCP это бы работало не хужею чем Netty. Вопрос стоило ли заморачиватся с Netty?
Думаю с TCP это бы работало не хужею чем Netty.
Вопрос стоило ли заморачиватся с Netty?Стоит, в первую очередь из-за производительности. Если вы не строите приложений критических к скорости обработки запросов, и вам 5ms погоды не сделают — понятное дело можно использовать что-то проще. C Netty, при правильной допилке, можно выжать под 150-200K запросов на ядро с задержками в 2-3ms. Естественно для большей части простых обывателей подобные вещи бесполезны.
А вообще, сетевых библиотек с нормальным offheap'ом в природе больше замечено не было.
C Netty, при правильной допилке, можно выжать под 150-200K запросов на ядро
Может поделитесь опытом, о какой допилке речь? У меня больше 20к рек-сек на ядро никак не полуачалось и это было без SSL.
мне тоже интересно как получить 200K на ядро с 2-3ms. Как машина справляется с таким количеством сокетов?
Цифры с в студию тесты и так далее а то я тоже могу писать 200K
Цифры с в студию тесты и так далее а то я тоже могу писать 200K
Перво-наперво нужно подтюнинговать JVM.
По хорошему — желательно вообще вырубить GC и использовать Disruptor, но я до такого сам не доходил, хотя были примеры из жизни и довольно позитивные отзывы. Я обычно выставляю выставляю низкий размер новых генераций для GC и максимальное переиспользование существующих. Как минимум, нужно поменять дефолтную реализацию hashcode что бы не было зависимости от размера пула энтропии — это уже даст довольно большой прирост производительности. Всё остальное — тюнинг ядрышка, нужно тюнинговать виртуальную память, что бы можно было запить больше файловых дескрипторов, ну там увеличить размер mmap/munmap'a посредством увеличения vm.max_map_count, после чего уже можно увеличивать всё остальное. Ещё можно увеличить количество ipv4 сокетов net.ipv4.ip_local_port_range, что иногда может приводить к довольно странным последствиям, и fs.epoll.max_user_watches для увеличения количества событий в epoll'e. Для обхода ограничения по количеству сокетов можно ещё маркировать пакеты, только «руками» без netfilter'a, и рассылать их по нескольким процессам — это позволит дублировать дескрипторы. Может чего и забыл, но я сейчас не особо то и слежу за текущим состоянием VM'a и сетевых плюшек в линуксе — переехал на более приземлённые задачи.
Очень желательно использовать netmap или dpdk для мапинга памяти.
Я писал как-то dpdk маппер для одного проекта, но заопенсорсить я его не могу по понятным причинам.
p.s. 200K на ядро это я ещё помелочился :3 — можно гораздо больше.
По хорошему — желательно вообще вырубить GC и использовать Disruptor, но я до такого сам не доходил, хотя были примеры из жизни и довольно позитивные отзывы. Я обычно выставляю выставляю низкий размер новых генераций для GC и максимальное переиспользование существующих. Как минимум, нужно поменять дефолтную реализацию hashcode что бы не было зависимости от размера пула энтропии — это уже даст довольно большой прирост производительности. Всё остальное — тюнинг ядрышка, нужно тюнинговать виртуальную память, что бы можно было запить больше файловых дескрипторов, ну там увеличить размер mmap/munmap'a посредством увеличения vm.max_map_count, после чего уже можно увеличивать всё остальное. Ещё можно увеличить количество ipv4 сокетов net.ipv4.ip_local_port_range, что иногда может приводить к довольно странным последствиям, и fs.epoll.max_user_watches для увеличения количества событий в epoll'e. Для обхода ограничения по количеству сокетов можно ещё маркировать пакеты, только «руками» без netfilter'a, и рассылать их по нескольким процессам — это позволит дублировать дескрипторы. Может чего и забыл, но я сейчас не особо то и слежу за текущим состоянием VM'a и сетевых плюшек в линуксе — переехал на более приземлённые задачи.
Очень желательно использовать netmap или dpdk для мапинга памяти.
Я писал как-то dpdk маппер для одного проекта, но заопенсорсить я его не могу по понятным причинам.
p.s. 200K на ядро это я ещё помелочился :3 — можно гораздо больше.
1. Есть много примеров контор которые действительно гоняли OpenJDK без сборки мусора — патчили System.gc(), хотя я не приветствую такой способ и считаю его большим костылём с ещё большими рисками. Как и почему нужно тюнинговать GC можно глянуть в презентации Рогозина, так же у него был хороший CheatSheet.
2. Disruptor помогает в реализации стратегии «Share Memory By Communicating» — не нужно заморачиваться с пулами объектов и multiton'ами, размерами очередей сообщений в разнообразных вариациях модели актёров.
3. Hashcode по умолчанию использует псевдослучайную генерацию хешей, которая быстро истощает пул энтропии в системе. По этому такие вещи как Haveged могут увеличить производительность виртуальной машины, но делают её random предсказуемым. Даже банальное Android приложение в 4.4 при замене дефолтного hashcode работает в 1.5-2 раза шустрее, по моим личным наблюдениям.
Тюнинг ядра сводится к увеличению размера mmap'a что влияет на максимальное количество дескрипторов (сокетов) в системе в целом, всё остальное — это увеличение epoll пула и обоюдный тюнинг TCP стэка, влияние на производительность которого не сравнимо ни в каких рамках с overhead'ом виртуальной машины.
dpdk / netmap нужны для того чтобы обойти netfilter и лишние memcpy для сетевых буферов.
Понятное дело что тут есть много «но», и большую часть «кусков» приложения нужно правильно профилировать под нагрузкой — подобные рассуждения и скептицизм не очень то и конструктивны.
2. Disruptor помогает в реализации стратегии «Share Memory By Communicating» — не нужно заморачиваться с пулами объектов и multiton'ами, размерами очередей сообщений в разнообразных вариациях модели актёров.
3. Hashcode по умолчанию использует псевдослучайную генерацию хешей, которая быстро истощает пул энтропии в системе. По этому такие вещи как Haveged могут увеличить производительность виртуальной машины, но делают её random предсказуемым. Даже банальное Android приложение в 4.4 при замене дефолтного hashcode работает в 1.5-2 раза шустрее, по моим личным наблюдениям.
Тюнинг ядра сводится к увеличению размера mmap'a что влияет на максимальное количество дескрипторов (сокетов) в системе в целом, всё остальное — это увеличение epoll пула и обоюдный тюнинг TCP стэка, влияние на производительность которого не сравнимо ни в каких рамках с overhead'ом виртуальной машины.
dpdk / netmap нужны для того чтобы обойти netfilter и лишние memcpy для сетевых буферов.
Понятное дело что тут есть много «но», и большую часть «кусков» приложения нужно правильно профилировать под нагрузкой — подобные рассуждения и скептицизм не очень то и конструктивны.
1. Приложение обновить/перезапустить можно только в горячую, и то не всегда. Задержка на перезапуск обычно не может быть больше 7-10ms. Обычно использую 1G. Для выпиливания GC нужен патч в 300 строчек С++.
2. Если в этом самом кольцевом буфере выделять статические объекты для работы с различными сущностями — отпадает потребность в реализации пулов и мультитонов, но это требует специфического подхода в разработке, и позволяет один раз выделить память «под всё» и полностью остановить сборку мусора.
3. На самом деле время вычисления hashcode может быть в 2-3 раза более ресурсоёмко нежели создание самого объекта и выполнения нужного кода, и для абстрактных Netty в вакууме его реализация без псевдо-случайностей часто бывает на много шустрее.
4 канала по 40ГБит на 4ёх Virtex7 картах :|
2. Если в этом самом кольцевом буфере выделять статические объекты для работы с различными сущностями — отпадает потребность в реализации пулов и мультитонов, но это требует специфического подхода в разработке, и позволяет один раз выделить память «под всё» и полностью остановить сборку мусора.
3. На самом деле время вычисления hashcode может быть в 2-3 раза более ресурсоёмко нежели создание самого объекта и выполнения нужного кода, и для абстрактных Netty в вакууме его реализация без псевдо-случайностей часто бывает на много шустрее.
4 канала по 40ГБит на 4ёх Virtex7 картах :|
Половина оптимизаций не имеет отношение к Netty. Все оптимизация ядра помогут любой платформы. Работать без GC продакшине не hello world как то не очень.
вот тесты с оптимизацией машины с GC и без всяких извращений
gist.github.com/hgfischer/7965620#go-standalone-1
gist.github.com/hgfischer/7965620#go-standalone-1
Эм, ну бэнчмарк малость неактуален и «туговат».
Нету ничего странного что при upstream'e на TCP'шном сокете производительно в 1.5-2 раза падает, но подобные бэнчмарки непосредственно к производительности самого golang'a отношения не имеют, хотя бы из-за «100 потоков по 500 соединений» и радости от 17-120ms задержек на древнем 1.2 runtime. А сабж вообще о нецелесообразности использования nginx балансера поврех golang'a, что вообщем-то должно быть совсем«как бы кэп» очевидно.
В общем я и не думаю что мне стоит здесь так распинаться по поводу производительности, которая в 99% случаев никому не нужна.
Буду в очередной раз оскорблять чувства «верующих» и читать разнообразные бесполезности.
Попробуйте аргументировать свой скептицизм и разобраться в личных целях подобных комментариев.
Фраза по поводу «серебряной пули» мной расценена как психологическая проекция.
Нету ничего странного что при upstream'e на TCP'шном сокете производительно в 1.5-2 раза падает, но подобные бэнчмарки непосредственно к производительности самого golang'a отношения не имеют, хотя бы из-за «100 потоков по 500 соединений» и радости от 17-120ms задержек на древнем 1.2 runtime. А сабж вообще о нецелесообразности использования nginx балансера поврех golang'a, что вообщем-то должно быть совсем
В общем я и не думаю что мне стоит здесь так распинаться по поводу производительности, которая в 99% случаев никому не нужна.
Буду в очередной раз оскорблять чувства «верующих» и читать разнообразные бесполезности.
Попробуйте аргументировать свой скептицизм и разобраться в личных целях подобных комментариев.
Фраза по поводу «серебряной пули» мной расценена как психологическая проекция.
Ну если уж выбирать решение вне ява мира, то для этой задачи идеально подойдет Erlang =). Но так как весь мой опыт — это java, я не рискнул идти другими путями. Да и на том этапе важно было сделать хоть какое-то решение и как можно быстрее.
Если сравнивать высокую доступность — тут у Erlang'a есть преимущество, так как в нём почти всё в Beam машине написано с использованием wait-free (но не lock-free) алгоритмов. Если сравнивать по производительности — она ниже плинтуса, так что для задач посложнее memcpy он не очень то и подходит. А в «дикой природе» получается так что гораздо проще прикрутить ту же Akka и, при правильной допилке, получить ту же производительность — это касается любых проектов которые отправляют что-то сложнее HelloWorld по Http.
Жду когда допилят порт erlang'a под llvm.
Жду когда допилят порт erlang'a под llvm.
но ниже я расскажу, как этого максимально избежать.
Так все-таки расскажете? :)
А что за проект?
www.blynk.cc сервер кстати, опенсорсный github.com/blynkkk/blynk-server
Ого!
Этот проект явно тянет на отдельную статью, а то и не одну.
Этот проект явно тянет на отдельную статью, а то и не одну.
На самом деле я уже их написал =). Правда на другом ресурсе — dou.ua/lenta/columns/blynk-30-days-after
Хмм…
Хотелось-бы почитать статью, однако РКН блочит этот домен.
Есть-ли у вас статья на альтернативном ресурсе?
P.S. Про VPN знаю, умею, но сейчас в командировке с чужим планшетом.
Хотелось-бы почитать статью, однако РКН блочит этот домен.
Есть-ли у вас статья на альтернативном ресурсе?
P.S. Про VPN знаю, умею, но сейчас в командировке с чужим планшетом.
Есть в гугл доке, где она готовилась docs.google.com/document/d/18vw4dZY53GF1XLYWULFRaH5sSYIlko-biyIo_JlsKzs/edit?usp=sharing
Cначало я написал сюда. Но тут меня забанили =). Так что я теперь не рискую публиковать информацию о проекте.
А CoAP рассматривали? coap.technology
Смотрел. Я прогуглил все популярные решения на тот момент. Но если MQTT используется очень часто, то CoAP я вообще не встречал. Даже теперь. Спустя 6 мес. после запуска. Вообще как показала наша практика — людям всеравно, что вы реализуете на низком уровне и какие протоколы используете, если работает хорошо и проект решает реальную проблему. Даже не смотря на тот факт, что наш продукт исключительно для железячников.
Спасибо, меня интересовала как раз критика и основную причину я уловил. Но может еще что-то? Интерес не праздный, я пишу систему, использующую CoAP для зарубежного клиента (телеметрия/управление). Мне довольно таки понравился сам протокол и его реализация — Californium (не идеал, но вполне годно). Правда, до внедрения еще не дошли, так что основные грабли наверняка еще впереди)
Тут не подскажу. Я лишь поверхностно ознакомился с ним. Могу по MQTT только рассказать. Несмотря на то, что это довольно популярный протокол, многие железячники его недолюбливают (по крайней мере сложилось такое впечетление при общении с американцами, когда мы презентовали Блинк). Основная причина — туда заложили всего и вся на все случаи жизни, хотя в реалных кейсах надо лишь 20%.
Похвально, в нужном направлении работаете! Раз уж тема java, поделюсь ссылкой на kura и iot.eclipse.org, может кому окажется полезно
В своё время тестировал Grizzly. Очень понравилась штука. Используется насколько я понимаю в GlassFish. По сравнению с нетти более понятный API.
Sign up to leave a comment.
IoT cloud на Netty или 10к рек-сек на ядро