Re[11]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 04:18
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

N>>Баги — исправляются. А вот принципиальная тормознутость рантайма — с ней сильно сложнее.

N>>Или таки скоро завезут сильный JIT (а не убогий HiPE)?

MA> Имхо, нормальный JIT нигде не завезли и никуда не завезут. Все успешные рантаймы идут на дикие компромисы, при чем стратегию "долго запрягаем — быстро едем" — они не только не способны обеспечить, но и часто искусственно отвергают.


Ну всё зависит таки от уровней ожидания. У меня сейчас один тяжело нагруженный компонент на Python (переход на что-то иное... ну планируется, а когда реально делать?) Даже странный зверь PyPy (который, если кто не знает, JITит код промежуточного интерпретатора, а не финальный код) даёт ускорение в разы. Но для этого надо его, да, прогреть (считаем, 50000 проходов по коду).

В условиях Erlang, HiPE давал нашему коду ну процентов 5. Если какой-то JIT ускорит его вдвое — это уже очень хороший показатель. А там можно думать и об интеграции с чем-то типа C, где может быть полезно (хотя нам не помогло бы).

MA> Add: Прошу прощения, за то что ворвался. Ну просто такое вот наблюдение по жизни. В добавок из того очень малого, что я воочию видел в erlang — это то,что он мог очень хорошо распарралелить задачу (под это написанную), но выхлоп... эх. Мой наивный код сделал его раза так в 4, на весьма скромном железе.


Ну тут от задачи зависит. Я свою могу вполне осветить в деталях, и там действительно на I/O был местами основной упор... но не весь, не весь.

MA> Да, я понимаю,что лумать так не правильно, но я с тех пор считаю вот его ущербцем. Для клеевых целей возможно он и годиться, но античеловечный язык, имхо, — это двести камней против и никакие JIT нп помогут. Именно, что называется — нишевой. Это не плохо, но... нишевые GP решениянравятся как-то больше тупо синидиотически.


Слово "синидиотически" не находится. Опечатка или что?
The God is real, unless declared integer.
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 04:19
Оценка:
Здравствуйте, SkyDance, Вы писали:

N>>Это просто потрясающе, насколько вы сделали выводы безо всякой на то причины. Начнём просто с факта, что именно эти коллеги, которых вы тут походя назвали обезьянами, делали много полезных вещей, но именно к описанным проблемам они имеют минимальное отношение.


SD>Признаю, что потерял навыки обращения с языком, и сформулировал утверждение в очень кривой форме. Ни в коем разе не хотел назвать ваших коллег обезьянами.


OK, принято. Отвечу по предыдущему сообщению.
The God is real, unless declared integer.
Re[12]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 04:20
Оценка:
Здравствуйте, std.denis, Вы писали:

SD>>И тогда получается WhatsApp

SD>хм.. как-будто вацап это что-то хорошее, а не кусок говна, который даже нельзя на нескольких машинах использовать ¯\_(ツ)_/¯

Это уже, думаю, ортогональный вопрос. Коллега SkyDance наверняка не влияет на маркетинг или команду клиентской части.
The God is real, unless declared integer.
Re[11]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 05:43
Оценка:
Здравствуйте, SkyDance, Вы писали:

N>>Баги — исправляются. А вот принципиальная тормознутость рантайма — с ней сильно сложнее.

SD>Я так понимаю, "принципиальная тормознутость" рассматривается ниже (с конкретными проблемами). Или есть еще что-то еще? Кроме заявлений про "тормознутость", чтобы было нечто осмысленное. А то я вижу, что "тормознутость" — это 50.000 юзеров на машину в кластере (средней руки мессенджер на жаве) и 500.000 на такую же машину (на Эрланге).

В случае Java, я думаю, сделано просто какого-то явно лишнего кода. Или в условиях очень коротких сработок на один клиентский запрос с длительными ожиданиями между ними — сделана какая-нибудь глупость типа персональной нити на каждого клиента. Иначе бы такой суровой разницы не было.
Но это надо смотреть реализацию в деталях: что делается и как.

N>>Да. Только надо перестать смотреть на это как на "переизобретение эрланга". Даже если Erlang был одно время образцом, то все эти реализации уже давно ушли дальше.

SD>Это и есть переизобретение эрланга. "Эти реализации" ушли не дальше, а в болото. Как туда уходит любой мейнстрим, см. Жава, С++.

Вы можете считать это болотом, но эта кочка зрения (tm) не выглядит обоснованной. Мейнстрим уходит в обеспечение значительно более широкого набора потребностей, чем нишевый продукт, в более разнообразных условиях. Но это никак не означает невозможность качественной специализации под конкретную реализацию.

N>>OK, когда будут множественные входные очереди на процесс?

SD>Сначала нужно объяснить, зачем. Один из патчей, который я сделал, как раз подобная поддержка (в слегка упрощенном виде, т.н. prepend send, послать сообщение в голову очереди). Но чем больше я занимаюсь архитектурой и более серьезным пониманием происходящих процессов, тем больше я понимаю, как был неправ. Просто на тот момент, когда я это сделал, у меня не было достаточно знаний. Сейчас эти знания есть, и я понимаю, что и prepend send, и "множественные очереди", и priority queues — это ошибочные направления. Но, повторюсь, чтобы это понять, нужно действительно провести много времени за изучением этих проблем.

Ну в таком случае выдайте на-гора, пожалуйста, хоть немного этой мудрости (в хорошем смысле), почему это "ошибочное направление". А то то, что я вижу, пока что подтверждает важность подхода.

Вот например RabbitMQ борется с такой проблемой:

  цитата
%% gen_tcp:send/2 does a selective receive of {inet_reply, Sock,
%% Status} to obtain the result. That is bad when it is called from
%% the writer since it requires scanning of the writers possibly quite
%% large message queue.
%%
%% So instead we lift the code from prim_inet:send/2, which is what
%% gen_tcp:send/2 calls, do the first half here and then just process
%% the result code in handle_message/2 as and when it arrives.
%%
%% This means we may end up happily sending data down a closed/broken
%% socket, but that's ok since a) data in the buffers will be lost in
%% any case (so qualitatively we are no worse off than if we used
%% gen_tcp:send/2), and b) we do detect the changed socket status
%% eventually, i.e. when we get round to handling the result code.
%%
%% Also note that the port has bounded buffers and port_command blocks
%% when these are full. So the fact that we process the result
%% asynchronously does not impact flow control.
port_cmd(Sock, Data) ->
    true = try rabbit_net:port_command(Sock, Data)
           catch error:Error -> exit({writer, send_failed, Error})
           end,
    ok.

(там где-то есть ещё и игнорирование этих tcp reply, не буду искать сейчас)


Опишите, пожалуйста, вашу точку зрения на их решение, одним из следующих вариантов (допустимы мелкие поправки):

1. Да, ребята молодцы, что для решения проблемы они полезли в обход аж двух слоёв стандартной библиотеки (gen_tcp и prim_inet), рискуя несовместимостью с будущими реализациями, так и надо. MQ много, OTP одна. Пусть страдают при переходе, не наше дело.

2. Нет, надо было искать чудо и делать, чтобы очередь никогда не превышала K сообщений, где K < N. Как это делать — да хоть через ETS, которую наполняет другой процесс. Публичная ETS (потому что удаляет другой процесс, чем добавляет) не страшна, все свои.

3. Надо было сидеть и страдать. Нефиг тут неуправляемые входные потоки принимать на процесс. TCP приёмник нормально контролирует, а заторы возникают по дороге? Пофиг, у меня всё работает (tm).

4. Вы неверно понимаете задачу и вообще у вас плохой дзен, становитесь ёжиками. Детали не интересуют, я стратегию разрабатываю.

5. Иное (интересно, что?)

N>>С какой версии это стало нормально работать? Я после 2015 не смотрел, до этого коллеги пробовали — не работало.

SD>В следующий раз посоветуй коллегам разобраться. Оно работало всегда. Могло не хватать каких-то инструментов для удобства. Но systools были еще с 90х годов.

Я именно про rebar. Где-то с 2012 вместо прежних подходов, когда народ достаточно любовно настраивал обстановку и был готов к тому, что система должна работать 24*365, пошли новые подходы типа
1) Пакуем всё в один тарболл вместе с рантаймом, зависимостями и рабочим кодом
2) Всей задачи девопам — развернуть на сервере и запустить
3) Прерывание сервиса? Если волнует, переедут на соседние узлы, если нет — и так пофиг
4) Завернём это ещё и в докер, нефиг тратить время на тюнинг внешних компонентов
5) failover, takeover, relup? Дядя, ты с кем сейчас разговаривал? У нас свои средства кластеризации и надёжности в кластере (90% — просто общая SQL база).

и именно к этому подходу rebar подошёл идеально и стал основным инструментом.

И на него тогда даже смотрели "а он сможет обеспечить нормальный relup на месте, без рестарта, при своей паковке?" и на версиях тех времён однозначно не сложилось.

N>>Основное было системой мониторинга кластера "Ломоносов". Её у нас забрали прямо в процессе затыкания этих проблем


SD>Вот в это я могу поверить — что в силу политических причин ("забрали проект") у кого-то образовалось неприятие к инструментам, которыми попросту не научились пользоваться.


Нет, для себя мы её решили — костылями различной кривости. На продуктин оно не ушло — или ушло, не знаем — но это уже стало не нашей заботой.

N>>А тут она ещё и грубо неверна. Когда проект начинался, мы взяли в контору группу военных админов(!) и они успешно за срок менее месяца переключились на проектирование и написание (при том, что часть ещё и не имела опыта программирования кроме одноэкранных скриптов баша) — и всё шло замечательно до тех пор, пока под реальной нагрузкой не начались уже характерно эрланговые проблемы, как минимум:


SD>Прям-таки классика жанра! Когда я написал "нельзя набрать обезьян" — я ровно это и имел в виду. Дело в том, что синтаксис и "первые шаги" на Эрланге до одури просты. И потому возникает ощущение "мы все поняли и все умеем". Но когда дело доходит до написания реального софта, оказывается, что кроме синтаксиса нужно еще... понять, что такое OTP, и как на самом деле надо пользоваться языком. Вы, однако, так и не поняли. Посему и проблемы, перечисленые ниже. Как раз отражение непонимания, как должна работать система.


Спасибо за извинения за "обезьян" (в соседнем сообщении), повторюсь, что именно эта группа не имеет отношения к проблемам перегрузки. Проблемы же возникали в следующей обстановке:

1. Приложение NA принимает входной поток (его плотность... ну давайте для простоты остановимся на цифре 10K сообщений в секунду) из толпы разных источников (можно распределять между экземплярами приложения на разных узлах). Но сообщение групповое, содержит ~50 вложенных других, и реально обрабатывается 500K. При первичной обработке поток сокращается в ~5 раз, получается 100K mps. Одно сообщение со всеми деталями это, насколько помню, около 200 байт. Вроде бы поток небольшой.

2. Поток выходных сообщений из NA отправляется на несколько приёмников, для простоты скажем про 2: генератор первичных логических выводов (NMU) и логгер. Реально между ними сидит ещё приложение шины (приняло и перепостило подписчикам).

3. NMU делает первичные выводы и посылает их на шину 2. Там свои логгер и групповая логика.

4. Приложение групповой логики (GL) делает выводы уже финальные — типа "стойка 123 недопустимо перегрета, надо выключать оборудование".

В спокойной обстановке на участке NMU — GL поток сообщений в десятки раз меньше входного потока NMU (то есть тысячи, если не сотни, в секунду, уровня "тут всё спокойно, тангаж, крен, рысканье в норме, температура 36.6"), при проблемах — может подскакивать до равного потока (считаем, те же 100K mps). Работа при пиковой нагрузке, соответственно, критична (должно быть всё гладко-линейно и должен ещё быть запас производительности).

Реально частично работало горизонтальное деление — NC, NMU, часть GL просто горизонтально масштабировалась. Но уже участок — вершина GL, и всё, что за ним — регистратор алармов, логгеры этой части, генератор команд по выводам GL (типа, уже надо грубо выключать ток) — не масштабируются. У получателя, типа регистратора, один отправитель. Не 100500 отдельных мелких, каждый из которых послал какое-нибудь "GET /zuka HTTP/1.1", а один, и он не ждёт — посылает следующие.

И вот тут начинается, что любой из процессов — приёмников потока:

1) Если он делает только обработку входящих сообщений и асинхронные посылки другим — живёт. (На самом деле чуть сложнее — иногда получалось, что и в этом случае начиналось торможение. Но этот вопрос на потом.)
2) Если ему хоть иногда надо делать синхронные вызовы (gen_server:call) и соответственно сразу ждать отвёт — всё, суши вёсла: из накопления входной очереди выше 10-20K сообщений он не способен уже выйти. Граница неточная, но, похоже, связана с размером кэша процессора. Временное переполнение, безвредное в других условиях, становится фатальным (надо только рубить процесс).
3) Даже если он сам не делает синхронные вызовы, задача оперативно получить состояние, не блокируя запрашивающего на недопустимый срок (1 секунда уже предел), не выполняется — пока прорабатываются остальные, {'$call',запрос} стоит в конце очереди.

Вот теперь я хочу послушать Ваши предложения по исправлению этих проблем в пределах текущих возможностей Erlang.

N>>1) Переполнение входных очередей без возможности адекватного взаимодействия с пострадавшими процессами; лечилось грубыми хаками типа просовывания управляющих команд через ETS с соседним процессом;


SD>Иными словами, не смогли правильно реализовать backpressure.


Нет. Backpressure вообще недопустим на участке как минимум после NMU. Есть некоторый уровень нагрузки, который в ламинарном состоянии это весьма мелкая доля от того, что может осилить железо и рантайм. Но это в ламинарном. Как только где-то перегрузка, Erlang не даёт восстановиться.

В том решении, которое было испытано локально, но не дошло до целевой эксплуатации, было сделано, что при детекте перегрузки NMU приостанавливает отдачу разрешений посылки сообщений исходным агентам. (Ну и темп регулировался, понятно, общими настройками.) Но даже это пришлось решать немного хакерски, ну и сама постановка вопроса означала, что система не справляется с задачей — состояние должно сниматься не реже раза в секунду, и не теряться.

SD> Справедливости ради, это действительно holy grail асинхронного программирования, и по сути нормально нигде и не реализовано. Да, есть теоретические измышления (SEDA та же) и кое-какие реализации (а ля GenStage), но чтоб серьезно к этому делу подойти, — пока руки не дошли. На данный момент все в стадии написания whitepaper.


Меня тут не интересуют дискуссии о теоретических основах. Остановить агентов мы были в состоянии. Реально они сами останавливались, не получив команды "даю разрешение на 5 отчётов". Меня интересует именно устойчивость реакции на перегрузку. В идеале, пока нет других проблем типа переполнения по памяти, ему должна была быть пофиг длина очереди, хоть миллиард.

N>>2) Страшно тормозной global, с синхронизацией, страдающей при перегрузке (попросту кластер рассыпался — и это при несчастных ~30 узлах); сейчас, по слухам, есть настройка "межкластерные данные идут по другим каналам, чем heartbeats", я не успел это сделать — выдернули на живую.

SD>Сейчас global попросту не нужен (как он не был нужен и раньше). Если нужны process groups, они уже есть (и нет, не pg2, которые работали поверх global). В общем, то, что вы не смогли кластер из 30+ машин поднять, так я про то и пишу — надо было разработчиков высокой квалификации брать. Тогда и 20.000 машин в кластере не были бы проблемой, и даже 30.000 (больше просто пока не требовалось).

И снова домыслы и критика "обезьян". Но это я отложу на следующий заход.

N>>Были и другие, поменьше, но облом вспоминать (попросишь — подниму архивы).

SD>Нет смысла. Я уже понимаю, что не тот уровень знаний.

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

N>>Эти проблемы я обсуждал с Валкиным, Лапшиным, Димандтом

SD>А надо было обсуждать с Lukas Larsson, Kenneth Lundin, Rickard Green, Sverker Eriksson, Kjell Winnblad. Круг, действительно, узок, и он не включает ни одной из указанных выше фамилий.

Общением с кем-то из core team занимались другие коллеги. Успеха не добились.
The God is real, unless declared integer.
Отредактировано 06.08.2020 5:55 netch80 . Предыдущая версия .
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 09:07
Оценка: 11 (1)
Здравствуйте, Mystic Artifact, Вы писали:

MA> От души могу добавить только то,что любому человеку который скажет что в каждой ... программе есть часть лиспа — готов не только плюнуть в рожу, но и больно ударить в нос. Потому что это бредятина сивой кобыли и слезные мечтания.


MA> Я ваш лисп наблюдал в ныне процветающих CAD системах и ничего кроме как сказать, что это полное уебище — просто невозможно.


MA> Но конечно, всегда найдутся альтернатмвно мыслящие которые найдут в этом хоть каплю хорошего. А что долдно быть им не ведомо.


Я таки чуть вступлюсь за него (заранее прикрыв нос)
Что собственно хотел сказать тут Гринспун, это следующее:

1. Толстая система (будем говорить так) достаточно быстро дорастает до состояния, когда её надо тюнить по куче параметров, причём (если это десктопное приложение) индивидуально и часто ещё и параметризованно.
2. Толстая система должна поддерживать скриптование — как хуки на события, так и просто автоматизацию (по кнопке).
3. Язык этих скриптов должен быть достаточно гибким, чтобы быть, грубо говоря, эквивалентным машине Тьюринга.
4. Язык этих скриптов должен позволять средства метапрограммирования, включая генерацию кода на ходу (даже если от неё требуется примитив уровня make_adder).

По состоянию на сейчас этому соответствуют несколько языков, сюда годятся JavaScript, Python, Ruby, Lua и с два десятка ещё других менее известных. Но:

1. На 1993, широко известным таким языком был, пожалуй, только LISP. Остальные были в зачаточном состоянии (Python, Ruby) или вообще ещё не родились. Может, были какие-то сейчас забытые (наверняка даже были), но тоже малопопулярные.
2. LISP, в отличие от остальных, обладает гомоиконичным метапрограммированием, то есть в нём код и данные представлены идентично, любые данные могут быть отданы на исполнение как код. Код можно реформировать, оптимизировать и т.д. обычными средствами работы с данными. (Как пример, это делается внутри GCC: его GIMPLE это специализация LISP.) У остальных надо как минимум конвертировать между исполнимым и обрабатываемым представлениями.

Ну и Common LISP был на тот момент развитой отработанной реализацией.

Это всё не значит, что сейчас надо всегда использовать LISP, тем более тяжеловатый Common LISP. GNU в основном использует свою реализацию, близкую к Scheme. Гугл использует JavaScript (например, вы можете даже на стандартном акаунте нарисовать скрипт, который будет что-то делать с документами на Google Drive, и сказать запускать его периодически или по триггеру). В небольшой программе на C/C++ можно собрать код на ходу через libjit, в более толстой — подключить LLVM. Важно понимать стоящий за этим принцип.

В задаче реализации распределённого сервиса с устойчивостью к локальным проблемам, сетевым проблемам, невидимым обновлением на ходу и т.д. — Erlang показывает аналогичный образец, тут Вирдинг в заметной мере прав. Эрланг старается держать марку идеала такой ниши; там, естественно, есть 100500 вопросов к отдельным моментам реализации, но как образец он сохраняет силу и сейчас.
Другой вопрос, что уже появились неплохие конкуренты (вроде Go)...

Ну и проблемы у LISP с Erlang в заметной мере одинаковые из-за, например, функционального подхода (хоть и самого примитивного, по сравнению с группой ML, хаскеллоидами и так далее) — если 99% программистов пишут императивно, то в фаворе будут императивные средства.

И спасибо за комплимент

MA> А я вот знаю точно — ни лиспу ни эрлангу в современном мире места нет. Доживают, не иначе.


MA> Add: А если ты не GP язык — то заявить как бы и нечего. И дело даже не в обезьянах... Просто, каждый язык и область требует своего погружения. Где-то рядом в темах мне наверное не верят, что люди выжимают из выровненных указателей. На кой оно надо? Где это вообще возможно? Зачем? Но, я вот нашел ответы для себя на эти вопросы. Зачем ерланг, раст, го или еще какая люси — мне неведомо. Да, список просто наугад взят. Вся популярность раста растет не из за его ебанутой прости господи модели, а то что серво+мозилла. Так то он язычок был и есть так себе. Тоже самое с го без гугла — никто б и не взглянул. Так и ты с эрлангом, но это просто нишевое решение.


Не путай таки, кто раскручивает изначально, и есть ли в принципе заметный смысл. Что раскрутить язык сейчас требует заметных ресурсов — факт, поэтому идут на это только крупными коллективами и от безысходности. Поддержка — тоже (подсчитаем-ка затраты на развитие GCC и Clang). Но дальше, набрав силу, он может существовать и без начального толкателя.
На сейчас, мне кажется, Rust и Go достигли того уровня, который позволяет существовать без первосоздателя — его роль кто-то точно подхватит. А вот для Erlang это откровенно сомнительно. Ну разве что тот же фейсбук с WhatsApp подхватит... но популярности ему это не добавит.

MA> За пределами своей ниши обитают только обезьяны, и хотя это видимо должно многим людям быть обидно, просвященный человек в 2020 году знает что теория эволюции Дарвина относительно человека весьма туманна, а большинство находок начала прошлого столетия — подделки. Шило в мешке не утоишь.


The God is real, unless declared integer.
Re[9]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 09:08
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>Короче говоря, можно переизобрести этот велосипед (эрланг) еще 10 раз. Например, akka streams есть не что иное как. И Orleans тоже. И go, и вообще практически весь современный concurrency-oriented софт.


Тут сказывается непонимание. У Go достаточно древние корни: Go->Alef->Newsqueak->Squeak. Так что непонятно еще, кто первоначальный изобретатель этого велосипада. Но скорее всего, там мысль двигалась параллельно у разных людей.

P.S. И что интересно, и Go и Erlang пришли из телефонной индустрии
Re[12]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 09:22
Оценка:
Здравствуйте, std.denis, Вы писали:

SD>>И тогда получается WhatsApp

SD>хм.. как-будто вацап это что-то хорошее, а не кусок говна, который даже нельзя на нескольких машинах использовать ¯\_(ツ)_/¯

Ну это ж придирка не к имплементации, а к Т.З. Его-то (Т.З.) вряд ли на Ерланге писали
Re[12]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 09:49
Оценка:
Здравствуйте, netch80, Вы писали:

N>2) Если ему хоть иногда надо делать синхронные вызовы (gen_server:call) и соответственно сразу ждать отвёт — всё, суши вёсла: из накопления входной очереди выше 10-20K сообщений он не способен уже выйти. Граница неточная, но, похоже, связана с размером кэша процессора. Временное переполнение, безвредное в других условиях, становится фатальным (надо только рубить процесс).


Вот по таким оговоркам сразу видно профессионала. Любителю такая гипотеза в голову не придет (это искренний комплимент, а не скрытая ирония).

А что, у ерланга вынимание из очереди пробегается по всей памяти очереди? Потому что иначе трудно понять, почему временное достижение очередью размера кэша настолько замедляет разгребание очереди, причем делает это "навсегда", что программа уже не восстанавливается.
Re[14]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 10:35
Оценка:
Здравствуйте, netch80, Вы писали:

N>Я таки чуть вступлюсь за него (заранее прикрыв нос)

N>Что собственно хотел сказать тут Гринспун, это следующее:

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

Сравни, например, подход sendmail, который по сути представляет собой этакий тьюринг-полный rewrite engine, с сетевыми сокетами и спулером (правда, не с лиспом, а с рефалом внутри, видимо для разнообразия) с более современными мейлерами, типа postfix/exim, написанными, когда уже стало понятно, чего MTA должен делать, а потому у них конфигурация описывается уже в предметных терминах, и в тьюринговской полноте не нуждается.

N>На сейчас, мне кажется, Rust и Go достигли того уровня, который позволяет существовать без первосоздателя — его роль кто-то точно подхватит


Мне кажется, критерием достижения такого уровня является появление независимых компиляторов. Go достигнет этого уровня, когда и если LLVM Go наконец доведут до ума (gccgo не считается, это те же самые люди).
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: std.denis Россия  
Дата: 06.08.20 11:27
Оценка: +1
SD>>>И тогда получается WhatsApp
SD>>хм.. как-будто вацап это что-то хорошее, а не кусок говна, который даже нельзя на нескольких машинах использовать ¯\_(ツ)_/¯
Pzz>Ну это ж придирка не к имплементации, а к Т.З. Его-то (Т.З.) вряд ли на Ерланге писали

ну тут сложно сказать со стороны – это может быть как административным ограничением, так и технической неспособностью реализации

просто не смог пройти, когда в очередном сообщении увидел ещё раз кичливое "мы тут настоящие инженеры и создали чудо инженерной мысли" и всю эту "обезьянью" демагогию 🙈
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: lpd Черногория  
Дата: 06.08.20 11:41
Оценка: +1
Здравствуйте, Pzz, Вы писали:

Pzz>Ну это ж придирка не к имплементации, а к Т.З. Его-то (Т.З.) вряд ли на Ерланге писали


Дизайн и маркетинг у whatsapp на уровне. Но технически сверх сложного ничего нет, даже с учетом большого числа пользователей. Обычный мессенджер, не более.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[14]: WA: 3 млн tcp соединений на одном сервере
От: Слава  
Дата: 06.08.20 11:57
Оценка: 10 (1) +1
Здравствуйте, std.denis, Вы писали:

SD>просто не смог пройти, когда в очередном сообщении увидел ещё раз кичливое "мы тут настоящие инженеры и создали чудо инженерной мысли" и всю эту "обезьянью" демагогию


Я с огромным интересом читаю тред, и жду очередного ответа SkyDance. А про демагогию — ну для начала тут у нас КЫВТ, да и никакой демагогии в его словах я не заметил.

Слушайте, где ещё вы сможете пообщаться с человеком на подобной должности? Тут надо аккуратно спрашивать и не докапываться до слов.
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 13:33
Оценка: 5 (1)
Здравствуйте, Pzz, Вы писали:

Pzz>А что, у ерланга вынимание из очереди пробегается по всей памяти очереди? Потому что иначе трудно понять, почему временное достижение очередью размера кэша настолько замедляет разгребание очереди, причем делает это "навсегда", что программа уже не восстанавливается.


У него это выглядит так: оператор receive может получать шаблон или нет.
Если шаблона нет, просто хватается сообщение из головы очереди.
Если шаблон есть, идёт перебор начиная с головы пока не встретится сообщение, соответствующее шаблону. Точнее, шаблонов может быть несколько, они проверяются по приоритетам.
Если такого сообщения (не соответствующего ни одному из предложенных шаблонов) в очереди нет, то процесс переходит в спячку, а при поступлении новых пробуждается на проверку поступивших. У спячки может быть задан таймаут.
Можно посмотреть, например, здесь.

Нормальный цикл процесса выглядит примерно так: я переписываю для ясности на C-подобный синтаксис:

work() {
  Message = receive(); // из головы очереди, вариантов нет
  if (Message LIKE первый шаблон) { ... }
  else if (Message LIKE второй шаблон) { ... }
  ...
  work(); // циклов в коде нет, всё пишется через рекурсию, интерпретатор умеет хвостовую рекурсию
}


в этом варианте всё ещё относительно шустро (с поправкой на динамику).

Проблемы начинаются, если делается синхронный вызов. Каждый такой вызов это:

1. Клиент заворачивает свой запрос — далее Request — в кортеж с тегом "это синхронное сообщение от меня"; в его синтаксисе это, чуть упрощая, Message переводится в {'$call', pid(), Request, make_ref()} и это отправляется серверу. make_ref() это функция генерации уникального значения (считай GUIDʼом, но конструируется иначе).

2. Сервер, получив нечто соответствующее такому шаблону {'$call', Client, Request, Ref}, исполняет запрос и отдаёт свой ответ, посылая процессу Client сообщение {'$reply', Ref, Reply}, где Reply — его ответ.

3. Клиент в это время находится в ожидании ответа, выполняя код типа

Ref = make_ref();
send(ServerPid, {'$call', pid(), Request, Ref});
Resp = receive(       //  <-- вот тут сидим в ожидании ответа
  {'$reply', Ref, *}, //  <-- это шаблон для поиска в очереди
  5000);              //  <-- таймаут, по умолчанию это 5 секунд, пишется в миллисекундах


И вот тут начинаются проблемы. Представим себе, что в очереди 10000 сообщений. receive() всегда работает одинаково: начинает перебирать с головы очереди. Как-то ему сказать, что сейчас ещё точно ответа нет? Не положено. Значит, послали запрос и начинаем перебирать эти 10000 сообщений... хотя твёрдо известно, что в этом нет смысла.
В худшем случае, если делается один синхронный вызов на каждое входящее сообщение, время работы становится O от квадрата длины очереди — что мы и наблюдали в полный рост.

В общем случае это решается несколькими вариантами:

1. Перед посылкой запроса узнать позицию хвоста очереди, а в receive() передать её, чтобы итерирование в поиске ответа начиналось с этой позиции.
Это оптимизация на частный случай, и она сделана, кажется, в 14-м релизе, но она 1) завязана на получение этого самого Ref, а поэтому не работает, например, при отправке в TCP порт (это то, что как раз обходится залезанием в потроха в RabbitMQ), и вообще для всех случаев за пределами стандартного вызова стиля gen_call; 2) делается не программистом, а компилятором на анализе кода, и поэтому отклонение от идеального шаблона make_ref() — send() — receive() сразу ломает логику и выключает оптимизацию. Дать возможность программисту управлять этим они отказались.

2. Сделать таки хотя бы 2 очереди, честные FIFO, и пусть обычный send() отправляет в 0, а спецпосылки и ответы на синхронные запросы — в 1; пусть синтаксис receive не менять, но чтобы очередь 1 всегда проверялась первой. Это даст универсальное решение для таких ожиданий и не только; я писал в предыдущем, что у нас при такой перегрузке даже нормальный call() тормозил и выбивался по таймауту из-за перегрузки входа (обычный разбор идёт строго последовательно).

N>>2) Если ему хоть иногда надо делать синхронные вызовы (gen_server:call) и соответственно сразу ждать отвёт — всё, суши вёсла: из накопления входной очереди выше 10-20K сообщений он не способен уже выйти. Граница неточная, но, похоже, связана с размером кэша процессора. Временное переполнение, безвредное в других условиях, становится фатальным (надо только рубить процесс).


Pzz>Вот по таким оговоркам сразу видно профессионала. Любителю такая гипотеза в голову не придет (это искренний комплимент, а не скрытая ирония).


Спасибо на самом деле я уже за давностью не помню, это я предположил или кто-то из команды, но я запомнил и оно, по экспериментам, подтвердилось.
При такой квадратичной зависимости от длины очереди дополнительный рывок торможения в 10-15 раз за счёт вылета из кэша оказался смертельным для задачи.
The God is real, unless declared integer.
Re[15]: WA: 3 млн tcp соединений на одном сервере
От: Sharov Россия  
Дата: 06.08.20 13:41
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Мне кажется, это происходит от того, что разработчики системы, толком не понимая, что она должна делать, сваливают свой технический долг на голову специалистов по эксплуатации. Отсуда и возникает потребность в тьюринг-полных конфигурационных скриптах.


Скорее менеджеры, и скорее как средство борьбы с постоянными модификациями и изменениями. Причем для разных клиентов. Ядро трогать не надо, но поведение адаптировать как-то надо. Вот и прикручивают скрипты.
Кодом людям нужно помогать!
Re[4]: Дублирую вопрос.
От: Sharov Россия  
Дата: 06.08.20 13:56
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>Что именно интересует? Просто открыть 3 млн соединений проблем нет почти на любой языке.


Ну вот индус спрашивает про rp\lb. Это что-то свое самописное или используете известные вещи типа nginx? Если известные, то что? Если не NDA.
Кодом людям нужно помогать!
Re[14]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 14:03
Оценка:
Здравствуйте, netch80, Вы писали:

N>Проблемы начинаются, если делается синхронный вызов. Каждый такой вызов это:


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

Ужос.

При такой архитектуре напрашивается мысль, что использование синхронных вызовов во всех промежуточных процессах — непозволительная роскошь. Т.е., процесс должен получить сообщение, что-то с ним сделать, куда-то переслать дальше, если сам не может обработать, и забыть навсегда. Отправка ответа изначальному инициатору запроса всегда должна быть заботой того процесса, который окончательно разрешил вопрос (самого последнего процесса в цепочке).

Хуже всего получаецца, если цепочка исполнения запроса разветвляется, и "последних" процессов несколько. Тогда кто-то должен свести результат воедино. Наверняка в ерланге есть какая-то идеома на этот счет, такая потребность должна возникать постоянно.

N>Спасибо на самом деле я уже за давностью не помню, это я предположил или кто-то из команды, но я запомнил и оно, по экспериментам, подтвердилось.


Не скромничай, кто бы ни предположил, понять такую гипотезу тоже не всякий может
Re[15]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 14:16
Оценка:
Здравствуйте, Pzz, Вы писали:

N>>Проблемы начинаются, если делается синхронный вызов. Каждый такой вызов это:


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


Да, именно так. Ну см. поправку на оптимизацию частного случая, в который ещё надо попасть.

Pzz>Ужос.


Ну а я о чём говорю весь тред
Причём пролечить это — чуть сложнее чем совсем тривиально (добавить параметр в десяток похожих вызовов), но — не хотят. Первый известный мне плач относится к 2008 или 2009 году, а наверняка были и раньше.

Pzz>При такой архитектуре напрашивается мысль, что использование синхронных вызовов во всех промежуточных процессах — непозволительная роскошь. Т.е., процесс должен получить сообщение, что-то с ним сделать, куда-то переслать дальше, если сам не может обработать, и забыть навсегда. Отправка ответа изначальному инициатору запроса всегда должна быть заботой того процесса, который окончательно разрешил вопрос (самого последнего процесса в цепочке).


Это ещё один вариант залезания в потроха (формально, даже описанные мной форматы сообщений это внутренняя кухня модуля gen_server, а не публичное API), и/или заката солнца полностью вручную (самому отрабатывать все сообщения, включая служебные сообщения OTP).

Pzz>Хуже всего получаецца, если цепочка исполнения запроса разветвляется, и "последних" процессов несколько. Тогда кто-то должен свести результат воедино. Наверняка в ерланге есть какая-то идеома на этот счет, такая потребность должна возникать постоянно.


Именно такого, по-моему, нет. Обычный API даёт только синхронные вызовы или асинхронные передачи, остальное — делайте сами.

N>>Спасибо на самом деле я уже за давностью не помню, это я предположил или кто-то из команды, но я запомнил и оно, по экспериментам, подтвердилось.


Pzz>Не скромничай, кто бы ни предположил, понять такую гипотезу тоже не всякий может


ok
The God is real, unless declared integer.
Re[16]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 14:29
Оценка: 117 (1)
Здравствуйте, Sharov, Вы писали:

S>Скорее менеджеры, и скорее как средство борьбы с постоянными модификациями и изменениями. Причем для разных клиентов. Ядро трогать не надо, но поведение адаптировать как-то надо. Вот и прикручивают скрипты.


Это не менеджеры, это такая жизненная позиция, называется программирование не для людей, а для компьютеров.

У человека, который приходит к программисту, всегда есть какая-то проблема. И она не программистская, а жизненная, иначе он сам бы написал программу. Например, сделать так, чтобы фотки котиков можно было посылать знакомым барышням. Заметим, в изначальной формулировке проблемы слово "компьютер" вообще не упоминается, это можно сделать с помощью голубей.

Менеджер предложит систему, в которой фотки котиков сохраняются на компьютере в форматах PNG или JPEG, приаттачиваются к электронным письмам и отправляются по системе e-mail. Количество проблем у пользователя сразу увеличилось: надо как-то извлечь фотографии в нужных форматах, у барышень должен быть компьютер, все участники должны обзавестись программами для e-mail и адресами, и научиться как-то всем этим хозяйством пользоваться. Зато бизнесу стало хорошо: все участники заплатили по 5 баксов за интернет, а некоторые еще и купили книжку на 500 страниц "как научиться пользоваться е-мейлом за 15 простых шагов".

Программист систему реализует, и в картине мира появятся дополнительные сущности, такие, как Mail Transfer Agent, DNS, PPP authentication, network packet routing и т.п. К счастью для себя, ни пользователь ни барышни про эти дополнительные сущности почти ничего не узнают, кроме иногда появляющихся на экране непонятных для них сообщений об ошибках внутри этих самых сущностей ("mail delivery failed: DNS lookup timed out"). Все попытки объяснить пользователю, где у котика находится DNS, уткнутся в глухую стену непонимания, и в конце концов пользователь смирится с тем, что компьютеры постоянно глючат, но метод try again/reboot and try again/reinstall windows and try again обычно помогает.

А потом придет WatsApp, и сделает все для людей (воспользовавшись уже накопленной к этому моменту инфраструктурой): фотка котика будет браться прямо из камеры телефона и отправляться к барышне. И всем станет хорошо.

Реально, создание платформы, на которой какую-то жизненную проблему можно решить — это примерно 10% работы, необходимой для решения проблемы. Жизненная позиция заключается в том, что всем нравится создавать платформы, а не решать проблемы.
Re[15]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 14:33
Оценка:
Здравствуйте, Слава, Вы писали:

С>Слушайте, где ещё вы сможете пообщаться с человеком на подобной должности? Тут надо аккуратно спрашивать и не докапываться до слов.


Интернет сделал мир плоским. В том смысле, что он теперь невысокий и широкий. В этом новом электрическом мире с кем угодно можно перекинуться парой писем
Re[15]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.08.20 14:34
Оценка:
Здравствуйте, Pzz, Вы писали:

N>>Я таки чуть вступлюсь за него (заранее прикрыв нос)

N>>Что собственно хотел сказать тут Гринспун, это следующее:

Pzz>Мне кажется, это происходит от того, что разработчики системы, толком не понимая, что она должна делать, сваливают свой технический долг на голову специалистов по эксплуатации. Отсуда и возникает потребность в тьюринг-полных конфигурационных скриптах.


Pzz>Сравни, например, подход sendmail, который по сути представляет собой этакий тьюринг-полный rewrite engine, с сетевыми сокетами и спулером (правда, не с лиспом, а с рефалом внутри, видимо для разнообразия) с более современными мейлерами, типа postfix/exim, написанными, когда уже стало понятно, чего MTA должен делать, а потому у них конфигурация описывается уже в предметных терминах, и в тьюринговской полноте не нуждается.


Позиция понятна, но согласиться сложно. Проблема в том, что у толстых систем очень часто есть какая-то внешняя интеграция, и вот с кем и как — заранее предсказать и определить все случаи невозможно.

Возьми даже майкрософтовский офис. Что ему на скрипты навешивают? Вполне может быть, что нажатие кнопки на экселевском листе вызывает цепочку реакций вплоть до открытия ворот, посылки робота на склад или подрыва пиропатрона. И как ты такую реакцию запишешь в готовый код?

Или более программистский пример. Есть пачка тикетниц (JIRA, Youtrack, RT, Redmine, ORTS...), серверов репозиториев (Gitlab, Gerrit...), CI серверов (Jenkins, Travis... ничего не путаю?)
И что, просить для каждого из них плагин у авторов?

Можно требовать писания плагинов, а можно — скриптов, если у них есть достаточный доступ внутри и снаружи. Скрипт будет плагином, просто не компилируемым в целевой язык.

И такие плагины не единственная задача скриптования. Даже просто автоматизировать последовательность своих действий или вызвать её по внешнему сигналу — уже задача достойная введения какого-то внутреннего языка.

А дальше — какие-то функции могут быть унесены в сердце, какие-то — в штатные плагины, но появятся новые запросы (если продукт всё ещё нужен) и реализовываться будут на том же языке.

Про sendmail история отдельная. Фактически его популярность вызвана тем, что он был в базовой поставке BSD систем, а туда попал потому, что разработчик был "свой" из своей тусовки. В то же время был, например, zmailer, у которого был свой скриптовый язык стиля шелла. Но кто сейчас помнит про zmailer, кроме совсем уж ветеранов типа меня?
И у exim, если ты не видел, есть Perl map. Через который включается любое внешнее скриптование в пределах, как можно что-то сделать вызовом мапы

N>>На сейчас, мне кажется, Rust и Go достигли того уровня, который позволяет существовать без первосоздателя — его роль кто-то точно подхватит

Pzz>Мне кажется, критерием достижения такого уровня является появление независимых компиляторов. Go достигнет этого уровня, когда и если LLVM Go наконец доведут до ума (gccgo не считается, это те же самые люди).

У Go уже давно свой компилятор и собственный бутстраппинг. Хотя стиль и качество выходного кода у него, мягко говоря, своеобразно.
The God is real, unless declared integer.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.