понедельник, 5 сентября 2016 г.

[prog.flame] Яркий пример того, почему инструменты вроде SObjectizer-а нужны, а на самом деле нет

Примером служит вот эта тема на LOR-е. Дабы не нужно было ходить по ссылке (хотя сходить, почитать комментарии, можно) скопирую стартовое сообщение:

Есть общий вопрос по очередям, по причине изобретения своего лисапеда. Как в нодах с воркерами регулируется нагрузка процессора? Хочется «чтобы было хорошо», но без крайностей вроде полного дублирования шедьюлера операционки.

Самое простое, это сделать воркеры однотредовыми и выгребать за раз по 1 задаче. Но даже если задача «тяжелая», у нее могут быть операции I/O, где процессор простаивает. Первое что приходит в голову - сделать воркеров в пару раз больше чем ядер, это вроде решит проблему с размазыванием нагрузки на проц.

А как быть если задача «долгая», но не сильно грузит CPU? Например, сканирование URL. Там время уходит на скачивание файла, а проц стоит. И что не очень приятно, если прилетит пачка таких задач (больше чем воркеров), они могут например тормознуть отправку писем (более приоритетные задачи).

Я могу отчасти снять проблемы с блокировками, запакетировав обработку ссылок (чтобы обрабатывалось все что накопилось но только одной задачей). Таким образом, блокироваться будет не больше одного ядра на каждую разновидность неудачной задачи. Но может можно сделать как-то красивее? Без превращения кода в ад.

UPD. Воркер - процесс node.js, то есть кооперативность на уровне IO там есть.

Предлагаю абстрагироваться от того, что автору LOR-овского топика нужно решение именно под node.js. Сама по себе проблема раскидывания разнородных тасков по рабочим нитям в тех или иных вариациях встречается весьма часто. Даже псевдозадачка из статей о SObjectizer-е для Хабра (которая про проверку email-ов) -- она ведь из той же оперы по сути.

И SObjectizer мы создавали для того, чтобы подобные задачи решались проще и быстрее. Отсюда и такая штука, как диспетчеры, которые позволяют "по щелчку" привязывать агентов-воркеров к наиболее подходящему рабочему контексту. Нужна рабочая нить, на которой мелкие агенты будут очень быстро инициировать асинхронные IO-операции -- пожалуйста. Нужен пул рабочих нитей, на которых тяжеловесные агенты будут выполнять нагружающие CPU операции -- пожалуйста. Нужны отдельные нити для работы со сторонним синхронным API -- да не вопрос. Ну и доступные из коробки очереди сообщений для общения агентов друг с другом. А так же всякие ручки для настройки и контроля всего этого.

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

Проблема, однако, в том, что когда разработчик сталкивается с подобной задачкой, он начинает на нее смотреть через призму своих собственных стереотипов, фобий и возможностей. Застрянет у такого разработчика в башке какая-нибудь идея фикс и все. Ничего больше не воспринимается. Зачем брать что-то чужое готовое, если можно слабать на коленке свой лисапед, у которого не будет фатального недостатка? ;)

Комментариев нет: