Подход Lift к масштабируемости лежит на одной машине. Масштабирование на разных машинах - более сложная тема. Краткий ответ: Scala и Lift ничего не делают, чтобы помочь или препятствовать горизонтальному масштабированию.
Что касается действующих лиц на одном компьютере, Lift достигает лучшей масштабируемости, поскольку один экземпляр может обрабатывать больше одновременных запросов, чем большинство других серверов. Чтобы объяснить, я сначала должен указать на недостатки в классической модели обработки потоков на запрос. Потерпи меня, это потребует некоторого объяснения.
Типичная структура использует поток для обслуживания запроса страницы. Когда клиент подключается, платформа назначает поток из пула. Затем этот поток выполняет три вещи: он читает запрос из сокета; он выполняет некоторые вычисления (потенциально включая ввод-вывод в базу данных); и он отправляет ответ на сокет. Практически на каждом этапе поток будет блокироваться в течение некоторого времени. При чтении запроса его можно заблокировать во время ожидания сети. При выполнении вычислений он может блокировать дисковый или сетевой ввод-вывод. Он также может заблокировать во время ожидания базы данных. Наконец, при отправке ответа он может блокироваться, если клиент получает данные медленно и окна TCP заполняются. В целом, поток может потратить 30 - 90% своего времени заблокированного. Однако он тратит 100% своего времени на один запрос.
JVM может поддерживать только столько потоков, сколько реально замедляется. Планирование потоков, конкуренция за объекты общей памяти (например, пулы соединений и мониторы) и собственная ОС ограничивают все ограничения на количество потоков, которые может создать JVM.
Что ж, если JVM ограничена в своем максимальном количестве потоков, а количество потоков определяет, сколько одновременных запросов может обработать сервер, то количество одновременных запросов будет определяться количеством потоков.
(Существуют и другие проблемы, которые могут накладывать более низкие ограничения - например, GC thrashing. Потоки являются основным ограничивающим фактором, но не единственным!)
Lift отделяет поток от запросов. В Lift запрос не связывает поток. Скорее, поток выполняет действие (например, читает запрос), а затем отправляет сообщение субъекту. Актеры - важная часть истории, потому что они запланированы через «легкие» темы. Пул потоков используется для обработки сообщений внутри актеров. Важно избегать блокирования операций внутри акторов, поэтому эти потоки быстро возвращаются в пул. (Обратите внимание, что этот пул не виден приложению, он является частью поддержки акторов в Scala.) Например, запрос, который в настоящее время заблокирован для базы данных или дискового ввода-вывода, не удерживает поток обработки запросов занятым. Поток обработки запросов доступен почти сразу, чтобы получить больше соединений.
Этот метод для разделения запросов от потоков позволяет серверу Lift иметь намного больше одновременных запросов, чем сервер потока на запрос. (Я также хотел бы отметить, что библиотека Grizzly поддерживает аналогичный подход без акторов.) Больше одновременных запросов означает, что один сервер Lift может поддерживать больше пользователей, чем обычный сервер Java EE.