Re[16]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.08.20 14:42
Оценка:
Здравствуйте, netch80, Вы писали:

N>Про sendmail история отдельная. Фактически его популярность вызвана тем, что он был в базовой поставке BSD систем, а туда попал потому, что разработчик был "свой" из своей тусовки. В то же время был, например, zmailer, у которого был свой скриптовый язык стиля шелла. Но кто сейчас помнит про zmailer, кроме совсем уж ветеранов типа меня?


Я его как-то даже себе поставил zmailer, когда осознал, что sendmail я один раз настроить могу, а вот поддерживать его, не будучи профессионально этим озабочен (т.е., залезая в его настройки раз в полгода) не могу. Запускаю я его, все вроде как работает, только компьютер раз в несколько секунд диском похрюкивает. Оказалось, что я что-то недоделал, тестовое письмо куда-то не дошло, и он написал отлуп. Который тоже не дошел, и на него тоже написался отлуп. Так он сам с собой и переписывался, пока я это случайно не заметил. Накопившаяся к тому времени история переписки была уже вполне впечатляющего размера. Но что характерно, систему почти не грузила, как и обещали.

N>И у exim, если ты не видел, есть Perl map. Через который включается любое внешнее скриптование в пределах, как можно что-то сделать вызовом мапы


Я обычно использую exim.

N>У Go уже давно свой компилятор и собственный бутстраппинг. Хотя стиль и качество выходного кода у него, мягко говоря, своеобразно.


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

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


Ну да, делаешь асинхронные передачи по цепочке. Потом где-то сводишь результат. Обещанная при этом простота куда-то вдруг волшебным образом рассасывается
Re[17]: WA: 3 млн tcp соединений на одном сервере
От: Sharov Россия  
Дата: 06.08.20 20:22
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Реально, создание платформы, на которой какую-то жизненную проблему можно решить — это примерно 10% работы, необходимой для решения проблемы. Жизненная позиция заключается в том, что всем нравится создавать платформы, а не решать проблемы.


А причем здесь здесь 10%? Речь про требования, которые постоянно и по-разному меняются. Программисты и пишут решения проблемы, а потом выясняется,
что решений много или для каждому заказчику нужно свое решение. Программисты и начинают писать платформу. Ну или добавляют скриптование или DSL, что
сам код ядра не трогать.

ЗЫ: может эту ветку в менеджмент снесете?
Кодом людям нужно помогать!
Re[12]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 07.08.20 01:34
Оценка:
N>В условиях Erlang, HiPE давал нашему коду ну процентов 5.

Это хороший показатель HiPE вообще был по сути исследовательским проектом.
Если что, его поддержку удалили из ОТР (буквально вот сейчас). JIT будет. Но вдвое — разве что только на очень специфичных задачах.
Равно как и статическая типизация, тоже будет.

А вот интеграция с С уже есть, и очень даже хороша — не понимаю, как вы могли упустить NIF. Особенно сейчас, в dirty CPU NIF & dirty IO NIF, и всем вокруг этого.
Re[12]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 07.08.20 03:07
Оценка:
ЗN>В случае Java, я думаю, сделано просто какого-то явно лишнего кода. Или в условиях очень коротких сработок на один клиентский запрос с длительными ожиданиями между ними — сделана какая-нибудь глупость типа персональной нити на каждого клиента. Иначе бы такой суровой разницы не было.

Именно в том и дело, что в Java/C++ и прочих "закатах солнца вручную" очень легко выстрелить себе в ногу. Вот в самом деле, персональная нить на клиента — это же, черт подери, удобно, и очень правильно! И, собственно, так и должно быть (более того, должно быть две нити на клиента, одна на вход, другая на выход, in/out pipes). Потому что это точно воспроизводит всю коммуникационную специфику. Неспроста же это решение возникло в телекоме. Обмен сообщениями. Просто, понятно, гениально.

N>Но это надо смотреть реализацию в деталях: что делается и как.


Как обычно. Дьявол в деталях. И в уровне разработчиков. То, что десяток профессионалов сделют на Эрланге, может быть недоступно сотне "обычных порошков". Для меня, кстати, это совсем недавнее открытие. Раньше я как-то и представить не мог, что один разработчик может быть на порядок более производителен, чем другой. То есть, раньше, в моем понимании, команда из пятерых человек по определению сделает больше, чем один гений. Вынужден признать, что глубоко заблуждался.

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


Как обычно, у любой проблемы есть варианты решений. Хотя для начала надо понять, почему у них эта проблема существует вообще.
1. Почему у writer'а длинная очередь?
2. Почему selective receive optimisation не работает для их случая?
3. Почему они вообще используют gen_tcp?

Могу лишь предположить, что:
а) переписывать старый код дорого
б) им нужно поддерживать старые версии OTP, или неподходящие для их софта ОС (ту же Windows)
в) нет большой нужды что-то улучшать в этом коде

Ибо если б нужна была, достаточно было бы просто перебраться на socket API, который выполнен в виде NIF и не страдает от указанных недостатков.

Я бы еще понял, если бы они страдали от странностей реализации TLS. Вот там да, мягко говоря, все очень и очень грустно, по куче разных причин. Что уж там, 3 последних PR я делал как раз вокруг TLS, ибо там и баги, и тормоза, и вообще — так делать не следовало с самого начала. Но "переписать с нуля" было бы еще менее осмысленным шагом, ибо это была бы уже четвертая реализация

N>1. Да, ребята молодцы, что для решения проблемы они полезли в обход аж двух слоёв стандартной библиотеки


Думаю, здесь было бы куда более логичным описать проблему более предметно. И вместо "обхода двух слоев" добавить нужную фунцкиональность. Но для этого им бы сначала пришлось разобраться в существующей. А вот это всегда и для всех было проблемой. Что уж там, сколько лет я пытаюсь подвинуть процесс интервью в направлении "проверять как кандидат умеет _читать_ код", но воз, увы, стоит на месте — все так же требует _писать_ код (который писать не нужно).

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


За такие "архите-крутные" решения вынесу порицание. И вообще, к моему страху и ужасу, кроме Вирдинга да еще пары человек понмания какие ужасы несут нам ETS, почти ни у кого нет. Как тут не вспомнить Хаскел, где усилие было приложено в нужном направлении, и ETS попросту нет (в том виде как они есть в Эрланге).

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


Этот вариант я не понял. Что именно предлагается? Разделить на два процесса, где у одного очередь и flow control, а второй непосредственно пишет в сокет? Да, так делают, да, нормально работает, но да, костыль. Но вообще эти страдания не совсем логичны. Впрочем, хорошо уже то, что у них таки есть разделение на r/w. Потому как куда более суровы страдания тех, кто в одном процессе все это делает, а потом жалуется, что gen_tcp:send() не возвращает управление пока данные не уйдут хотя бы в kernel send buffer.

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

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

Пожалуй, что "иное" — просто используйте socket. Если его нет в вашей версии, — портируйте. Вполне нормальная практика backport'ить что-то из старших версий, скажем, мы в древние времена бэкпортили crypto, чтобы работало с аппаратным ускорением (через УМЗ), а не как в R16B.

N>1) Пакуем всё в один тарболл вместе с рантаймом, зависимостями и рабочим кодом


Так ведь это и есть release (он же target system). Где-то еще так с начала 90х

N>5) failover, takeover, relup? Дядя, ты с кем сейчас разговаривал? У нас свои средства кластеризации и надёжности в кластере (90% — просто общая SQL база).


Традиционная проблема же, "нам некогда учиться, нам надо вчера", в итоге велосипедостроение в полный рост, tech debt, и — свой вариант, но очень незрелый, того что есть в ОТР.
Классика жанра. Очень немногие способны разобраться, понять как сделано, как надо, какие грабли были. Нет, вместо этого надо скорее делать, чтобы потом просто совершить еще один круг, еще один прыжок на месте, сделать свой Эрланг, с блекджеком и женщинами.

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


Может быть. Я в 2012 этим не занимался. Но были уже тогда systools. Но да, неудобные — и правильным вариантом было бы просто исправить. Ибо ведь open source. Это и есть подход, который я исповедую. Сначала разберись, потом пойми, потом осознай, почему так, — потом исправь и сделай мир лучше. Дай другим результаты твоего труда. Используй синергию этого процесса, объедини усилия.
Но да, это требует усилий.

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


Может, в этом причина недовольства?

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


Это же невозможно по определению. Или вы должны быть overprovisioned, чтобы соблюдать гарантии, или должна быть load shedding логика для защиты от перегрузки, или — backpressure.
"Все уже украдено до нас": https://ferd.ca/handling-overload.html

N>2) Если ему хоть иногда надо делать синхронные вызовы (gen_server:call) и соответственно сразу ждать отвёт — всё, суши вёсла


Хаха, как знакомо, все с тем же Вирдингом общались на тему "кто же это придумал gen_server:call и какие кары ждут его в аду"
Все правильно: как только нарушается стройная концепция ("процессы обмениваются сообщениями") и приходит императивный девелопер "нам нужно сделать RPC", как все сразу начинает работать не так, как задумано. Embrace concurrency, adopd asynchronicity, и так далее. Пока это не случится, будут все те же одинаковые проблемы с блокировкой процесса там, где не следует.

N>: из накопления входной очереди выше 10-20K сообщений он не способен уже выйти. Граница неточная, но, похоже, связана с размером кэша процессора.


Прочитав еще пару комментариев ниже, и увидев, как другие участники восхищаются скоростью постановки диагноза, просто обязан прокомментировать. Во-первых, отослать к моему выступлению на прошлой code MESH, — как раз на тему "in god we trust, all others must bring data".

Во-вторых, конечно же, у меня есть куда более простое, логичное и понятное объяснение, почему это происходит, ибо — я в теме разобрался чуть менее поверхностно. Допускаю, что у вас на тот момент не было никого, что мог бы просто воспользоваться gdb/perf/fprof/eprof/cprof, и понять, что дело не в кэше, а в том, как работает GC. Но да, что занятно, Rick Reed в свое время тоже наступил на сию граблю, но на то он и Rick Reed, чтобы разобраться. Я тогда еще и рядом не стоял. Могу лишь гордится тем, что учился у таких людей.

Так вот, возвращаясь к вопросу, — возможно в древних версиях, которыми вы пользовались, еще не было off-heap message queues, поэтому и случалась death spiral, когда с ростом количества сообщений в очереди GC становился все более и более дорогим, что вело к еще более быстрому наполнению очереди, что вело к еще более медленному GC, и так далее.

N> Временное переполнение, безвредное в других условиях, становится фатальным (надо только рубить процесс).


Кто хочет, ищет причины. Кто хочет — решения. Мы нашли решения: во-первых, добавили патч для flush message queue, во-вторых, допилили GC для более удачной работы с длинными очередями, в-третьих, когда доделали off-heap mq, просто перелезли на них.

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


Надеюсь, я ответил. No fate but the one we make. Если что-то сейчас в Эрланге не так, как нужно, это либо просто не было нужно до вас (и тогда — просто сделайте PR), либо... вам это не нужно, просто нужно разобраться, как оно на самом деле должно быть.

N>Нет. Backpressure вообще недопустим <...> Остановить агентов мы были в состоянии. Реально они сами останавливались, не получив команды "даю разрешение на 5 отчётов".


Или я чего-то не понимаю, или... это как раз и есть backpressure (в самом простом и классическом варианте, т.е. credit control. Странно, что это вы считаете "хаком". Это вполне легальный, и один из самых простых в реализации, способов. В конце концов, Ulf Wiger еще в 2010 (на деле, в 2005, но опубликовали позже) с теоретической стороны это рассмотрел. Позже, в том же Elixir, Jose Valim сделал аналогичный GenStage. Да что там, реализаций немало.

И. Справедливости ради, это же и есть holy grail. SEDA, и все эти akka streams, и все это reactive programming, — все аналогичные data flow pipelines, все это отнюдь не ново! Все уже было, и whitepapers более чем навалом, и реализаций. Если уж вы работали над "Ломоносовым", это ведь в МГУ, как могло так получиться, что вы не были знакомы со всеми работами в этом направлении? Уж на что моя должность прикладного характера, но даже я с ними знаком. Ибо без такого знакомства я был бы обречен написать очередной worker pool.


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


Давайте, очень жду. Чем же так был нужен global, чтобы вот без него никак.

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

N>Общением с кем-то из core team занимались другие коллеги. Успеха не добились.

Что такое core team?
OTP team, у них нет "core", есть VM, есть PS, и есть еще один человек сбоку. И так уже лет... пятнадцать. И вот это, да, проблема, слишком мало драйверов роста.

Не знаю, почему не удалось добиться успеха. У нас отлично получается.
Re[10]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 07.08.20 03:09
Оценка:
Pzz>Тут сказывается непонимание. У Go достаточно древние корни: Go->Alef->Newsqueak->Squeak. Так что непонятно еще, кто первоначальный изобретатель этого велосипада. Но скорее всего, там мысль двигалась параллельно у разных людей.

Erlang родом из 70х. Это и хорошо, и одновременно плохо — хорошо тем, что очень взрослый язык. Плохо тем, что слишком поздно он вышел из лаборатории, в 1998 году, на 15 лет позже чем стоило бы. Момент был упущен.

Pzz>P.S. И что интересно, и Go и Erlang пришли из телефонной индустрии


Такая уж предметная область (массивная параллельная обработка). По сути ведь это был язык для телефонных свитчей. Самых надежных в мире.
Re[14]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 07.08.20 03:16
Оценка:
N>Проблемы начинаются, если делается синхронный вызов. Каждый такой вызов это:

Правильно. В первоначальном варианте языка никаких "синхронных вызовов" не предусматривалось (и правильно, по делу).

N>Это оптимизация на частный случай, и она сделана, кажется, в 14-м релизе


А сейчас на дворе 23.
И оптимизации сделаны чуть иначе, с чуть большими возможностями. Но, да, только под конкретный шаблон (тот самый gen_server:call).
Странно еще что вы не совершили традиционный "удар ниже пояса" на тему monitor()/demonitor() — ведь это еще пара злобных поглотителей времени (и да, конечно, уже тоже давно не относится к реальности, примерно с R21, где было добавлено то самое, о чем вы просили — "две очереди", даже, скажем так три, но не для пользователя).

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


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


Вот именно это меня особенно смущает, "подтверждение экспериментами". Нет бы просто прочитать код и разобраться. Как это сделали мы.
Re[5]: Дублирую вопрос.
От: SkyDance Земля  
Дата: 07.08.20 03:18
Оценка:
S>Ну вот индус спрашивает про rp\lb. Это что-то свое самописное или используете известные вещи типа nginx? Если известные, то что? Если не NDA.

не совсем понимаю вопрос. Что есть rp? lb — load balancing?
Re[17]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 07.08.20 03:43
Оценка:
Pzz>Ну да, делаешь асинхронные передачи по цепочке. Потом где-то сводишь результат. Обещанная при этом простота куда-то вдруг волшебным образом рассасывается

Это и есть простота.
Надо научиться думать асинхронно. Понять и принять это. Осознать, что именно так и работает наш мир. Мы, существа, actors, — просто посылаем сообщения. Наш мозг так работает. Он посылает сообщения. И он не блокируется в ожидании ответа, как это делает анти-паттерн "call".

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

Учили бы в школе функциональному подходу.
Учили бы асинхронному мышлению.
Учили бы разбираться в сути вещей... все было бы иначе.

Ладно, можно на этом закругляться. Все равно общение слегка бессмысленное. Мир идет по кругу, или по спирали, если смотреть сбоку, но суть от того не меняется. Все в итоге суета сует. Буду честным — сделать можно какой угодно софт, на какой угодно платформе, на любом языке.
Дело лишь в профессионализме тех, кто будет этим заниматься, и в свойствах полученной системы. У меня хватает примерно увидеть то, на что способны несколько талантливых людей. И увидеть то, как на место десятка нанимается сотня, с результатами куда более печальными.

Такова жизнь. Мы рождаемся, взрослеем, стареем, умираем.
И мы несем это в софт. Он тоже рождается, взрослеет, стареет, умирает. Порой долго и мучительно, см. КОБОЛ, порой с феерверками. Иногда оставляет восхитительное послевкусие, см. common lisp — я до сих пор считаю модель разработки CL куда более удобной, чем то, что происходит в С++, жаве и многом еще. Благодаря одному чертовски важному свойству, тому, что я зову instant signal, — когда сигнал от сделанного изменения виден немедленно. Это holy grail of development productivity. И он достижим на Erlang'е. Сложнее, но также и на Java, PHP, Python, еще языкам. На С++, хм, нуу... не знаю, может, стар я стал, но до того медленны нынче компиляторы, что не то что signal, а даже build, и тот не instant.
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.08.20 04:32
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>А вот интеграция с С уже есть, и очень даже хороша — не понимаю, как вы могли упустить NIF. Особенно сейчас, в dirty CPU NIF & dirty IO NIF, и всем вокруг этого.


99% работы продукта это манипуляция структурами данных.
Объём работы по переносу их на C через NIF был бы такой, что точно проще было бы "задвинуть" целиком C/C++.
The God is real, unless declared integer.
Re[12]: WA: 3 млн tcp соединений на одном сервере
От: Mystic Artifact  
Дата: 07.08.20 05:09
Оценка:
Здравствуйте, netch80, Вы писали:

N>Слово "синидиотически" не находится. Опечатка или что?


Там одна большая опечатка... и не только в орфографии но и по смыслу.

Имелось ввиду, что больше нравятся языки и платформы общего назначения, на которых строятся конкретные решения (аля библиотеки). Не вижу плохого в других подходах (а иногда вижу и плюсы), но узколобая душонка их не любит и требует сделки с дьяволом.
Re[6]: Дублирую вопрос.
От: Sharov Россия  
Дата: 07.08.20 06:44
Оценка:
Здравствуйте, SkyDance, Вы писали:

S>>Ну вот индус спрашивает про rp\lb. Это что-то свое самописное или используете известные вещи типа nginx? Если известные, то что? Если не NDA.


SD>не совсем понимаю вопрос. Что есть rp?


reverse proxy

SD>lb — load balancing?


Да.
Кодом людям нужно помогать!
Re[13]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.08.20 10:46
Оценка:
Здравствуйте, SkyDance, Вы писали:

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


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

SD>1. Почему у writer'а длинная очередь?

Потому что туда поступили сообщения из внутренней обработки, и их надо отправить. Терять нельзя.

SD>2. Почему selective receive optimisation не работает для их случая?


Потому что не подходит под тот единственный шаблон, на котором настаивали авторы этого костыля.

SD>3. Почему они вообще используют gen_tcp?

SD>Ибо если б нужна была, достаточно было бы просто перебраться на socket API, который выполнен в виде NIF и не страдает от указанных недостатков.

Гениально, Ватсон!

>> Module socket was introduced in OTP 22.0.


Спасибо, что снизошли до нас, простых смертных. А все предыдущие ~15+ лет нам что делать было?
Мы начинали на R11, кажется.

N>>1. Да, ребята молодцы, что для решения проблемы они полезли в обход аж двух слоёв стандартной библиотеки

SD>Думаю, здесь было бы куда более логичным описать проблему более предметно.

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

Это проблема и MQ-движков, и нашего мониторинга.

SD> И вместо "обхода двух слоев" добавить нужную фунцкиональность. Но для этого им бы сначала пришлось разобраться в существующей. А вот это всегда и для всех было проблемой. Что уж там, сколько лет я пытаюсь подвинуть процесс интервью в направлении "проверять как кандидат умеет _читать_ код", но воз, увы, стоит на месте — все так же требует _писать_ код (который писать не нужно).


Опять "мышки, станьте ёжиками". У меня совершенно конкретный вопрос: как вы предлагаете писать, чтобы не получать квадратичную зависимость затрат CPU (хотя бы) от скорости потока, в условиях подобных неоптимизируемых синхронных вызовов (которые неизбежны хоть изредка)?

Хотя бы самую общую идею, как это сделать, но чтобы было реализуемо в пределах Erlang.

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


SD>За такие "архите-крутные" решения вынесу порицание. И вообще, к моему страху и ужасу, кроме Вирдинга да еще пары человек понмания какие ужасы несут нам ETS, почти ни у кого нет. Как тут не вспомнить Хаскел, где усилие было приложено в нужном направлении, и ETS попросту нет (в том виде как они есть в Эрланге).


Роскошно. Повторю вопрос: как вы будете решать иначе?
ETS был тут совсем не от хорошей жизни.

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


SD>Этот вариант я не понял. Что именно предлагается? Разделить на два процесса, где у одного очередь и flow control, а второй непосредственно пишет в сокет? Да, так делают, да, нормально работает, но да, костыль.


Мнэээ... вы хоть попробовали действительно детально расписать, как вы предполагаете реализацию этого?

Ну-ка попробую ("давно не брал я в руки шашек", но основы помню). Итак, процесс A получает входные сообщения, процесс B отправляет пусть штатным образом через gen_tcp:send (напоминаю, socket API нам ещё не доступен). Мы защищаемся от слишком длинной очереди процесса B, передавая эту обязанность на A.

Очевидно, что если B передаёт каким-то образом "а ну дай следующие данные на передачу", их надо собрать одним сообщением. Проблема в receive именно в количестве сообщений, а если я все передаваемые пакеты набью в одно, оно будет тяжёлым (объём данных никуда не девается), но одним. Потом процесс будет разбирать его и отправлять по кусочкам.
И чтобы не ожидать синхронизации с A, B всегда просит запас на сколько-то сообщений, если есть. Он передаёт в сторону A сообщения типа "у меня сейчас <N готовых на отправку, давай следующие" (XON) или "у меня сейчас >=N, копи у себя" (XOFF). (Пока не думаем, как он именно это передаёт в A. Можно рассматривать на грубых мерах уровня XON/XOFF, а не более тонких типа "скинь мне ещё 200 сообщений", покамест это неважно.)
Теперь: B должен же как-то реагировать на внешний мир, пока это происходит? Значит, надо разбирать поступившее относительно мелкими порциями, давая в промежутках управляющей системе что-то сделать. Может, она пошлёт стандартное OTP сообщение "расскажи, чем ты занят" (не помню, как выглядит), может, скажет проапгрейдиться, а может, скажет потухнуть. Значит, один раз на K сообщений надо отдать управление основному циклу (мы ж считаем, что он не самопальный? значит, берём gen_server, вряд ли что-то иное). А себе тогда надо послать сообщение типа "работай дальше".

Вроде с B утвердили. В нормальной обстановке у него безумной очереди нет: в произвольный момент там будут только какие-то из набора: 1) порция данных от A, <=1 сообщение; 2) самому себе про про продолжение разбора, <=1 сообщение; 3) какое-то разумное количество '$call', если спрашивают; 4) что-то управляющее от системы, <=1 сообщение.

Теперь переходим к A. Он накапливает входную очередь в своё состояние и сбрасывает его по заказу от B. Теперь пусть последний сигнал от B — "XOFF, копи у себя". В очереди опять ~20000 сообщений, источники не могут группировать. B передаёт A: XON. Теперь этот XON становится в хвост этих 20000 сообщений... B давно всё отправил и ждёт нового поступления, а A накапливает сообщения, раздуваясь, хотя давно мог бы скинуть порцию для B.

Вот это как раз тот случай, когда мы применили ETS, что вам так не нравится. В нём B выставлял этот флажок XON/XOFF, а A в обработке своего handle_cast (или handle_info, не помню) раз на 100 отработанных сообщений проверял его и смотрел, может он отправлять на B. Некошерно, зато мгновенно.

Итак, оно типа работает (хотя и потребовало заметного усложнения обоих процессов). Теперь: у этой системы есть свой мониторинг мониторинга. Каждый процесс должен отвечать подробностями своего состояния. Делаем это на сообщениях? Опять, пока "покажи личико" стоит в хвосте очереди, A прорабатывает свой входной набор.

Да, мы это обошли — и снова через ваш нелюбимый ETS! В приложении процесс listener отрабатывает длинный вход и рапортует своё состояние через ETS процессу manager, а заодно проверяя там — опять же каждые пусть 100 сообщений, или по таймеру — запросы от manager по ETS. А manager не получает длинную очередь, и отрабатывает все управляющие команды. И так в каждом приложении.

А теперь как это было бы на более разумно спроектированном средстве: никаких множественных процессов, никаких сложных буферизаций, никаких нечестных каналов мгновенного взаимодействия. Просто: пусть у нас 3 очереди. 0 — входной поток (cast + info), 1 — синхронные запросы (call + служебные OTP), 2 — ответы на наши синхронные запросы. Даже если receive читает, пусть по шаблону, в порядке приоритета: 2, 1, 0 (но пока копается в 0, всё равно реагирует на поступление в очередь 2) — то всё решено, реакция своевременная и адекватная, поведение устойчивое и линейное, и одного процесса хватает с головой. Ещё лучше, конечно, ограничить, что ответы на call читаются только из 2, но это следующий шаг.

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

Ну теперь хочу послушать ваши предложения. Только в технической конкретике, иначе спор неравный, и без фокусов типа socket API, который недоступен (машины времени, простите, нет), по уровню 2010 года (когда вопрос про очереди уже был поднят и получил отказ), максимум 2012. Потом можно перейти к 2020, вдруг что изменилось.

SD> Но вообще эти страдания не совсем логичны. Впрочем, хорошо уже то, что у них таки есть разделение на r/w. Потому как куда более суровы страдания тех, кто в одном процессе все это делает, а потом жалуется, что gen_tcp:send() не возвращает управление пока данные не уйдут хотя бы в kernel send buffer.


Это как раз более понятная проблема и решаемая: 1) просто распараллелить отправщиков (считаем, TCP соединения разные), 2) задержка линейна, а не квадратична.

SD>Пожалуй, что "иное" — просто используйте socket. Если его нет в вашей версии, — портируйте. Вполне нормальная практика backport'ить что-то из старших версий, скажем, мы в древние времена бэкпортили crypto, чтобы работало с аппаратным ускорением (через УМЗ), а не как в R16B.


Этой "старшей версии" ещё в 2011 просто нет, бэкпортить нечего. Надо писать самому. Лезть на сишный уровень в сложный чужой код...
Понимаете, почему я во втором проекте всё это выбросил, и просто перегнал на другой язык? И взлетело за 3 дня.

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

SD>Может, в этом причина недовольства?

Не-а

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

SD>Это же невозможно по определению. Или вы должны быть overprovisioned, чтобы соблюдать гарантии, или должна быть load shedding логика для защиты от перегрузки, или — backpressure.
SD>"Все уже украдено до нас": https://ferd.ca/handling-overload.html

И снова вы не хотите читать, что вам пишут.
У нас не было проблемы переполнения именно такого рода, как тут пишут, не было причины выставлять какие-то произвольные лимиты на основании представления, что это предел, и всё такое.
Если бы система адекватно (то есть с зависимостью не выше линейной) реагировала на нагрузку, пусть там ждёт 100000, 1000000 сообщений — всё пофиг; мы их просто обрабатываем.
Да, это именно что overprovisioned, и в данной ситуации это намеренно. Пусть каждый узел будет нагружен даже в самом тяжёлом случае на 50%, на 30% — всё отлично, нас это устроило бы, задача не просто допускает такой overprovisioning, она косвенно это требует.

Но квадратичность зависимости от текущей длины очереди:
1. Не даёт возможность создать никакого запаса нагрузки.
2. Не допускает устойчивого поведения: в отличие от линейной реакции, где любой локальный перекос просто чуть удлиняет очереди и спокойно разгребается вслед — тут подскок приводит к тому, что времени разгребать уже нет, надо дропать без обработки или дохнуть.

N>>2) Если ему хоть иногда надо делать синхронные вызовы (gen_server:call) и соответственно сразу ждать отвёт — всё, суши вёсла


SD>Хаха, как знакомо, все с тем же Вирдингом общались на тему "кто же это придумал gen_server:call и какие кары ждут его в аду"

SD>Все правильно: как только нарушается стройная концепция ("процессы обмениваются сообщениями") и приходит императивный девелопер "нам нужно сделать RPC", как все сразу начинает работать не так, как задумано. Embrace concurrency, adopd asynchronicity, и так далее. Пока это не случится, будут все те же одинаковые проблемы с блокировкой процесса там, где не следует.

Ну вот именно что "всё правильно", только другое "всё": в ад должны пойти те, кто уже более 10 лет отказывают в простых дешёвых надёжных мерах решить проблему, ссылаясь на "как задумано".

И от синхронных вызовов отказаться как-то нереально. Хотя сократить их долю, да, можно.

N>>: из накопления входной очереди выше 10-20K сообщений он не способен уже выйти. Граница неточная, но, похоже, связана с размером кэша процессора.

SD>Прочитав еще пару комментариев ниже, и увидев, как другие участники восхищаются скоростью постановки диагноза, просто обязан прокомментировать. Во-первых, отослать к моему выступлению на прошлой code MESH, — как раз на тему "in god we trust, all others must bring data".

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

SD>Во-вторых, конечно же, у меня есть куда более простое, логичное и понятное объяснение, почему это происходит, ибо — я в теме разобрался чуть менее поверхностно. Допускаю, что у вас на тот момент не было никого, что мог бы просто воспользоваться gdb/perf/fprof/eprof/cprof, и понять, что дело не в кэше, а в том, как работает GC. Но да, что занятно, Rick Reed в свое время тоже наступил на сию граблю, но на то он и Rick Reed, чтобы разобраться. Я тогда еще и рядом не стоял. Могу лишь гордится тем, что учился у таких людей.


Мне на самом деле нет принципиальной разницы тут: кэш, GC или стая ворон. Это только дополнительный триггер, который приводил к более резкой границе срабатывания. Мы могли бы выдержать торможение и в 10 раз на переходе границы, но — фиксированное. Вот пусть ровно в 12.4 раза, но не больше.
Реально же измерения на тесте типа "заполняем входную очередь до заданного количества, потом начинаем разбирать" показали, что время растёт с характеристикой, близкой к квадрату количества сообщений.

SD>Так вот, возвращаясь к вопросу, — возможно в древних версиях, которыми вы пользовались, еще не было off-heap message queues, поэтому и случалась death spiral, когда с ростом количества сообщений в очереди GC становился все более и более дорогим, что вело к еще более быстрому наполнению очереди, что вело к еще более медленному GC, и так далее.


Там есть функции пощупать, чем занят сейчас процесс (без вопроса ему самому) — собственно, process_info() с соответствующими параметрами. Если бы вы были правы, там оно показывало бы GC. Но оно не показывало GC. Так что этот фактор если и влиял, то далеко не главным.

(Ну или показометр врал. Кто знает... но тогда это опять же проблема Erlang.)

N>> Временное переполнение, безвредное в других условиях, становится фатальным (надо только рубить процесс).

SD>Кто хочет, ищет причины. Кто хочет — решения. Мы нашли решения: во-первых, добавили патч для flush message queue, во-вторых, допилили GC для более удачной работы с длинными очередями, в-третьих, когда доделали off-heap mq, просто перелезли на них.

Вот именно, что ищет решения. Нашим решением для второго проекта был уход от Erlang. И не пожалели.

N>>Нет. Backpressure вообще недопустим <...> Остановить агентов мы были в состоянии. Реально они сами останавливались, не получив команды "даю разрешение на 5 отчётов".


SD>Или я чего-то не понимаю, или... это как раз и есть backpressure (в самом простом и классическом варианте, т.е. credit control. Странно, что это вы считаете "хаком". Это вполне легальный, и один из самых простых в реализации, способов. В конце концов, Ulf Wiger еще в 2010 (на деле, в 2005, но опубликовали позже) с теоретической стороны это рассмотрел. Позже, в том же Elixir, Jose Valim сделал аналогичный GenStage. Да что там, реализаций немало.


Супер статья, да:

>> For lack of a better analysis,we called them “monster waves” (see Figure 5) although we do notyet know exactly what causes it.


Ну хоть по вашему мнению, вы победили эти monster waves, или нет? )

Ну и, как уже сказал, она не в тему. Управление потоком для нас не было проблемой, проблема в том, когда его принципиально недостаточно для решения проблемы.

SD>И. Справедливости ради, это же и есть holy grail. SEDA, и все эти akka streams, и все это reactive programming, — все аналогичные data flow pipelines, все это отнюдь не ново! Все уже было, и whitepapers более чем навалом, и реализаций. Если уж вы работали над "Ломоносовым", это ведь в МГУ, как могло так получиться, что вы не были знакомы со всеми работами в этом направлении? Уж на что моя должность прикладного характера, но даже я с ними знаком. Ибо без такого знакомства я был бы обречен написать очередной worker pool.


А кто вам сказал, что не были знакомы? Мне сейчас не доступна история внутренних событий тех времён, но раскопки шли, и какие-то работы рассматривались. Имя Wigerʼа я помню с тех времён.
Тем не менее, их не хватило.

Поставьте сами эксперимент такого же рода. Какое-то современное железо (не менее Corei3 или Ryzen3, если x86), незагруженный узел. Сделайте процесс, который принимает поток сообщений с отдельного узла (какая-нибудь структурка в кортеже байт на 200) и обрабатывает их с участием синхронного вызова (пусть в трёх вариантах: сначала типа оптимизированного gen_server:call, потом gen_tcp:send и наконец чего-то своего) хотя бы один раз на 100 сообщений. И ещё один, который периодически мониторит этот процесс вызовами, на которые тот должен в handle_call отвечать своим состоянием. И начните его грузить, равномерным потоком, под потолок 50% нагрузочной способности на текущем железе. Потом сделайте внешнее вмешательство: просто заставьте заснуть процесс на 2-3 секунды (годится call с сообщением, которое зовёт sleep)... а потом смотрите, как он выкарабкивается из этой ситуации.
Потом возьмите от того пикового ламинарного потока — 95%, 90%, 85%... и каждый раз приостанавливайте процесс и смотрите, восстановится или нет.
Критерий восстановления: если остановить входной поток, через 6 секунд (дадим запас, хотя 4 секунд должно было хватить) очередь процесса исчерпывается полностью.
Потом повторить на R12-R13 и на железе того времени (пусть будут Nehalem всех видов).
Основная цифра, которая меня интересует по результату: пусть RL — пиковый рейт для устойчивого ламинарного состояния (сообщений в секунду). Пусть RX — пиковый рейт для режима "пригрузив, остановить процесс на 2 секунды, запустить снова, и чтобы он восстановился после этого" (повторюсь, восстановление — это когда через 4-6 секунд все входные сообщения проработаны, и процесс спит в ожидании). Чему равно RL/RX, и как она зависит от железа, версии Erlang и варианта синхронного вызова?
И если RL/RX более 2 (дадим запас, хотя я бы смотрел на случай >1.4), что именно тормозит восстановление?

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

N>>Общением с кем-то из core team занимались другие коллеги. Успеха не добились.

SD>Что такое core team?

SD>OTP team, у них нет "core", есть VM, есть PS, и есть еще один человек сбоку.

Core team — это общее понятие. Мне пофиг, как оно называется в конкретном случае — core team, cardinal crew, steering committee или как-то ещё.

SD>И так уже лет... пятнадцать. И вот это, да, проблема, слишком мало драйверов роста.


Ну если вы будете вместо того, чтобы помогать пусть даже на среднего качества разработке добиваться успехов, требовать высочайшего качества подготовки программистов/архитекторов/etc. — не удивляйтесь, что у вас "слишком мало драйверов роста", их больше и не будет — наоборот, будет только меньше.

SD>Именно в том и дело, что в Java/C++ и прочих "закатах солнца вручную" очень легко выстрелить себе в ногу. Вот в самом деле, персональная нить на клиента — это же, черт подери, удобно, и очень правильно! И, собственно, так и должно быть (более того, должно быть две нити на клиента, одна на вход, другая на выход, in/out pipes). Потому что это точно воспроизводит всю коммуникационную специфику. Неспроста же это решение возникло в телекоме. Обмен сообщениями. Просто, понятно, гениально.


Спасибо, посмеялся.

N>>Но это надо смотреть реализацию в деталях: что делается и как.


SD>Как обычно. Дьявол в деталях. И в уровне разработчиков. То, что десяток профессионалов сделют на Эрланге, может быть недоступно сотне "обычных порошков". Для меня, кстати, это совсем недавнее открытие. Раньше я как-то и представить не мог, что один разработчик может быть на порядок более производителен, чем другой. То есть, раньше, в моем понимании, команда из пятерых человек по определению сделает больше, чем один гений. Вынужден признать, что глубоко заблуждался.


У меня такого заблуждения никогда не было. Но вы вместо обсуждения технических деталей опять впали в философию, где святой дух гения помогает Эрлангу, но не помогает Джаве.
The God is real, unless declared integer.
Re[15]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.08.20 10:53
Оценка:
Здравствуйте, SkyDance, Вы писали:

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

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

Ну и где этот "правильный вариант", если сейчас без gen_call OTP в принципе не будет работать — слишком много на него завязано?
Может, вместо того, чтобы его ругать, просто набраться сил и признаться, что синхронные вызовы неизбежны и надо с ними справляться?

N>>Это оптимизация на частный случай, и она сделана, кажется, в 14-м релизе


SD>А сейчас на дворе 23.

SD>И оптимизации сделаны чуть иначе, с чуть большими возможностями. Но, да, только под конкретный шаблон (тот самый gen_server:call).

Вот в этом и загвоздка.

SD>Странно еще что вы не совершили традиционный "удар ниже пояса" на тему monitor()/demonitor() — ведь это еще пара злобных поглотителей времени (и да, конечно, уже тоже давно не относится к реальности, примерно с R21, где было добавлено то самое, о чем вы просили — "две очереди", даже, скажем так три, но не для пользователя).


Потому что monitor/demonitor был ближе к константной затрате на каждый вызов (хотя при перегруженных линках и он мог давать сверхлинейные затраты по времени, но этого я уже тупо не помню).

SD>Вот именно это меня особенно смущает, "подтверждение экспериментами". Нет бы просто прочитать код и разобраться. Как это сделали мы.


Как чтение кода давало бы понять, упёрлись в кэширование или нет? Не заговаривайтесь.
The God is real, unless declared integer.
Re[18]: WA: 3 млн tcp соединений на одном сервере
От: Pzz Россия https://github.com/alexpevzner
Дата: 07.08.20 12:03
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>Это и есть простота.

SD>Надо научиться думать асинхронно. Понять и принять это. Осознать, что именно так и работает наш мир. Мы, существа, actors, — просто посылаем сообщения. Наш мозг так работает. Он посылает сообщения. И он не блокируется в ожидании ответа, как это делает анти-паттерн "call".

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

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

И да, это стоит потери производительности по сравнению с "голым железом". Мне, как человеку, прошедшему путь от самодельного компьютера на 8080 (и это был не Радио-86РК с интерпретатором бейсика, шестнадцетиричные коды которого публиковались в журнале) до того, что мы имеем сейчас, близка и понятна боль от потерянных на высокоуровневые абстракции тактов процессора и килобайтов памяти. Но тем не менее, если мы не готовы переступить через эту боль, то мы потеряем контроль над собственным софтварием, уж больно сложным он станет, не помещающимся в голове.

В общем, я считаю, что ты изнасиловал себя. Вероятно, ты достаточно талантлив, и в этом изнасиловании себя изрядно преуспел. Но это не отменяет факта изнасилования

Подход Go, с его идеей, "заводите поток на каждый чих, компилятор разберется" мне представляется более человечным. Эти ребята, конечно, врут, что потоки Go ничего не стоят. Между прочим, они уже один раз проделывали такой трюк, когда в 60-е — 70-е считалось, что настоящие операционные системы пишут на настоящем языке программирования, на ассемблере, а они написали свой UNIX на C и ходили, всем рассказывали, что ихний Сишный компилятор почти и не уступает ассемблеру — и тоже врали, он уступал по скорости раза в два, а по памяти даже и не знаю. Но результат нам известен, сейчас все операционные системы пишутся на Си.

Go, кстати, чертовски сложный под капотом, видно, что настоящий хакер старой школы писал. Но наружу эта сложность практически не вылазит.

SD>Учили бы асинхронному мышлению.


Этому в цирковом училище учат, на отделении акробатики

SD>Учили бы разбираться в сути вещей... все было бы иначе.


А этому — в ПТУ

SD>Ладно, можно на этом закругляться. Все равно общение слегка бессмысленное. Мир идет по кругу, или по спирали, если смотреть сбоку, но суть от того не меняется. Все в итоге суета сует. Буду честным — сделать можно какой угодно софт, на какой угодно платформе, на любом языке.


Ну ОК, разговор все равно состоялся приятный.

SD>Дело лишь в профессионализме тех, кто будет этим заниматься, и в свойствах полученной системы. У меня хватает примерно увидеть то, на что способны несколько талантливых людей. И увидеть то, как на место десятка нанимается сотня, с результатами куда более печальными.


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

SD>И мы несем это в софт. Он тоже рождается, взрослеет, стареет, умирает. Порой долго и мучительно, см. КОБОЛ, порой с феерверками. Иногда оставляет восхитительное послевкусие, см. common lisp — я до сих пор считаю модель разработки CL куда более удобной, чем то, что происходит в С++, жаве и многом еще. Благодаря одному чертовски важному свойству, тому, что я зову instant signal, — когда сигнал от сделанного изменения виден немедленно. Это holy grail of development productivity. И он достижим на Erlang'е. Сложнее, но также и на Java, PHP, Python, еще языкам. На С++, хм, нуу... не знаю, может, стар я стал, но до того медленны нынче компиляторы, что не то что signal, а даже build, и тот не instant.


Этого я просто не понял, объясни, что ты имел ввиду. Про instant signal, а не про КОБОЛ.
Re[18]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 07.08.20 13:02
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>Это и есть простота.

SD>Надо научиться думать асинхронно. Понять и принять это. Осознать, что именно так и работает наш мир. Мы, существа, actors, — просто посылаем сообщения. Наш мозг так работает. Он посылает сообщения. И он не блокируется в ожидании ответа, как это делает анти-паттерн "call".

Если call — антипаттерн, то процесс — антипаттерн втройне. У нас нет отдельных процессов (а то, что есть — значительно сложнее). Перестаньте плодить процессы на каждый чих — это будет честно.

Но с каких это пор устройство компьютера должно следовать устройству мозга?

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


Просто потому, что оно проще.
Точно так же, как в математике стараются всё свести к линейным уравнениям, потому что нелинейные мы не умеем решать (а где решаем — сводим к линейным).
А проще — значит, подъёмнее, меньше требуется и уровня, и ресурсов. И это хорошо. Сложным надо делать только то, где это неизбежно.

SD>Учили бы в школе функциональному подходу.

SD>Учили бы асинхронному мышлению.
SD>Учили бы разбираться в сути вещей... все было бы иначе.

От "асинхронного мышления" до "разбираться в сути вещей" — "дистанции огромного размера".
А "асинхронное мышление" вон сейчас у каждого первого фронтэндера, потому что асинхронный JS асинхронно грузит асинхронные скрипты.

SD>Такова жизнь. Мы рождаемся, взрослеем, стареем, умираем.

SD>И мы несем это в софт. Он тоже рождается, взрослеет, стареет, умирает. Порой долго и мучительно, см. КОБОЛ, порой с феерверками. Иногда оставляет восхитительное послевкусие, см. common lisp — я до сих пор считаю модель разработки CL куда более удобной, чем то, что происходит в С++, жаве и многом еще. Благодаря одному чертовски важному свойству, тому, что я зову instant signal, — когда сигнал от сделанного изменения виден немедленно. Это holy grail of development productivity. И он достижим на Erlang'е. Сложнее, но также и на Java, PHP, Python, еще языкам. На С++, хм, нуу... не знаю, может, стар я стал, но до того медленны нынче компиляторы, что не то что signal, а даже build, и тот не instant.

Плюсовик сказал бы, что тот, кто залагается на немедленный результат, не научен думать и предсказывать результаты своих действий
И я частично согласен. REPL и аналоги — плодят лень. Полноценные данные собираются за такие периоды, на которых та компиляция это просто ничто.
Но это уже совсем в оффтопик.
The God is real, unless declared integer.
Re[14]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 08.08.20 00:24
Оценка:
N>Потому что туда поступили сообщения из внутренней обработки, и их надо отправить. Терять нельзя.

Напоминает проблему reliable exactly once delivery в distributed environment, а также все ту же handling overload статью.
Что значит "терять нельзя"? В случае перегрузки либо load shedding, либо backpressure, третьего не дано (или по крайней мере мне неизвестно).

N>Спасибо, что снизошли до нас, простых смертных. А все предыдущие ~15+ лет нам что делать было?


Решать конкретную проблему, попутно улучшая инструменты. Заодно — учиться.

N>Опять "мышки, станьте ёжиками". У меня совершенно конкретный вопрос: как вы предлагаете писать, чтобы не получать квадратичную зависимость затрат CPU (хотя бы) от скорости потока, в условиях подобных неоптимизируемых синхронных вызовов (которые неизбежны хоть изредка)?


Как обычно, есть варианты:
а) научиться мыслить асинхронно, и более не вспоминать про неизбежность
б) внести необходимые изменения в инструмент, сделав его доступным всем (contribute to open source)
в) научиться работать с тем, что есть

N>Роскошно. Повторю вопрос: как вы будете решать иначе?


Я уже объяснил. Можно было написать NIF-based socket, можно было реализовать backpressure, можно было разобраться и поднастроить GC. Можно было подумать про архитектуру и ее огранчиения: почему у вас строго одна выходная "труба"? Ведь это single point of failure. Это по определению ненадежно.

N>Ну-ка попробую ("давно не брал я в руки шашек", но основы помню). Итак, процесс A получает входные сообщения, процесс B отправляет пусть штатным образом через gen_tcp:send (напоминаю, socket API нам ещё не доступен). Мы защищаемся от слишком длинной очереди процесса B, передавая эту обязанность на A.


N>Очевидно, что если B передаёт каким-то образом "а ну дай следующие данные на передачу", их надо собрать одним сообщением.


Пока логично. Процесс "А" просто выгребает приходящее и складывает в iolist, или, как вариант, накапливает длинный binary (unbounded, судя по условию вашей задачи, когда "ничего терять нельзя").

N> Проблема в receive именно в количестве сообщений, а если я все передаваемые пакеты набью в одно, оно будет тяжёлым (объём данных никуда не девается), но одним. Потом процесс будет разбирать его и отправлять по кусочкам.


На этом месте следовало бы остановиться и посмотреть, как именно сделан message passing для тяжелых сообщений (точнее, binaries внутри). Само сообщение будет крошечным, и будет содержать только ref-counter pointer на binary (который лежит вообще в отдельном аллокаторе).
Иными словами, процесс "А" является ровно тем, чего вы от него и хотите — буфером. Все, что он делает, это выгребает приходящие сообщения и сериализует в большой binary. Когда процесс "В", который вызывает (потенциально блокирующийся) вызов gen_tcp:send готов что-то еще отправить, он запрашивает у "А" все, что тот успел накопить.

Позвольте мне пропустить дальнейшее описание рукопашного flow control protocol, ибо сама необходимость водружать столь сложный механизм была основна на заведомо неверном предположении. Ох неспроста "The Art of Challenging Assumptions" по статистике Whova App набрал максимум посещаемости из всех выступлений на той конференции

N>Вот это как раз тот случай, когда мы применили ETS, что вам так не нравится.


Ну, в моей практике встречались и еще более странные применения ETS. Равно как и еще более необычные side channels — скажем, вместо ETS можно было бы завести отдельный процесс (условно назовем его locker) который бы отвечал на вопрос "уже можно или еще нет". Способов организвать flow control — не счесть. И не только на Эрланге, на Java/C++/Python есть ничуть не меньше разных забавных конструкций на эту тему. Скажем, проверять глобальные флажки. А что, отличный вопрос для собеседования — поговорить о семантике volatile переменных
В общем, можно построить очень много ненужных велосипедов, если с самого начала не разобраться в задаче как следует.

Но. Хочу отдать должное, даже в самых простых решениях вроде этого самого binary buffer можно очень легко сделать ошибку. Вот пример. Прям один-в-один ваш случай, включая gen_tcp:send, и middleman-process. Неспроста я про TLS и ужасы говорил


N>Теперь: у этой системы есть свой мониторинг мониторинга.


Каждый такой пример "системы мониторинга" зачастую следствие неумения организовать supervision tree. Эта тема мне уже очень набила оскомину. Более двух лет я и лекции читаю, и мастер-классы провожу, и дизайн ревью, и code review, но, видимо, сказывается отсутствие этой темы в фундаментальном образовании программистов. Корректная организация supervision порой требует познаний в архитектуре. Выделить failure domains, договориться об SLA, о том, какие ошибки считать transient, какие permanent, и на каком периоде времени/частоте — этому всему нужно учиться. Ни в школе, ни в курсев "девелопер на РНР за 21 день" про это не рассказывают. И, кстати, зря — тема не такая и сложная, просто требует развернуть мозги, чтобы те заработали в нужном направлении. Тогда многое щелкнет и станет ясно, как именно (и, главное — ДЛЯ ЧЕГО) нужно организовать мониторинг.

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

N>Просто: пусть у нас 3 очереди


Нет, это не просто. Это как раз сложно. Просто — это когда у вас 3 процесса, и у каждого своя очередь.

N>И, что крайне важно, это всё не помешало бы всему остальному, что вы тут пишете про "правильный дизайн".


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

N>Понимаете, почему я во втором проекте всё это выбросил, и просто перегнал на другой язык? И взлетело за 3 дня.


Понимаю, конечно. Я ровно про то и писал в стартовом сообщений этого суб-треда. Кривая обучения нелинейна — вы научились базовому синтаксису, а потом ударились о резкий рост сложности концепций. Повторяю, вы не одиноки — это действительно cliff, на который, когда заберешься, начинаешь понимать, _ПОЧЕМУ_ система получилась столь стройной и красивой.

Есть простая аналогия. Лопата и экскаватор. Кто-то с самого начала сел в экскаватор, и оказалось очень удобно в нем сидеть! Но совершенно непонятно, как этим ковшом копать. Тяжелый, неудобный. В общем, потыркаться, а потом взять лопату и за три дня выкопать канаву. Это явно быстрее, чем месяц осваивать экскаватор.
Учиться в целом очень сложная задача. Мало кто в состоянии. Это надо иметь к тому склонность.

N>И от синхронных вызовов отказаться как-то нереально. Хотя сократить их долю, да, можно.


Представляете, что было бы, если бы ваш мозг мог синхронно зависнуть, ожидая ack'а от сердечной мышцы?

N>Там есть функции пощупать, чем занят сейчас процесс (без вопроса ему самому) — собственно, process_info() с соответствующими параметрами. Если бы вы были правы, там оно показывало бы GC. Но оно не показывало GC. Так что этот фактор если и влиял, то далеко не главным.


Куда именно выс смотрели? Что именно показывали erlang:system_monitor(long_gc) ?

N>Вот именно, что ищет решения. Нашим решением для второго проекта был уход от Erlang. И не пожалели.


Очень разумный подход. Если задача в том, чтобы "быстрее сделать", выбирать надо тот инструмент, в котором разбираешься лучше всего. А если таких инструментов много, то — тот, который лучше подходит к предметной области.
Иными словами, если у вас есть программист на С++, и нужно сделать что-то небольшое и быстро, заставлять его учить Эрланг не было бы разумным подходом. Вы попытались, не осилили, вернулись к знакомым инструментам. По мне так, вполне правильный процесс, fail fast, fail early.

N>А кто вам сказал, что не были знакомы?


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

N>Поставьте сами эксперимент такого же рода.


Вы описали один из test cases для off-heap message queue. В 2010 ее не было (появилась в OTP 19, то есть 5 лет назад).

N>Потом повторить на R12-R13 и на железе того времени (пусть будут Nehalem всех видов).


Нет смысла, я и так знаю, что произойдет (gc death spiral, можно найти слайды от Rick Reed'a где про это вкратце рассказывается).

Поймите важность root cause analysis. Кстати, да, тоже одна из тем, кажется, в 2019 на code BEAM SF я рассказывал про troubleshooting process и RCA. Не следует делать поспешных выводов на тему "ограничено размером кэша" и т.п.. Следует разобраться в проблеме — прочитав source code, например. И тогда уже оперировать знанием, а не ощущениями.

N>Core team — это общее понятие. Мне пофиг, как оно называется в конкретном случае — core team, cardinal crew, steering committee или как-то ещё.


Нет таких "общих понятий". И не было.

N>Ну если вы будете вместо того, чтобы помогать пусть даже на среднего качества разработке добиваться успехов, требовать высочайшего качества подготовки программистов/архитекторов/etc. — не удивляйтесь, что у вас "слишком мало драйверов роста", их больше и не будет — наоборот, будет только меньше.


К делу не относится, но здесь мне хочется поддержать Pzz,

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


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


Это ваши личные домыслы. Я лишь утверждаю, что вне зависимости от языка или парадигмы, разработчик, который в состоянии challenge assumptions, который может провести root cause analysis, а затем решить проблему, на порядок более производителен "среднего качества разработчика".

Отдельный котел в аду хотелось бы приготовить для тех, кто решает проблему наворачиванием очередного слоя поверх существующих. Причем слои почти всегда leaky, без соответствующей модели, и почти никогда не в состоянии выдержать property-based testing.
Re[7]: Дублирую вопрос.
От: SkyDance Земля  
Дата: 08.08.20 03:45
Оценка: 15 (1)
S>>>Ну вот индус спрашивает про rp\lb. Это что-то свое самописное или используете известные вещи типа nginx? Если известные, то что? Если не NDA.
S>reverse proxy

До 2019 были самые простые решения, и самые надежные. Никаких rp/lb. Эрланг напрямую торчал в Интернет, банальнейшим TCP socket. Весь "load balancing" делался в DNS.

Сейчас все работает через инфраструктуру Facebook. Там не используется nginx, и вообще все свое. Рассказать не могу, извините. То, о чем можно рассказывать, уже есть в интернете, ключевые слова "facebook software load balancer L4".
Re[19]: WA: 3 млн tcp соединений на одном сервере
От: SkyDance Земля  
Дата: 08.08.20 04:12
Оценка:
Pzz>Я бы поспорил. Я думаю, нам для того и нужны хитроумные инструменты, потому что наши мозги по-другому думают, чем компьютеру было бы удобно.

Разница между мозгом и компьютером в том, что мозг — гибкий.
Не у всех, конечно, а у тех, кто мозг тренировал быть гибким (см. flexible vs rigid thinking). Это хорошая тема для обсуждения Но опять ведь обвинят в уходе в философию. Конечно, все философия — до тех пор, пока не начинаешь решать реальную задачу, и работать над одной проблемой в составе команды.

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


Прекрасно сказано! Эрланг, кстати, один из примеров такого инструмента.
Но сложность в том, что к этому инструменту приходят люди, долгое время (как бы даже не всю жизнь) работавшие только с императивным подходом. И зачастую еще и с полным непониманием асинхронности мира и задач, которые требуется решить. И виноват тут не инструмент. могу рекомендовать выступление Simon Peyton Jones — про новую программу CS в британских школах. Вот это, "The revolution of computing in schools" — нашел запись здесь. То, что он делает, — если взлетит — может ощутимо изменить ландшафт софтостроения.

Pzz> Мне, как человеку, прошедшему путь от самодельного компьютера на 8080 (и это был не Радио-86РК с интерпретатором бейсика, шестнадцетиричные коды которого публиковались в журнале)


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

Не надо ограничивать искусственными горизонтами. Мысли шире. И глубже. Научись учиться.

Pzz>Go, кстати, чертовски сложный под капотом, видно, что настоящий хакер старой школы писал. Но наружу эта сложность практически не вылазит.


Да-да, это уже пол-эрланга, надо еще подождать, и будет полный.

Pzz>Ну ОК, разговор все равно состоялся приятный.




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


Вы только не говорите этого в какой-нибудь большой компании с глубокой иерархией. Да-да, Google, Apple, Facebook и т.п.. Нельзя вот так брать и резать правду-матку, или придется участвовать в обсуждениях про "токсичных девелоперов".

Pzz>Этого я просто не понял, объясни, что ты имел ввиду. Про instant signal, а не про КОБОЛ.


Попытаюсь в двух словах.
Суть в том, чтобы разработчик не раздражался по таким пустякам как бессмысленное ожидание.
1. Build (compile/assemble/link/...) должен быть мгновенным (200 мс и меньше). Иными словами, как только я закончил редактировать код/тест/конфиг, я не должен жать никаких кнопок, ждать 5 секунд пока взлетит компилятор, еще 10 секунд на разворачивание разных там докеров, инстанцирование чего-то еще, или запросов "а не компилировал ли кто-то где-то в интернете точно такой же код" (привет bazel).
2. Signal — подразумевается весь полезный сигнал от инструментария разработчика. То есть, lint, format, smoke tests (естественно, с test selection в соответствии с code coverage).
3. Интеграция инструментария (т.е. lint не отдельно где-то там, а прямо в IDE/vim/emacs).
4. Отсутствие любой необходимости (или полная прозрачность) "рестарта системы". Скажем, в том же эрланге, поддержка hot code load сделана по уму (а не как в java, где значительная часть попросту не работает).

И так далее. Все задачи должны выполняться за незначительное время. Чтобы потребность выпить чашечку чая возникало не потому, что "я запустил build", а потому, что чаю захотелось.
Не надо заставлять девелоперов ждать. И уж точно нельзя делать инструменты, которые заставляют человека уходить и менять контекст. Это софт пусть работает в асинхронхронном режиме. А вот процесс его разработки должен быть таким, чтобы имитировать самую что ни на есть синхронность.
Re[15]: WA: 3 млн tcp соединений на одном сервере
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.08.20 06:40
Оценка:
Здравствуйте, SkyDance, Вы писали:

N>>Потому что туда поступили сообщения из внутренней обработки, и их надо отправить. Терять нельзя.


SD>Напоминает проблему reliable exactly once delivery в distributed environment, а также все ту же handling overload статью.

SD>Что значит "терять нельзя"? В случае перегрузки либо load shedding, либо backpressure, третьего не дано (или по крайней мере мне неизвестно).

Да, тут лучше уточнить. В случае нормальной перегрузки и нормальной реакции на неё — да, управление потоком через backpressure, и его, естественно, делали. В том и дело, что проблема в случае ненормальной реакции из-за свойств рантайма, когда любая реакция на перегрузку в точке её детекта будет заведомо опоздавшей. Это вы в данной дискуссии систематически игнорируете, заменяя абстрактными словами, которые сводятся к "у нас тут своя атмосфера" и "учиться, учиться и учиться", а также "вложите 100500 человеко-часов, это пойдёт всем на пользу" (на самом деле ещё фиг его знает, и очень вероятно, что нет).

N>>Роскошно. Повторю вопрос: как вы будете решать иначе?

SD>Я уже объяснил. Можно было написать NIF-based socket,

Объём работы. Проблема поддержки этого всего.

Вы, мысля масштаба WhatsApp и Facebook, не понимаете, что при маленькой команде (а она никогда не выходила за 10 человек, из которых собственно проблемы транспорта понимали максимум 3, а ведь есть и другие задачи) постановка в духе "написать NIF-based socket" означает серьёзное увеличение затрат на разработку, поддержку и сопровождение; кроме того, она означает, что инструмент не справился с теми задачами, для которых он и был, согласно рассказам авторов, рассчитан.

Так как сочетание NIF-сокета с остальным Erlang означает, кроме того, что этот сокет должен кто-то написать и поддерживать (ладно, я бы написал, у меня "экспертизы" хватает, а дальше кто этим займётся?), ещё и отладку бутерброда и Erlang+C (а то, что отладка будет нужна — к гадалке не ходи). Это проблема всех бутербродных построений, и выигрывают те средства, в которых они не нужны как минимум для 99% базовой функциональности (вспоминаем Java, C#, Python...)

SD> можно было реализовать backpressure, можно было разобраться и поднастроить GC. Можно было подумать про архитектуру и ее огранчиения: почему у вас строго одна выходная "труба"? Ведь это single point of failure. Это по определению ненадежно.


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

N>> Проблема в receive именно в количестве сообщений, а если я все передаваемые пакеты набью в одно, оно будет тяжёлым (объём данных никуда не девается), но одним. Потом процесс будет разбирать его и отправлять по кусочкам.


SD>На этом месте следовало бы остановиться и посмотреть, как именно сделан message passing для тяжелых сообщений (точнее, binaries внутри). Само сообщение будет крошечным, и будет содержать только ref-counter pointer на binary (который лежит вообще в отдельном аллокаторе).


Ага, то есть хорошо было бы ещё и в binary их перепаковывать, причём размера не меньше сколько-то (с какого размера там включается оптимизация)? И это на внутреннем взаимодействии (внутри одной ноды)? Вам не кажется, что это слишком большие требования для простой задачи?

SD>Позвольте мне пропустить дальнейшее описание рукопашного flow control protocol, ибо сама необходимость водружать столь сложный механизм была основна на заведомо неверном предположении. Ох неспроста "The Art of Challenging Assumptions" по статистике Whova App набрал максимум посещаемости из всех выступлений на той конференции


Я посмотрел, спасибо. Великолепный английский как для родного русского — завидую... остальное — или подробности Erlang-решений, или вода. Любой грамотный разработчик с опытом скажет то же самое, пусть и не столь красиво, но во всём этом нет ответа на главное: мы в принципе все свои действия основываем на предположениях на основании существующего опыта, и их подавляющее большинство на самом деле ничему не мешает, и менять их нереально и бессмысленно; но, после того, как надо просто выделить ресурсы на измерения и проверки того, что казалось очевидным (а ресурсы тут важны всегда, и сурово критичны — почти всегда) — остаётся определить, с чего именно начинать измерения и проверки, а это получается только с опытом в теме.
В сумме, доклад — красивый пиар вас лично и фирмы. Полагаю, что вы таки достигли поставленных для этого пиара целей.

И чем же тут было "заведомо неверное" предположение — вы не объяснили, так что ответа нет. Ответ в духе "вы предположили, что можно обойтись первыми приходящими в голову средствами и не подумать вызвать X, Y, Z, чёрта лысого, подключить библиотеку WWW243972" это не ответ, это издевательство.

N>>Вот это как раз тот случай, когда мы применили ETS, что вам так не нравится.


SD>Ну, в моей практике встречались и еще более странные применения ETS. Равно как и еще более необычные side channels — скажем, вместо ETS можно было бы завести отдельный процесс (условно назовем его locker) который бы отвечал на вопрос "уже можно или еще нет".


Дададад. "Отвечал". То есть шло бы обратно сообщение, которое вставало бы в конец очереди. Вы это серьёзно?

SD> Способов организвать flow control — не счесть. И не только на Эрланге, на Java/C++/Python есть ничуть не меньше разных забавных конструкций на эту тему. Скажем, проверять глобальные флажки. А что, отличный вопрос для собеседования — поговорить о семантике volatile переменных


И вы тут то ли намеренно ёрничаете, то ли явно не в курсе про volatile в многонитевом окружении?

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


SD>Но. Хочу отдать должное, даже в самых простых решениях вроде этого самого binary buffer можно очень легко сделать ошибку. Вот пример. Прям один-в-один ваш случай, включая gen_tcp:send, и middleman-process. Неспроста я про TLS и ужасы говорил


Перескажите словами, что происходит, если хотите понимания. Я-то ещё разберу происходящее за пару часов (TLS на Erlang никогда не заводил), но если кто ещё читает — то точно не поймёт.

N>>Теперь: у этой системы есть свой мониторинг мониторинга.


SD>Каждый такой пример "системы мониторинга" зачастую следствие неумения организовать supervision tree.


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

>> какие ошибки считать transient, какие permanent, и на каком периоде времени/частоте


?

Ню ню (tm)

Или опять ETS, который вы хотели бы устранить?

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


Я думаю, последние 20 лет вопрос "какие действия принимаются..." на основе счётчиков событий (банально, полученных/посланных сообщений по выбранной классификации, и всё такое) — просто не должен озвучиваться. Вопрос должен быть — делаются ли эти действия вообще и правильные ли они.

N>>Просто: пусть у нас 3 очереди

SD>Нет, это не просто. Это как раз сложно. Просто — это когда у вас 3 процесса, и у каждого своя очередь.

Докажите. Я объяснил, что именно достигается несколькими очередями и как оно стабилизирует работу системы. Теперь хочу послушать, каким образом вы этими 3 раздельными процессами добьётесь аналогичного результата. На всякий случай приведу ещё раз базовые условия, хотя бы в таком наборе:
1) Речь идёт об управлении конкретным процессом и его контроле через единственный, по вашим же правилам, разрешённый интерфейс в виде асинхронно поступающих сообщений. Канал через ETS не разрешаем.
2) Надо управлять этим процессом, включая регулирование параметров (оперативное! ждать секунды, пока он прочтёт сообщение, нельзя).
3) Увы, gen_call иногда (а может, и всегда) нужен из-за того, что на нём работает некоторый интерфейс, который мы менять не можем.

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

N>>И, что крайне важно, это всё не помешало бы всему остальному, что вы тут пишете про "правильный дизайн".


SD>Думаю, что ваша точка зрения не имеет достаточной научной базы.


О том, что не помешало бы? То есть у вас есть очень себе "challenging" предположение о том, что чем-то помешало бы? Хочу послушать предпосылки к этому предположению, это становится интересным А также научную базу, как от этого попортилось бы что-то

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


И снова от вас никакой конкретики, только "стройная модель" (стройность которой на самом деле ничуть не испортит введение нескольких очередей) и ссылка на какие-то посторонние случаи, про которые ничего не известно.

N>>И от синхронных вызовов отказаться как-то нереально. Хотя сократить их долю, да, можно.

SD>Представляете, что было бы, если бы ваш мозг мог синхронно зависнуть, ожидая ack'а от сердечной мышцы?

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

N>>Вот именно, что ищет решения. Нашим решением для второго проекта был уход от Erlang. И не пожалели.


SD>Очень разумный подход.

Если задача в том, чтобы "быстрее сделать", выбирать надо тот инструмент, в котором разбираешься лучше всего.

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

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

SD>Вы описали один из test cases для off-heap message queue. В 2010 ее не было (появилась в OTP 19, то есть 5 лет назад).


То есть пробовать не хотите? Спасибо, Ч.Т.Д.

SD>К делу не относится, но здесь мне хочется поддержать Pzz,

SD>

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


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

Ну и у меня, по своему опыту, далеко не такие мрачные выводы о качестве людей (по крайней мере программистов). Может, потому, что я никогда не работал в аутсорсе.

SD>Это ваши личные домыслы. Я лишь утверждаю, что вне зависимости от языка или парадигмы, разработчик, который в состоянии challenge assumptions, который может провести root cause analysis, а затем решить проблему, на порядок более производителен "среднего качества разработчика".


Ну вот пока вы считаете "средним качеством" тех, кто не может и даже не хочет... ok, ваше дело.
The God is real, unless declared integer.
Отредактировано 08.08.2020 7:03 netch80 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.