LINUX.ORG.RU

Масштабирование приложений на go и scala

 ,


3

3

Для нового приложения выбираем стек и появился вопрос, как масштабировать приложения на go и scala. На ноде есть pm2 и можно указывать кол-во инстансов, есть ли что-то похожее на go или scala?

Скорее всего заказчик будет пускать приложение в кубах, но во-первых - не факт, а во-вторых хотелось бы знать, как выжимать максимум с одного сервера или виртуалки.


Ответ на: комментарий от anonymous

можно запускать сборщик мусора для каждого потока отдельно, но обмен сообщениями между потоками будет делаться копированием сообщений

Примерно так и происходит.

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

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

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

anonymous
()
Ответ на: комментарий от anonymous

а го просто передаст одну и ту же ссылку из одной горутины в другую без копирований

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

кто там что выигрывает не понятно. что лучше: копировать память или переключать контексты?

Ну в такой формулировке вопрос имеет мало смысла. Надо выбрать метрику и по ней уже сравнивать.

theNamelessOne ★★★★★
()

Про Scala ничего не знаю.

Проблема Go состоит в том, что прибить горутину и конкретный процесс к одному ядру нельзя. В итоге у тебя есть планировщик, который будет конкурировать еще и с отправкой сообщений в каналы. На больше нагрузке у меня получалось что-то вроде shared memory api. На старте аллоцируется хитрая структура с кучей буферов, а потом в зависимости от состояния атомиков происходит маршрутизация сообщений в нужную горутину. На разных процессорах лучше покрутить GOMAXPROC(кажется так называется параметр макс. числа процессов), возможно уменьшение дефолтного значения позволит меньше конкурировать за ресурсы.

Что бы выжимать максимум, да еще и на виртуалках то тебе понадобится C++.

xpahos ★★★★★
()
Ответ на: комментарий от anonymous

Я сталкивался. Пришли к тому, что больше 4-6 ядер в нашем случае лучше было не использовать. Хотя на бумаге как раз всё должно было быть шикарно.

hateyoufeel ★★★★★
()
Ответ на: комментарий от anonymous

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

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

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

hateyoufeel ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Товарищ колхозник, оркестрацию и иже с ней для кого придумали?

Предлагаете даже на одиночном сервере или виртуалке для одного приложения с десятком потоков/задач разворачивать полный Kubernetes?

monk ★★★★★
()
Ответ на: комментарий от hateyoufeel

можешь рассказать подробнее, что это было за приложение и в чём конкретно заключалась проблема? если возможно, то даже с цифрами.

anonymous
()
Ответ на: комментарий от theNamelessOne

а в этой общей куче будет свой сборщик мусора и другие сборщики мусора её трогать не будут, да? а память течёт если ссылку оставить в другом потоке?

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

anonymous
()
Ответ на: комментарий от anonymous

С цифрами не получится, я давно не занимаюсь тем проектом и у меня нет доступа к коду.

Вкратце, был сервис, который принимал кучу сообщений по HTTP от кучи юзеров по сети, собирал статистику и отправлял раз в N времени в базу. Сделано было тупо на каждое соединение по горутине, которая крутилась в цикле receive -> process -> reply. Каждое отдельно сообщение было небольшим: вместе с HTTP заголовком вполне влезало в килобайт.

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

Решили это тупо подняв по процессу на ядро и сделав балансировку через nginx. Потом вроде кто-то глубоко ковырял это и переписывал, но я тогда уже свалил и подробностей не знаю.

hateyoufeel ★★★★★
()
Ответ на: комментарий от monk

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

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Мониторинг и метрики прикрутить — дело техники и считанных строк кода.

Продемонстрируете эти строки? Ежели они считанные. Особенно про мониторинг тасков на корутинах голанга.

monk ★★★★★
()

На ноде есть pm2 и можно указывать кол-во инстансов, есть ли что-то похожее на go или scala?

Можно писать на go или scala так же, как на ноде, а запускать через pm2: pm2 start go -- run app.go

monk ★★★★★
()
Ответ на: комментарий от monk

И причём тут мониторинг? Кто вообще мониторит корутины? Давай ещё каждый вызов аллокатора или наоборот gc мониторить например.

WitcherGeralt ★★
()
Ответ на: комментарий от anonymous

а в этой общей куче будет свой сборщик мусора и другие сборщики мусора её трогать не будут, да?

Да, там используется подсчёт ссылок.

а память течёт если ссылку оставить в другом потоке?

Ага.

theNamelessOne ★★★★★
()
Ответ на: комментарий от WitcherGeralt

В теме же было написано, чего хочет автор. Есть pm2. По ссылке видно набор функций, который он умеет. Существует ли аналог на go или scala?

В ответ получил предложение использовать горутины от Lrrr, использовать кубер или самописный велосипед от тебя, бред от Legioner и slaykovsky, что автор не понимает, что такое потоки и «ты не понял их ответы, ибо они (т.е. Legioner и slaykovsky) говорят всё правильно» от Demacr. От Demacr’а также было утверждение, что в го задачи отдельными приложениями не делаются: «Пойми, в нормальных языках тебе не нужно запускать несколько копий приложения в рамках одного сервера.».

А теперь от тебя «Кто вообще мониторит корутины?». То есть всё-таки и на го надо задачи запускать отдельными приложениями, а управлять через какой-то аналог pm2? Возвращаясь к вопросу: есть ли готовый аналог на go или scala. Или реально для го только запускать рабочий сервер в режиме профилирования, а для скалы покупать Phobos за $4000 в год?

monk ★★★★★
()
Ответ на: комментарий от WitcherGeralt

немного оффтоп, но этот товарищ прямым текстом заявлял, что «права человека» это очен-очень плохо. поэтому расценивать его как субъект диалога… ну такое.

anonymous
()
Ответ на: комментарий от hateyoufeel

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

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

Поднимать по процессу на ядро - одно из возможных решений. Кстати Nginx запилили nginx unit для go, как раз чтобы удобно рулить такими конфигурациями. Другие варианты - отказаться от net/http в пользу чего-то более производительного, например fasthttp, уменьшать число аллокаций в коде (использовать sync.Pool и т.п.).

Проблемы тут возникают ровно те же самые, что в других языках. С ростом нагрузки неизбежно придется вообще отказаться от сборки мусора и переписать сервис на каком-нибудь расте или C++.

Lrrr ★★★★★
()
Ответ на: комментарий от Lrrr

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

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

Проблемы тут возникают ровно те же самые, что в других языках. С ростом нагрузки неизбежно придется вообще отказаться от сборки мусора и переписать сервис на каком-нибудь расте или C++.

Или нет. Хацкелл у нас отлично на 32 ядра параллелился. Скорее всего, тут дело в глобальных структурах, на которых треды где-нибудь лочатся.

hateyoufeel ★★★★★
()
Ответ на: комментарий от anonymous

В среднем меньше секунды, но иногда отдельные треды секунд на 5-7 подвисали ЕМНИП.

Опять же, я не уверен, что это я или мои коллеги нигде не наgовнокодили, но свиду всё было ок и понять где именно затык было довольно нетривиально.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Понятно, всё же к врачу.

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

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

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

WitcherGeralt ★★
()

А что pm2 языко специфичный менеджер процессов? Вроде он умеет работать с бинарями. А так да куб, докер сворм, и пр.

DukeNukem
()

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

DukeNukem
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.