Как стать автором
Обновить

Комментарии 58

спасибо за статью, всегда интересно читать про использование вебсокетов =) я тоже как-то давно развлекался поднятием 1кк коннектов на домашнем компе, выдерживало 800к, сообщения ходили, все было ок, старенький amd на 4 ядра и 16гб оперативы, java. Тестировать это было интересно, пришлось поднять 20 виртуалок по 40к коннектов
как получил 40к коннектов? почему именно 40к? что за сервер?
если на одном сервере сделать 20 http портов слушающих ws и на каждом по 40к коннектов?
это вместо 20 виртуалок.

Ну всего лимит 65к коннектов с одного клиента в один порт, минус занятые файловые дескрипторы, можно и с одного клиента 1кк коннектов открыть, если в разные порты и лимиты настроить, но про разные порты я не подумал, а с лимитами в lxc было что-то мутно. Кстати как балансировать 20 разных портов?

про разные порты — мысль пришла из твоего опыта. вот тут tootallnate.github.io/Java-WebSocket это вполне можно реализовать, там просто «слушатель» порта. он отдельно. а вот если использовать либу из tomcat — там так просто порты не добавить…
как балансировать по портам — чисто теоретически — массив — свободных, при подключении/открытии страницы брать из него свободный и подставлять… и убирать из массива…
для начала как бы проверить вообще такую возможность — несколько http портов вместо машин.
и вроде для ws подключений нет ограничений для количества портов. они вроде как отдельно от портов http? ( имеется в виду все 65к)
ws идет поверх http, для балансировки нужно будет как-то сообщать клиенту в какой порт стучаться, но да, всё реализуемо
если клиент браузер — то всё просто, а если приложение — то несколько усложняется.
Спасибо и за пример и за реальную статистику. Чисто теоретически я вобщем-то был уверен в том что решения на основе Erlang это наиболее удачное решение для веб-сокетов. То что Go показал сравнимую производительность в тестах это еще не гарантирует сравнимую производительность на проде (и не исключает ее). Хотелось бы посмотреть на реальную статистику реальных приложений на Go, если она у кого-нибудь имеется.
habrahabr.ru/company/mailru/blog/331784 к примеру.

Да и как раз на проде сложно представить реальную задачу, где Erlang составил бы сильную конкуренцию Go. Разве что какие очень развесистые деревья или подобные структуры.
Спасибо интересная статья. Правда как я понял из контекста это все же не работет на продакшине, а то что работает (как я понял тоже Go только без оптимизации) нет конкретной статистики. Про erlang конкретно я имел в виду исключительно решение с большим количеством сокетов. (см. phoenixframework.org/blog/the-road-to-2-million-websocket-connections ).
Как раз таки работает.
Но в любом случае такие технические статьи на любом ЯП интересно почитать.
А какая версия Go была и что было в GOMAXPROCS?
Ни ссылок на golang в конце, ни тестируемого кода, ни даже в тегах не упомянут) Похоже, что Go, в контексте статьи, это просто как в рекламе:

Была ли проверка с mnesia in memory в качестве базы данных на отдельной ноде? Теоретически это позволило бы мониторить упавшую ноду и обновлять цифры.

много обовсем,

Тесты проводились на примере простейших чатов на Go и Phoenix


мне, например, непонятно что за такие простейшие чаты и откуда,

хороший тон: публиковать тестируемый код, иначе остается словам верить.
Чаты — те что идут в официальных примерах фреймворков
Для Gorilla — github.com/gorilla/websocket/tree/master/examples/chat
Для Phoenix — github.com/chrismccord/phoenix_chat_example
В тот момент не планировали что-либо публиковать, и многое из тестируемого кода просто не сохранилось
Для 3х сценариев ( 1)-минимум подключенных клиентов (например два), (2)-среднее кол-во (например 150К и (3) тестируемый макс — например 800к) сл. вопросы:

— Скольку удавалось получить new-connections-per-second (создание нового соединения — процесс очень дорогой)
— Какая messages-per-second
— Какое latency при передаче сообщения клиент-клиент
— Какое время регистрации нового клиента

Отвечу вам цифрами с нашего последнего нагрузочного тестирования на уже готово продукте.

Порядка 220 новых соединений в секунду, 200к ботов.
Время регистрации нового клиента не превышает 50ms.
В пике около 6000 сообщений в секунду летает между сервером и клиентами.
У нас бизнес логика не предполагает общения клиент-клиент, NDA не позволит дать конкретики, абстрактно схема следующая:
1. Событие на сервере -> Уникальные сообщения для большой группы пользователей
2. Реакция пользователя -> Сообщение серверу о том что пользователь подтвердил получение сообщения 1
Ого, вот это у вас темп работы — разработка за месяц сервиса для 150 тыс. людей онлайн — круто!

Вот интересно, вы, как Тимлид проекта, когда выбирали Элексир vs Go — рассматривали ли вопрос кадров? Кажестся, что у нас куда проще найти Go-разработчика, чем Erlang/Elixir.
Код nodejs сервера, который у вас не выдержал 5000 соединений в студию на гитхаб!
Ну уж раз так то список сайтов на node.js где это работет на 150 тыс. соединенй (хотя бы ) тута же.
Я не утверждаю, что 150 000 соединений невозможны или возможны. Автор статьи же наоборот утверждает, что 5000 невозможно.
Кстати, случайно не подскажете где ссылка на сайт автора в продакшене?
Далее я рассмотрел Node.JS WS. Этот фреймворк показал неплохие результаты – около 5 тысяч коннектов на тестовом стенде без дополнительных настроек

Возможно 5000. Ссылки на сайт автора у меня нет.

По поводу использования конерктно nodе.js и конерктно для веб-сокетов очень большие вопросы есть. Если бы был реальный пример то можно было бы пробовать реализовать в нагруженном (хотя бы) проекте.
Вот тут автор уверяет, что еще в 2015 поднял на node.js на амазоновском EC2 600-620к вебсокет соединений. Пусть и с небольшими подпорками, но, видимо, реально.

Сам я в ноде практически 0, так что хз.
Вобщем-то автор не скрывает что это были лишь тесты со «своим клиентом». Цель была присоединиться и держать соединение на что не использщуется основной процесс в коором віполняется JavaScript а только средства NIO. Что будет когда все эти коннеты «заговорят» и потребуют свою долю от движка JavaScript. Большой плюс автора обсуждаемй статьи на Хабре это то что он сделал реальное приложение и показал нам графики реальной загрузки реальной конфигураци сервера.

wouter
April 13, 2015 at 20:37 /

What did you use to generate 620k connections?
And did you send a message over every connection every x seconds or was is just a silent connection?

Daniel Kleveros
April 14, 2015 at 08:11 /

I created my own client with the same websocket lib websockets/ws which I then deployed on a cluster of M1.Large instances.

It was silent connections but to keep the connections alive, if you are behind a elastic load balancer, you need to check the idletimeout setting on the loadbalancer and send a ping before that time expires. If not the load balancer will start to drop your connections.
Около 5000 это может и меньше. Конкретики как всегда около 0. Вот я и задал вопрос. Ответа тоже около 0. NDA видимо)

Все больше склоняюсь к тому, что автор статьи лукавит. Вот почему: конфиг который он скинул – кривой косой, отсутствуют примеры кода, тулза под названием artillery выдает не очень полезную инфу.
Скорее всего человек просто получил задачу написать статью. Кое-как сделал, накидал и вот уже на хабре. Все вопросы можно игнорировать сославшись на NDA. Спрашивается, зачем писать статью если нет возможности рассказать полностью…

Давайте загуглим эту конторку под названием mediasoft.
Вот она http://php73.ru/.
А это favicon этого сайта:
image
Хотел найти список сотрудников там, но не нашел. То ли конфиденциальность такая, то ли лень, то ли текучка кадров лютая… Непонятно. Зато есть список выполненных работ, где числится carprice. Ну вот, хоть заценю этот сайт и гляну как вебсокеты работают там. Честно говоря спустя 5 минут так и не нашел где там вебсокеты. Попытался купить авто, но мне просто открывалась еще одна такая же вкладка браузера. Простой php сайт на битриксе?

Всё это очень мутно выглядит, что даже не хочется дальше разбираться. Ну не смогли на js 100к коннектов сделать да и пофиг.

напоследок фото топикстартера
image

ладно, еще одно фото
image

конфиг
config:
  target: "http://localhost:3000"
  socketio:
      transports: ["websocket"]
  phases:
    - duration: 1
      arrivalRate: 2
scenarios:
  - engine: "socketio"
    flow:
      - think: 1





результат
Started phase 0, duration: 1s @ 22:50:07(+0600) 2018-03-15
Report @ 22:50:10(+0600) 2018-03-15
Scenarios launched: 2
Scenarios completed: 2
Requests completed: 0
RPS sent: NaN
Request latency:
min: NaN
max: NaN
median: NaN
p95: NaN
p99: NaN

All virtual users finished
Summary report @ 22:50:10(+0600) 2018-03-15
Scenarios launched: 2
Scenarios completed: 2
Requests completed: 0
RPS sent: NaN
Request latency:
min: NaN
max: NaN
median: NaN
p95: NaN
p99: NaN
Scenario counts:
0: 2 (100%)



незатейливый backend
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = process.env.PORT || 3000;

io.on('connection', function (socket) {
    console.log("connected");
    socket.on('hello', function (msg) {
        console.log("hello");
        io.emit('hello', msg);
    });
});

http.listen(port, function () {
    console.log('listening on *:' + port);
});

не холивара ради, простое любопытство: почему не СИ?
я набросал работающий фреймворк за день. но у меня уже было понимание, как устроен протокол. разобрался когда пытался, несколько лет назад, делать сервер на CLI PHP.

Потому что нет готовых инструментов, зато есть ограничения по времени и уровню поддержки.
Почему не C — надеюсь автор ответит.
А вот работающие «фреймворки» давно написаны и вряд ли можно написать что-то более производительное, чем связка libwebsocket и libevent.
Были мысли и про СИ, остановило отсутствие готовых инструментов, общая сложность разработки и то что СИ, в целом, не особо ориентирован на WEB.
мне кажется, вы как-то через-чур преувеличиваете сложность СИ, не так страшен чёрт как его малюют. пишете некое CORE (ядро) для общей обработки Websockets, а для разных функций — разные подключаемые DLL модули. и не придётся перекомпилять всё то и дело.
а вообще, я уверен, что-то уже есть. вот люди советуют вам посмотреть libwebsocket и libevent, посмотрите, хотябы и обзорно. хотябы и после того, как «горящий» проект сдадите в прод. я думаю такие вещи имеют высокую повторяемость в потребности, и время на изучение, проработку вопроса не будет потрачено без пользы. оно себя с лихвой окупит в будущем.
Проект уже давно ушёл в прод, и успешно выполняет задачи.
В мир C/C++ обязательно загляну в свободное время. Но «продать» заказчику реализацию на С, по моему мнению, будет ещё сложнее чем на Erlang. Увы, все хотят дешёвых и популярных технологий, таких как PHP, Ruby, Pyton
НЛО прилетело и опубликовало эту надпись здесь
А как же Java + Spring?

Приветствую всех!
Ws действительно интересная тема. Недавно была задача для crm-bpm системы сделать event-сервер. Я остановился на node.js. У меня, служба работающая под pm2, является клиентом ws для asterisk. Ловит и обрабатывает все события АТС и раздает авторизованным пользователям системы, подключенным по wss, уведомления о входящих звонках, проверяя соответствия номера клиента с наличием в базе данных. Также от пользователей приходят комманды на уведомления других пользователей при постановке задачи, состояние он-лайн, офф-лайг, а также работа по API с сайтами при поступлении POST запросов. То есть, одновременно это клиент и сервер.
Пользователей он-лайн около 200, события от АТС идут постоянно (один только звонок порождает около 6000 тыс. строк), их около 400 в день. С сайтов приходят запросы, но немного, один-два в час.
Так к чему я это все рассказывал. Честно говоря не могу понять как протестировать нагрузку, чтобы можно было смело говорить о каких-то конкретных цифрах.
Я конечно понимаю, что видимо знаний мало, но тут и запросы к базе и активность клиентов системы очень варьируется, и данные по API разный объем имеют. Плюс-минус километр если, то на 200 пользователей при 400 звонках в день и 300 задачах в системе + 40 отправленных сообщений по API в сутки, пиковая нагрузка по RAM была 81mb. По процессору не более 10%. Можно смело об этом говорить, что эти показатели не превышались никогда, так как PM2 в этом случае перезапускал бы службу (ну должен это делать во всяком случае) и фиксировал это событие.
Интересно было бы узнать о каких-то системах расчета нагрузки, потому как мои средние наблюдения и "простые чаты" это как-то из разряда средней температуры по больнице…
За статью спасибо! Я, к сожалению до Go не дошел в этом вопросе, а PHP отмел по причине неудобной, ИМХО реализации по работе с сокета и.

Так много вариантов со стороны PHP (не совсем очевидного выбора о котором думают в первую очередь говоря о вебсокетах), а со стороны node.js один только ws. Хотя можно было ещё и socket.io рассмотреть — было бы интересно посмотреть на его результаты.
socket.io — смотрел, пробовал. Это было чуть раньше, когда он был незаменим в связи со слабой поддержкой сокетов браузерами. Сейчас все и так хорошо.
Сам большой поклонник PHP, но сдался в связи в удобством реализации на Node.
Могу сказать только что socket.io многократно больше потребляет траффика… или я «котов не умею готовить» :)
т. Плюс-минус километр если, то на 200 пользователей при 400 звонках в день и 300 задачах в системе + 40 отправленных сообщений по API в сутки, пиковая нагрузка по RAM была 81mb
На ноде такая загрузка была? Конечно одновременных 200 соединений это почти ничего но все равно я предполагал большую цифру.
Давайте в скайп, что тут флеймить: akadex2
:)
хотелось ты посмотреть код на NodeJS, почему был такой маленький лимит у вас в запросах
Поверьте, вот все по мануалу из:
www.npmjs.com/package/ws
Там банальный небольшой скрипт процедурный. Никакого специализированного фреймворка. Все время/трудозатраты в основном на тесты и отладку ушли. Те же event`ы различных диалпланов Астериска парсить. А лимиты такие сугубо из показателей мониторинга. Как только PM2 начнет ребутить, то будет повод посмотреть логи, подумать о том, что надо ресурсы увеличить, или увидеть очередной объект, который надо за`delete`ить.
ws лучше вообще не использовать, где хотя бы более 1000 коннектов предполагается.
Есть другая библиотека — uws (на С++). Производительность и расход ресурсов различается в несколько раз. Особенно момент массового подключения клиентов и если много данных передавать.
Для браузера пока что есть альтернатива веб-сокеты или fallback на еще более реурсоемкие технологии. Если есть другие варианты расскажите о них, пожалуйста. По поводу библиотеки uws (на С++) какую нагрузку в Ваших проектах она выдерживает и какие ресурси при этом требует?
В основном использовалось для рассылки событий клиентам, в разных проектах. На один процесс обычно получалось по 3k коннектов и в среднем 100-150 ГБ трафика за месяц, хотя это и не особо важно. Примерно год назад (когда библиотека была молодая и сыроватая) было сравнение на нодах Digital Ocean (512-1024 МБ). Выйгрыш по памяти выходил до 4-5 раз (кол-во клиентов до OOM killer), а так же сравнимо CPU. Исчезла проблема, когда в момент наплыва клиентов (после рестарта) происходил ступор процесса на несколько минут.
График (производительности) на Github соответствует заявленным цифрам, есть другие обзоры.
Интерфейс библиотеки совместим с пакетом ws, socket.io/engine.io/… поддерживают замену пакета. Единственный минус — необходимо компиляция.

www.npmjs.com/package/uws
github.com/uNetworking/uWebSockets
Спасибо хороший там график производительности и много альтернативных игроков показана производительность. Основной вопрос который все же меня лично волнует — это нужен ли сейчас fallback. При этом с учетом не только возможностей браузера которые конечно сейчас все поддерживают веб-сокеты. А с точки зрения не недоступности сокетов в некоторых странах (якобы они подпадают под действие закона об ограничении), в сетях некторых мобильных операторов.
Если посмотреть на код можно наверное сказать почему был лимит 5000. Но это не ответит на вопрос какой может быть реальный лимит и какие при этом будут затраты (сколько ядер, сколько памяти, сколько нодов. У Вас есть реаьные данные по nodejs как у атора этой статьи есть реальные данные по фениксу? Расскажите, это интересно.
у меня есть проект в проде, и там показатели в разы выше
вот и хотел код глянуть

с фениксом не работал, тут нечего сказать
интерес исключительно по NodeJS

по готовым примерам… вот готовый модуль, лаботающий на сокетах, использующий нативный модуль
www.npmjs.com/package/ipc-socket

максимальный лимит который был достигнут на моей машине, 35к/сек
этот модуль у нас так же используется в проде, по нему гоняем логи с нескольких проектов в единое хранилище
То есть у Вас одновременно около 1 миллиона одновременно подключившихся активных клиентов? Икакие при этом параметры по серверу/серверам (количество серверов/ядер/объем памяти)?
на серверах замеры не производил
замерял только на своей локальной машине
замер производился на конфигурации
i7
16G RAM

у имеющихся двух серверов, только оперативы в 2 раза больше, остальные параметры примерно те же
Ага у Вас свой нативный модуль. А как с fallback если веб-скоеті на поддерживаются и актуальнно ли сейчас делать fallback? Говорят что например в некоторых странах (Китай) и некоторые провайдеры (мобилного интернета) эти веб-сокеты не поддерживают. Также поддержка веб-сокетов из соображений скажем безопасности моет быть отключна администраторами корпоративной сети для доступа к внешним сверерам/сайтам.
этот модуль рассчитан только на работу в серверном коде
а там TCP сокеты никто никогда не отменял
А какой модуль работет с 1 млн. одновременных клиентов-браузеров онлайн? Мы же насколько я понял это сейчас обсуждаем?
изначально, я у автора просто спросил код, и ничего обсуждать не собирался

написание кода под высокие нагрузки, имхо, это вопрос прямизны рук
Также поддержка веб-сокетов из соображений скажем безопасности моет быть отключна администраторами корпоративной сети для доступа к внешним сверерам/сайтам.


не слышал ни одного такого случая
если что-то закрывается с целью безопасности, то уже сразу целым доменом/IP
Я наконец понял в чем Ваш вопрос. Автор не говорит что у него было 5000 запрсов в секунду. И для вебсокетов (не в серверном варианте) высокая нагрузка совсем другое подразумевает. Это когда у Вас 5 или 150 тысяч одновременно пользователей открыли соединения из браузера и все они работают не секунду а час или например цеоый день у них приложение открыто и нужно держать постоянно соединение. Я-то думаю откуда у Вас на ноде такие показатели на слабых девайсах.

Или если перейти на серверы то это у вас со всего мира 150 000 серверов к Вами присоединились и держат коннекты. А если у Вас пусть даже миллион сообщений в секунду но от сотни серверов то это как раз сто содеинений а не сто миллионов соединений.
И это ещё cowboy версии 1. Жду не дождусь, когда cowboy 2 интегрируют в феникс.
Есть сторонний хэндлер для cowboy 2: github.com/voicelayer/phoenix_cowboy2.
Было бы интересно взглянуть на графики из статьи ещё раз, но уже с cowboy 2
Причитал статью и вспомнил высказывание: "- Вы не любите котов!? — Вы просто не умеете их правильно готовить!"

Как чужой опыт, статья конечно имеет право быть, но ИМХО выглядит она как хвалебная песня в честь Linux, Go и Erlang.
Можно было просто сказать, что наша команда знает Linux, Go и Erlang и поэтому в условиях дефицита времени для достижения цели выбрали в качестве инструмента, то что мы лучше всего знаем. (И это единственно правильное решение).

Но недостатки других решений или преимущества (Linux, Go и Erlang) совсем не очевидны.
Чем плох PHP и в частности PHP Workerman не понятно!

«Poll vs. Epoll»… А где kqueue/kevent?
Или kqueue настолько не эфективен что не заслужил упоминания? Да,… не кросплатформенно… да, с этим умеют работать только BSD системы и некоторые комерческие системы используют подобный подход.
Но согласитесь, что это проблема Linux, а не PHP Workerman!
NGINX + PHP-FPM умеют использовать эфективный kqueue и вместе они прекрасно масштабируются «по самое не могу»!

«PHP Workerman — Код находится на уровне PHP 5.3 и не соответствует никаким стандартам.» — простите, а каким конкретно стандартам он должен соответствовать?!
У меня код работал на PHP 7.1, но если автор тестировал на сервере с PHP 5.3, то это даже не проблема настроек PHP… и уж тем более не проблема PHP Workerman. И из этого не следует, что он не позволяет реализовывать высоконагруженные проекты…

Скажем прямо, просто Вы выбрали другой путь… свой путь.
У меня код работал на PHP 7.1

Не сочтите за наезд. Я просто реально хочу получить реальные данные о реальных серверах (как у автора этой статьи). Какая нагрузка была на приложение? Какие были затраты по памяти/процессорам? Как мониторилась доступнасть веркеров? Сколько было запущено веркеров? Каки были организованы сессии в смысле как отслеживалось чтобы лиибо было соединение с одинм и тем же веркером или же данные расшарвались между веркерами? Расскажите. Это интересно.
Можно было просто сказать, что наша команда знает Linux, Go и Erlang

Это было-бы великолепно, но увы это был первый опыт работы с Elixir

А где kqueue/kevent?

Нельзя объять необъятное, BSD системы не рассматривали, хотя возможно стоило

а каким конкретно стандартам он должен соответствовать

Ну для начала PSR
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.