От переводчика: MeteorJS — открытый (MIT) фулстек JavaScript фреймворк (и клиент и сервер). Текущая версия 0.7.0 — в начале 2014 планируется выход версии 1.0. Публикации на хабре: 1, 2, 3.
Диаграмма компонентов:
Здесь три сервера Метеор, один MongoDb-сервер и HaProxy-сервер, как балансировщик нагрузки. Для поддержки SSL поставим Stud перед HaProxy.
Давайте обсудим компоненты и их настройку.
Я использую одно-серверный набор реплик с поддержкой oplog. Лучше, конечно, использовать много-сервернрый, но я немного упростил, для большей наглядности.
Прежде всего, необходимо запустить MongoDb, так, чтобы она знала о реплике. Воспользуемся следующей командой для настройки набора реплик meteor:
После этого открываем Mongo-shell, и вводим следующие настройки для нашей одно-серверной реплики:
Так-как мы используем выделенный MongoDb-сервер, необходимо предотвратить неавторизованный доступ к нему. Можно настроить брандмауэр, либо использовать доступ по ролям в самой MongoDb. Чтобы упростить настройку, я предполагаю, что у вас правильно сконфигурирован брандмауэр, либо же обратитесь к документации по ролевому доступу MongoDb.
Базу данных для Метеор-приложения назовем app. Для интеграции с oplog, будем использовать базу данных с именем local, в которой и будет находиться сам oplog.
При планировании развертки масштабируемого Метеор-приложения нужно учитывать несколько моментов. О них мы и поговорим.
В предыдущей статье я уже рассказывал о том, как oplog может помочь горизонтальному масштабированию Метеор. Есть два варианта. Можно использовать SmartCollections или предварительную версию Метеора с oplog (UPD вышла версия Метеора 0.7.0 с полной поддержкой OpLog. Ее и следует использовать.).
И в том и в другом случае нужно будет указать дополнительный MongoDB connection URL к журналу oplog (к базе данных local, о которой я говорил ранее). Для SmartCollection нужно будет установить переменную среды OPLOG_URL, для предварительной реализации oplog в Метеор, переменную MONGO_OPLOG_URL.
(Ну и конечно, как обычно, нужно не забыть установить MONGO_URL)
IE 8 и 9 не отправляют cookies c AJAX запросом и это сломает наш балансировщик нагрузки, который мы обсудим далее. К счастью, в SockJS есть встроенное решение этой проблемы, но оно выключено по умолчанию в Метеор. Чтобы включить его необходимо экспортировать следующую переменную окружения:
Очень важно чтобы вы выбрали одинаковые сервера для Метеор. Нужно чтобы они были в одном дата-центре, имели одну и ту же производительность, ОС и архитектуру, иначе нагрузка будет неправильно балансироваться.
В текущей настройке я использую только по одному процессу на сервер, поэтому многоядерные сервера вряд ли помогут. Постарайтесь использовать одноядерное аппаратное окружение для серверов. В следующих статьях я расскажу об этом подробней.
Очень важно развертывать ваши серверы Метеор корректно, правильно настроив сервера. Если это возможно, обратитесь за помощью к тому, кто в этом ориентируется. Либо же можете использовать Meteor-Up, который я создал для того, чтобы осуществлять развертывание готовых к промышленной эксплуатации приложений Метеор.
Для балансиновки нагрузки у нашего Метеор-приложения я буду использовать HaProxy. Он очень стабилен и испытан в промышленной эксплуатации многими компаниями. Так же HaProxy поддерживает sticky-session и имеет некоторые другие полезные нам настройки.
Есть несколько вариантов реализации sticky-session. Они реализуются при помощи cookies, хэшированием IP клиента или модификацией URL. Есть еще варианты, но это самые распространенные.
Хэширование IP-адреса клиента самый простой в реализации способ, но с ним не получается нормально сбалансировать нагрузку. Мы не можем доверять IP информации да и прозрачные прокси-сервера (очень часть используются провайдерами) скрывают оригинальный IP, что для нас обернется повышенной нагрузкой на каком-то из серверов.
Модификация URL — хороший вариант и он очень хорошо поддерживается SockJS. Но для него требуется реализовать дополнительную логику в балансировщике нагрузки и в Метеор.
Решение, основанное на cookies, подходит нам лучше всего — оно отлично балансируется и легко настраивается.
Очень важно выбрать хороший алгоритм балансировки нагрузки. В HaProxy их несколько. Алгоритм roundrobin рекомендуется документацией. Он отлично подходит для приложений не содержащих внутреннее состояние (stateless), созданных, например, на RoR или PHP.
Однако, Метеор основан на учете состояний и долговременных соединениях, так что лучше воспользоваться алгоритмом leastconn. В нем новое подключение отдается серверу, имеющему наименьшее количество соединений. Это дает равномерное распределение нагрузки, даже в случае временного отключения какого-либо сервера. В случае с roundrobin загрузка была бы неравномерной.
Посмотрите, как я настроил HaProxy, это конфигурационный файл:
Некоторые части конфигурационного файла я удалил ради наглядности. Полную версию можно взять тут.
Использование SSL в промышленной эксплуатации, на мой взгляд, обязательно. К сожалению стабильная версия HaProxy не поддерживает SSL. Но мы можем использовать Stud перед HaProxy как второй конец SSL-соединения. Ну и конечно же лучше разворачивать Stud на том же сервере, что и HaProxy.
Можно использовать следующий файл настроек:
Здесь полная версия файла настроек.
Stud требует, чтобы ваш SSL-сертификат и закрытый ключ были в одном .pem-файле. Подробнее в этой инструкции.
П.С. На хабре появился новый хаб: Meteor.JS — подписывайтесь.
Подготовка к масштабированию
Диаграмма компонентов:
Здесь три сервера Метеор, один MongoDb-сервер и HaProxy-сервер, как балансировщик нагрузки. Для поддержки SSL поставим Stud перед HaProxy.
Давайте обсудим компоненты и их настройку.
Настройка MongoDb
Я использую одно-серверный набор реплик с поддержкой oplog. Лучше, конечно, использовать много-сервернрый, но я немного упростил, для большей наглядности.
Настройка одно-серверной реплики
Прежде всего, необходимо запустить MongoDb, так, чтобы она знала о реплике. Воспользуемся следующей командой для настройки набора реплик meteor:
mongod --replSet meteor
После этого открываем Mongo-shell, и вводим следующие настройки для нашей одно-серверной реплики:
var config = {_id: "meteor", members: [{_id: 0, host: "127.0.0.1:27017"}]}
rs.initiate(config)
Контроль доступа
Так-как мы используем выделенный MongoDb-сервер, необходимо предотвратить неавторизованный доступ к нему. Можно настроить брандмауэр, либо использовать доступ по ролям в самой MongoDb. Чтобы упростить настройку, я предполагаю, что у вас правильно сконфигурирован брандмауэр, либо же обратитесь к документации по ролевому доступу MongoDb.
Базу данных для Метеор-приложения назовем app. Для интеграции с oplog, будем использовать базу данных с именем local, в которой и будет находиться сам oplog.
Настройка Метеор
При планировании развертки масштабируемого Метеор-приложения нужно учитывать несколько моментов. О них мы и поговорим.
Поддержка Oplog
В предыдущей статье я уже рассказывал о том, как oplog может помочь горизонтальному масштабированию Метеор. Есть два варианта. Можно использовать SmartCollections или предварительную версию Метеора с oplog (UPD вышла версия Метеора 0.7.0 с полной поддержкой OpLog. Ее и следует использовать.).
Подробнее узнать о интеграции MongoDb oplog в Метеор можно из выступления Девида Грасера в DevShop 10.
И в том и в другом случае нужно будет указать дополнительный MongoDB connection URL к журналу oplog (к базе данных local, о которой я говорил ранее). Для SmartCollection нужно будет установить переменную среды OPLOG_URL, для предварительной реализации oplog в Метеор, переменную MONGO_OPLOG_URL.
(Ну и конечно, как обычно, нужно не забыть установить MONGO_URL)
Поддержка sticky-session в IE 8 и 9
IE 8 и 9 не отправляют cookies c AJAX запросом и это сломает наш балансировщик нагрузки, который мы обсудим далее. К счастью, в SockJS есть встроенное решение этой проблемы, но оно выключено по умолчанию в Метеор. Чтобы включить его необходимо экспортировать следующую переменную окружения:
export USE_JSESSIONID=1
Используйте Метеор версии 0.6.6 или старше, данная опция появилась начиная с этой версии.
Выбор серверов
Очень важно чтобы вы выбрали одинаковые сервера для Метеор. Нужно чтобы они были в одном дата-центре, имели одну и ту же производительность, ОС и архитектуру, иначе нагрузка будет неправильно балансироваться.
В текущей настройке я использую только по одному процессу на сервер, поэтому многоядерные сервера вряд ли помогут. Постарайтесь использовать одноядерное аппаратное окружение для серверов. В следующих статьях я расскажу об этом подробней.
Развертывание
Очень важно развертывать ваши серверы Метеор корректно, правильно настроив сервера. Если это возможно, обратитесь за помощью к тому, кто в этом ориентируется. Либо же можете использовать Meteor-Up, который я создал для того, чтобы осуществлять развертывание готовых к промышленной эксплуатации приложений Метеор.
Настройка балансировщика нагрузки (HaProxy)
Для балансиновки нагрузки у нашего Метеор-приложения я буду использовать HaProxy. Он очень стабилен и испытан в промышленной эксплуатации многими компаниями. Так же HaProxy поддерживает sticky-session и имеет некоторые другие полезные нам настройки.
Поддержка sticky-session
Есть несколько вариантов реализации sticky-session. Они реализуются при помощи cookies, хэшированием IP клиента или модификацией URL. Есть еще варианты, но это самые распространенные.
Хэширование IP-адреса клиента самый простой в реализации способ, но с ним не получается нормально сбалансировать нагрузку. Мы не можем доверять IP информации да и прозрачные прокси-сервера (очень часть используются провайдерами) скрывают оригинальный IP, что для нас обернется повышенной нагрузкой на каком-то из серверов.
Модификация URL — хороший вариант и он очень хорошо поддерживается SockJS. Но для него требуется реализовать дополнительную логику в балансировщике нагрузки и в Метеор.
Решение, основанное на cookies, подходит нам лучше всего — оно отлично балансируется и легко настраивается.
Алгоритм балансировки нагрузки
Очень важно выбрать хороший алгоритм балансировки нагрузки. В HaProxy их несколько. Алгоритм roundrobin рекомендуется документацией. Он отлично подходит для приложений не содержащих внутреннее состояние (stateless), созданных, например, на RoR или PHP.
Однако, Метеор основан на учете состояний и долговременных соединениях, так что лучше воспользоваться алгоритмом leastconn. В нем новое подключение отдается серверу, имеющему наименьшее количество соединений. Это дает равномерное распределение нагрузки, даже в случае временного отключения какого-либо сервера. В случае с roundrobin загрузка была бы неравномерной.
Настройка
Посмотрите, как я настроил HaProxy, это конфигурационный файл:
defaults
mode http
timeout connect 5s
timeout client 10s
timeout server 10s
frontend public
#binding port 80
bind *:80
default_backend apps
backend apps
#load balancing algorithm
balance leastconn
#using JSESSIONID as the cookie
cookie JSESSIONID insert nocache
#adding server
server host1 host1.example.com cookie host1
server host2 host2.example.com cookie host2
server host3 host3.example.com cookie host3
Некоторые части конфигурационного файла я удалил ради наглядности. Полную версию можно взять тут.
SSL с помощью Stud
Использование SSL в промышленной эксплуатации, на мой взгляд, обязательно. К сожалению стабильная версия HaProxy не поддерживает SSL. Но мы можем использовать Stud перед HaProxy как второй конец SSL-соединения. Ну и конечно же лучше разворачивать Stud на том же сервере, что и HaProxy.
Убедитесь, что устанавливаете Stud из исходников. Версия, получаемая, apt-get устарела.
Можно использовать следующий файл настроек:
#bind to defualt SSL port
frontend = "[*]:443"
#haproxy host and port
backend = "[localhost]:80"
#location of the .pem file
pem-file = "/path/to/ssl.pem"
Здесь полная версия файла настроек.
Stud требует, чтобы ваш SSL-сертификат и закрытый ключ были в одном .pem-файле. Подробнее в этой инструкции.
П.С. На хабре появился новый хаб: Meteor.JS — подписывайтесь.