All streams
Search
Write a publication
Pull to refresh
1
0

Пользователь

Send message
Стоит. На нем все еще пилят вебсервера. Но, если это с нуля пописать годик-два, это одно. А если вы придете в проект где сервисы на ноде прошли через руки 10-20 человек, да поможет вам бог в поддержке этого чуда. Вы будете молиться на каждом деплое и станете верующим. Возможно даже уйдете в монастырь =)

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

Есть огромная разница между людьми которые пишут POC на JS и прыгают со стартапа в стартап и никогда не доходят до момента когда простенький POC вырос в гиганта и теперь кому-то с этим жить.
JS не перестает удивлять =)

[1,2,3] + [null,4,5,6]
'1,2,3,4,5,6'
Есть и плюсы. Легаси еще лет на 10 как минимум хватит что-бы поддерживать и переписывать на тайп скрипт или другие языки. А это рабочие места и зряплата Ж)

Когда проект, количество кода и разработчиков растет, с чистым JS работать невозможно. Но быстрый старт — это да… главное потом выжить.

А вы знаете что уже сегодня есть поколение разработчиков не видавших никогда колбэк хела уровней так на 10 со всякими вотерфолами? А потом еще обернутыми в промисы =))
Студенты хоть знают за этими картинками стоит ״Теория автоматов״? :)
Как-то не убедили без цифр. Ну хотя бы RPs, mem/cpu usage до и после.

  1. HTTP/2 не обязывает использовать gRPC
  2. Даже до HTTP/2 можно keep-alive попробовать
  3. Генерить типы для разных языков можно и со свагера


Единственное что подкупает это то, что сериализация должна быть быстрей. Мы же любим все быстрое Ж) Но и тут я не уверен что это правило работает для всех платформ. (https://medium.com/@onufrienkos/benchmarking-performance-grpc-vs-rest-on-node-js-bf766127f170)

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

Хотелось бы видеть реальную пользу :/
Понимать как работает движок полезно и интересно. Главное что бы человек понимал что конкретно этот пример является классическим premature optimization. Потому как я уверен что в продакшене вместо 1000^3 итераций:

for(var i = 0; i < 1000 * 1000 * 1000; i++)


даже если их будет 100, время потраченное на оптимизацию не окупится в ближайшие лет 10 =)
А еще бывает весело когда кто-то вешается на 404-ю ошибку что бы удалить у себя что-то связанное с объектом (ну потому что 404, значит объект был удален). А потом выясняется что что кто-то баг засунул в роутинг или настройки лоадбалансера/прокси или еще чего. Вот и получили блокер на ровном месте. Поэтому мы всегда проверяем респонс, даже когда это 404-я.
Мне кажется все к этому приходят. Более того, часто и одного уровня ошибки не хватает, потому что могут быть разные причины приводящие к одной ошибке, и нужно реагировать по разному.

Поэтому можно неделю потратить на обсуждение формата ошибок с коллегами споря о кошерности того или иного решения.

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

Например фейсбук использует

{
  "error": {
    "message": "Message describing the error", 
    "type": "OAuthException", 
    "code": 190,
    "error_subcode": 460,
    "error_user_title": "A title",
    "error_user_msg": "A message",
    "fbtrace_id": "EJplcsCHuLu"
  }
}


Twitter

{
  "errors": [
    {
      "parameter": "start_time",
      "details": "invalid date",
      "code": "INVALID_PARAMETER",
      "value": "",
      "message": "Expected time, got \"\" for start_time"
    }
  ],
  "request": {
    "params": {
      "account_id": "hkk5"
    }
  }
}


Ведь не от хорошей жизни они пришли к этому :)
Сенкс! Будем посмотреть.
А где можно почитать про эти подходы?
Спасибо! Загляну! а нет случайно таких же каналов для слака?
Конкурентные запросы упрутся в транзакции, кто первый запрос бросил — того и тапки.


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

Ну у нас такие доводы в пользу кафки (сейчас используем раббит и в основном без транзакций, потому что из еще не было в монге когда это разрабатывалось):

1. Пользователи насилуют систему как хотят и нам надоело иметь дело с параллельным процессингом или вообще обратным порядком команд. Например когда они делают Update -> Delete. На самом деле они могут делать много операций и нам это делает проблемы. С раббитом мы теряем order потому что скейлинг.
2. Кафка обеспечит нам partial order (партишенинг кафки по агрегату)
3. Опять же из-за партишенинга, у нас есть возможность использовать locality data patterns и работать с агрегатом при помощи load data -> mutate -> store, и не бояться что в соседнем воркере хэндлер тоже что-то сделал с этими данными.
4. Ну и в связке с DDD хотим топики и т.д. в любом случае.
5. В этом случае в принципе транзакции нам нужны только для «все или ничего с ролбэками». Боюсь что без этого транзакции убьют перформанс на нет когда все и вся будет ритраиться из-за конфликтов.

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

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

Не уверен что всех этих проблем можно избежать полагаясь только на транзакции. Тем более придется разбираться очень хорошо с изоляциями транзакций (например Serializable как я понимаю монго не поддерживает). Всякие фантомные ридс и т.д. Я то в конце разберусь, а вот остальные люди в компании — не уверен что все разберутся.
Приходилось ли кому натягивать сову на глобус попробовать имплементировать DDD для задач где есть работа с календарем?

Например есть вещь и есть календарь у этой вещи. Любой человек может попросить попользоваться этой вещью на определенное время. Если запрос удовлетворен, то это вещь принадлежит определенному человеку на определенный период. Если нет, то в календаре состояние этой вещи на определенные даты отображается со статусом «pending» например. Статусы могут быть разными. Вещь можно передавать другому человеку, отменять и т.д. Может быт несколько запросов от разных человек на разные даты и они будут отображаться в календаре.

Можно смотреть на это вещи и из состояние. Допустим есть у нас:

Item {
id
title

}

state block {
id
startDate
endDate
itemId
status [available, pending, reserved, unavailable]
userId
}

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

1. Много конкурентных запросов и команд для определенной вещи от разных людей, апи и скедулеров которые в конце концов манипулируют стейтом. Создают, меняют даты, статус, овнеров и т.д.
2. Стейты могут накладывать друг на друга с разными датами, статусами и т.д по определенным правилам.
3. Нужно обеспечить целостность данных. Например 2 запроса одновременно могут увидеть что вещь свободна (!reserved, unavailable), и попытаяются зарезервировать его. В это время кто то может вручную заассайнить вещь на эти же даты на другого человека. И в это же время какой нибудь скедулер отменяет стейт в том же диапазоне дат потому что статус pending ничего не решает.

Вот что мы думаем.

1. Стейт блок как агрегат. Но, пользователи работают с датами календаря и вещами. Они не видят и не знают что это имплементировано в базе стейтами с айдишниками. Айдишники это скорее для девелоперов просто что бы оперировать данными в базе. Пользователи могут выбрать вещь и отменить пользование в определенных датах, а внутри уже наш код знает как обрезать стейты, делаить их или мержить. Их может быть несколько эти стейт блоков. Не вариант вобщем.

2. Item это агрегат рут. И вся работа со стейтами (календарем) будет идти через него. И так как он должен быть под транзакцией и никакого конкурентного доступа к нему не должно быть на запись по определению агрегата (если я не ошибаюсь), мы можем загрузить в память календарь этого агрегата по itemId, делать с ним что хотим, со всеми этими стейтами, пока остальные ждут, и потом сохранить. Чтобы не было конкурентного доступа на мутации будет кафка с партишенами по айтему ну и/или оптимистик лок и/или транзакции. НО — если человек хочет взять вещь на след неделе, на 4 дня, то его запрос будет ждать пока агрегат освободиться, потому что кто то зарезервировал пользование на сегодня и идет обработка. Ну то есть мы убиваем конкаренси тут конкретно, а нам она нужна.

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

з.ы.
Сейчас у нас это имплементировано с транзакциями в монго (прости господи). Там столько всего я еще не раобрался полностью как оно живет. Худо бедно работает. Но данные херачатся переодически, и когда в рантайме мы на эти стейти налаживаем еще правила всякие, на выходе иногда получаются неправильные данные. Потому как на деле можнт быть 20 воркеров получивших задачу что-то сделать с одним и тем же айтемом. Ну и перформанс на рид райт не ахти. А некоторые требование по запросам мы вообще выполнить не можем. Ну не подходит схема.

Вот пытаемся на sqrc + возможно event sourcing + materialized view и все это в рамках DDD запилить. Что бы и история была, вьюшки под разные запросы разные создавались, и что бы избавиться от проблем невалидных данных в базе. Только вот положить этот стейт на агрегат не можем. Грузить например 2 года календаря в память что бы изменить пару дней как-то некошерно. Можно поиграться и загрузить только релевантные данные в память если получиться (например стейты ближних дат для проверки
конфликтов и другие валидации) + по itemId, и после мутации сохранить опять в базу. Но опять же, мутаций много. Некоторе из них нужно выполнить очень быстро (может приоритет запросов на мутацию тут поможет).

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

Вобщем мозг взрывается =)) Может кто чего подскажет почитать, посмотреть.

З.Ы.
Может все таки у нас нет выбора кроме как грузить в память состояние календаря, но попытаться делать все так быстро что бы по максимому обеспечить throughput и компенсировать недостаточную конкурентность/параллельную обработку?
Работаю в 3-ем стартапе уже четвертый год…

1. Первый закрылся через ~3 года, из которых я отработал полтора где-то. Зашел аккурат перед выходом в продакшен. Кто этого никогда не делал, вряд ли поймет что это. Скажем так, когда инвестору обещали выйти в мир через неделю, после почти года интенсивной разработки, а по итогу за 4 дня до релиза ты понимаешь что даже логин не работает потому что люди писавшие все это чудо на JS не понимали что такое асинхронность. Пришлось знатно попотеть.

2. Со второго уволили после 9-ти месяцев (стартап был очень маленький, решил расти, и директор думал что взять чувака и посадить за стол, без управления ни проектом, ни компанией со стороны менеджмента (его не было) будет работать так же хорошо как и когда в стартапе было 5 челоек. В итога год промучался я с каким то проектом который лежал в ящике как минимум год, и директор думал что я его закончу за пол года без намека не техзадание и минимального списка requirements). Директор просто хотел «что бы работало». В итоге разочаровался что я не закончил его проект, и мы расстались.

3. Уже четвертый год в 3ем стартапе. Процессы поставлены. Есть начальнки, есть менеджеры. есть техзадание и т.д.

Работы завал. Проблем завал. Легаси завал. Новых фичеров завал. Поддержка юзеров и багов, тоже завал. При этом, проблемы нетривиальные и интересные. Местами highload, event driven и т.д. Так же проблемы перформанса, легаси, тестов и т.д. Скажем так, распиливаем монолит который писался 5 лет все кому не лень. Можете представить себе объем работы. Да, приходится много блокеров чинить, и 2 ночи и в 7 вечера. Не для каждого. Но, вайб хороший, не скучно, и можно реально расти.

Не знаю как в других странах, но в Израиле, если ты не дурак, то за год в стартапе ты узнаешь и учишься тому что в большой компании возьмет года 3. Есть компании старые и большие, где люди по 9 лет работают, и все что они делают это запуск бэкапа скриптом. Остальное время поддерживают легаси… (я не говорю про гугл фейсбук и эппл… там немного подругому, но и в них ты маленький винтик).

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

Я после работы в стартапах ничего не боюсь в этой жизни =))

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


Это как? Депенденси инжекшен он и в африке… И если они бэкендистов заставили писать фронт, а не фуллстек/фронтенд разработчиков, то ожидаемо что они будут писать говнокод без энтузиазма. Хоть на ангуляре хоть на реакте.

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

Я никогда не видел двух проектов React с одинаковыми зависимостями, структурой проекта и руководящими принципами.


Ну если структуру делать feature based то она и на ангуляре разная будет.

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

Вообще тут намешаны разные вещи не связанные с реактом от слова совсем. Билд берет время? Ну это проблема всей экосистемы ноды.

Могу согласиться только с тем что новые хуки и контекст добавляют магию и конвенции, и действительно не все их любят, включая меня. Ну и борьба с самим собой потому что на тебе лежит ответственность выбора библиотек, а не как в ангуляре — что дали тебе в фреймворке то и юзай. Хотя и там сторонних библиотек хватает. Redux это отдельная пестня…
Действительно. Давно не следил за редисом. Похоже Redis Streams это кафка на минималках. Но все же интересно. Может пригодится когда нибудь.
Как это противоречит тому что написано? Это конечно же можно делать как часть процесса обработки месседжа. А там как хотите так и делайте. Хоти в s3 кидайте, хотите в базу. Хотите по ключу определяйте что такой рипорт уже просили и возвращайте данные с прошлой обработки. А где вы их храните — это же ваш бизнес решает.

Тут же не об этом. Тут о том что браузер не будет ждать так долго и оборвет коннекшен. И в добавок если что-то временно пошло не так, можно делать попробовать позже и захендлить этот кейс а не ждать пока юзер обнаружит что что0то зафейлилось и он должен повторить просьбу.
Ну да. Шардинг это не про «отдельный топик по id» (id как пример), это про обеспечение условия fifo по id. Это просто условие что мессежди одного и того же юзера будут обработаны в определенном порядке, за счет того что они прилетят на один и тот же консюмер.

Решение с топиком под каждого юзера кажется мне избыточным и возможно даже не реализуемым. Вот что пишут в самой кафке

Unlike many messaging systems Kafka topics are meant to scale up arbitrarily. Hence we encourage fewer large topics rather than many small topics. So for example if we were storing notifications for users we would encourage a design with a single notifications topic partitioned by user id rather than a separate topic per user.

The actual scalability is for the most part determined by the number of total partitions across all topics not the number of topics itself (see the question below for details).


И

Jun Rao (Kafka committer; now at Confluent but he was formerly in LinkedIn's Kafka team) wrote:

At LinkedIn, our largest cluster has more than 2K topics. 5K topics should be fine. [...]

With more topics, you may hit one of those limits: (1) # dirs allowed in a FS; (2) open file handlers (we keep all log segments open in the broker); (3) ZK nodes.
Проблема в том что в раббите нужно свой велосипед писать для ребалансировки шардов если вдруг нужно убрать/добавить консюмер. Насчет медленности раббита — зависит от задачи. У нас мессежди обрабатываются сравнительно медленно, поэтому скорость самого раббита вообще не интересна.

Information

Rating
6,248-th
Location
Израиль
Date of birth
Registered
Activity