Pull to refresh

Node: Масштабирование в малом против масштабирования в целом

Reading time8 min
Views4.7K
Original author: Alex Payne
Последние несколько недель я использую все свободное время, которое могу найти, чтобы обдумать, какие технологии мы будем использовать, чтобы реализовать первую версию BankSimple. Многие люди, вероятно, предположат, что я сразу же предпочёл Scala, в связи с тем, что я был соавтором книги об этом языке, но я подхожу к решению инженерных задач совершенно иначе. Каждая проблема имеет соответствующий набор применяемых технологий, и задача разработчика, — обосновать необходимость их использования.

(Кстати, Scala, может быть, хорошо подходит для BankSimple, в немалой степени из-за большого количества стороннего кода на Java, с которым мы должны интегрироваться, но это уже совсем другая тема для блога, и даже, скорее всего, для совершенно другого блога).

Одной из самых обсуждаемых технологий среди Hacker News является Node, окружение для разработки и запуска событийно-управляемых приложений JavaScript на виртуальной машине V8. В рамках выбора технологий для реализации проекта я выполнил оценку Node. Вчера я выразил некоторый общий скепсис относительно Node, и автор этого окружения, Райан Дал, попросил, чтобы я изложил свои мысли более подробно. Так вот, приступаю.

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

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

Для чего создан Node?


Раздел «О проекте» домашней страницы Node гласит:
«Цель Node, — предоставить простой путь к построению масштабируемых сетевых приложений».

Несколькими параграфами ниже заявлено:

«Так как ничего не блокируется, даже не эксперты в области программирования способны создавать быстрые системы [с Node]».

Итак, цель Node, — обеспечить простой способ создавать масштабируемые сетевые программы, или чтобы программистам, не являющимися экспертами, разрабатывать «быстрые системы»?

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

Масштабирование в малом


В системе незначительного масштаба, в целом, все работает.

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

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

Здесь, я считаю, Node подходит идеально.

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

Это замечательно. Такой результат определенно соответствует заявленной вторичной цели Node, — «менее, чем программист-эксперт» „в состоянии разработать быструю систему“. Тем не менее, он имеет очень мало общего с масштабированием в целом, в более широко понимании этого термина.

Масштабирование в целом


В системе значительных масштабов у нас нет волшебной пули.

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

В этом и заключается моя критика основной заявленной цели Node: «обеспечить простой способ создания масштабируемых сетевых программ». Я принципиально не верю, что есть простой способ создания масштабируемого чего-угодно. Люди путают легкие проблемы с простыми решениями.

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

Рост Node


Что касается меня, я думаю, что Node будет тяжело расти вместе с разработчиками в процессе перехода от масштабирования в малом к масштабированию в целом (нет, я не аргументирую это тем, что „обратные вызовы превратятся в кучу спагетти-кода“, хотя, я думаю, вы слышите об этом снова и снова, потому что это фактически болезненная точка разработчиков асинхронных систем).

Смелым решением в архитектуре Node является то, что все операции асинхронны, вплоть до файлового ввода/вывода, и я восхищаюсь приверженностью Райана к последовательности и ясности в реализации данного тезиса в своем программном обеспечении. Инженеры, которые глубоко понимают нагрузку их систем, могут найти места, где модель Node хорошо подойдёт, и может быть хорошей и эффективной в течение неопределенного времени; этого мы не знаем, так как пока не наблюдаем долгосрочных и зрелых развертываний Node. Большинство систем, с которыми я работал, всё время меняются. Меняется рабочая нагрузка. Данные, с которыми вы работаете, меняются вместе с системой. То, что раньше хорошо подходило под асинхронное решение, вдруг стало лучше обслуживаться многопоточным решением, или наоборот, или вы столкнулись с некоторыми другими, непредсказуемыми, полными изменениями.

Если вы глубоко погрузились в Node, вы застряли на одном из путей достижения параллелизма, на одном из способов моделирования ваших проблем и решений. Если решение не вписывается в основу событийной модели, вы попали. С другой стороны, если вы работаете с системой, которая позволяет реализовать несколько различных подходов параллелизации (JVM, CLR, C, C++, GHC и т.д.), у вас есть возможность изменить свою модель параллелизма по мере того, как ваша система эволюционирует.

На данный момент основная предпосылка Node, — что события обязательно означают высокую производительность — до сих пор под вопросом. Исследователи из Калифорнийского университета в Беркли обнаружили, что „потоки исполнения могут обладать сильными сторонами событийной модели, включая поддержку высокого параллелизма, низкие накладные расходы, а также простую модель параллелизма“. Позднее исследование, основанное на предыдущей работе, показывает, что события и подход с моделью конвейера одинаково хороши, и что блокирующие сокеты могут реально увеличить свою производительность. В индустриальном мире Java периодически речь идет о том, что неблокирующий ввод/вывод не обязательно лучше подходит по сравнению с потоками исполнения. Даже один из самых цитируемых документов по этому вопросу с вопиющим заголовком «Почему потоки, — плохая идея» заканчивается выводом, что вы не должны отказываться от потоков для высокопроизводительных серверов. Там как раз указано, что не бывает решения, которое одинаково подходит всем в плане параллелизма.

На самом деле, принятие гибридного подхода к параллелизма, кажется, является движением вперед, если нет каких-либо противопоказаний. Ученые в области компьютерных наук из университета штата Пенсильвания обнаружили, что сочетание потоков и событий предлагает лучшее из обоих миров. Команда Scala в EPFL утверждает, что Actors объединяют программирование на основе потоков выполнения и программирование на основе событий в одну аккуратную, простую для понимания, абстракцию. Russ Cox, бывший сотрудник Bell Labs, теперь занятый проектом языка программирования Go в Google, заходит ещё дальше, утверждая, что бессмысленна сама дискуссия „потоки против событий“ (обратите внимание, что все это даже не затрагивает аспект распределения масштабирования системы; потоки — это конструкции для одного компьютера, и события, — конструкции для одного процессора; мы даже не говорим о распределении работы между машинами в простой манере; кстати, это включено в Erlang, и о нём стоит задуматься, если вы няньчите быстро растущую систему).

Утверждение: опытные разработчики используют смесь потоков и событий, а также альтернативные подходы, такие как Actors и, экспериментально, STM. Для них мысль, что „неблокирующий означает, что он быстр“ звучит, по крайней мере, немного глупо, это относится к мифологии масштабируемости. Ребята, которые платят большие деньги, чтобы поставить масштабируемые решения, не переписывают лихорадочно по ночам свои системы с использованием Node. Они делают то, что они всегда делали: измерение, тестирование, тестирование производительности, обдумывание, изучение научной литературы, относящейся к их проблемам. Это то, что необходимо для масштабирования в целом.

Заключение


Для моих инвестиций рабочего времени, я бы скорее основывался на системе, которая позволяет мне гибко смешивать асинхронный подход с другими способами моделирования параллелизма. Гибридная модель параллелизма не может быть столь же простой и чистой, как подход Node, но зато будет более гибкой. Хотя BankSimple находится в зачаточном состоянии, мы будем сталкиваться с радостными проблемами масштабирования в малом, и Node может быть разумным выбором для нас на этом раннем этапе. Но когда нам требуется масштабирование в целом, я бы предпочел ассортимент из различных вариантов, открытых для меня, и я бы не хотел столкнуться с перспективой большого переписывания под давлением обстоятельств.

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

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

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

Это нелегко.
Tags:
Hubs:
+39
Comments39

Articles

Change theme settings