Parse – это платформа «мобильный сервер как услуга», которая с 2013 года принадлежит Facebook. В январе 2016 Parse анонсировал, что полностью прекратит поддержку сервисов внешнего размещения 28 января 2017 года.
К счастью, Parse также выпустил сервер API с открытым исходным кодом, совместимый с API-интерфейсом хостинга, называемым Parse Server. Parse Server находится в активной разработке и, вероятно, привлечет большое сообщество разработчиков. Его можно развернуть в различных средах с Node.js и MongoDB.
В этом руководстве основное внимание уделяется миграции готового рабочего приложения Parse на автономный экземпляр Parse Server, работающий на Ubuntu 14.04. Он поддерживает шифрование TLS/SSL для всех подключений, используя бесплатный сертификат Let’s Encrypt. В целом этот мануал подходит всем пользователям, которые работают с Debian-подобными дистрибутивами GNU/Linux.
Важно! Настоятельно рекомендуется проверить данную процедуру на тестовой версии приложения, прежде чем пытаться выполнить ее на приложении в среде производства. Также при выполнении мануала следует обращаться к официальной документации проекта.
Требования
Данный мануал основан на руководстве Запуск Parse Server на Ubuntu 14.04.
Для работы вам понадобится:
- Сервер Ubuntu 14.04, настроенный по этому мануалу.
- Node.js 5.6.x
- MongoDB 3.0.x
- Домен, указывающий на ваш сервер.
- Рабочее приложение Parse, которое вы хотите переместить.
- Сервер Nginx с поддержкой SSL (читайте мануал Создание сертификата Let’s Encrypt для Nginx в Ubuntu 14.04).
На целевом сервере должно быть достаточно места для обработки всех данных вашего приложения. Поскольку Parse сжимает данные, разработчики проекта официально рекомендуют предоставить как минимум в 10 раз больше места, чем нужно вашему приложению.
1: Подготовка MongoDB к миграции данных
Parse предоставляет инструмент для перемещения готовых приложений. Для этого нужно открыть MongoDB для внешних подключений и защитить БД копией сертификата TLS/SSL от Let’s Encrypt. Для начала объедините fullchain1.pem и privkey1.pem в новый файл /etc/ssl:
sudo cat /etc/letsencrypt/archive/domain_name/{fullchain1.pem,privkey1.pem} | sudo tee /etc/ssl/mongo.pem
Примечание: Вам нужно будет повторить вышеуказанную команду после обновления сертификата Let’s Encrypt. Если вы настроили автоматическое обновление сертификата Let’s Encrypt, не забудьте включить эту операцию.
Передайте права на mongo.pem пользователю mongodb:
sudo chown mongodb:mongodb /etc/ssl/mongo.pem
sudo chmod 600 /etc/ssl/mongo.pem
Откройте /etc/mongod.conf в nano или другом текстовом редакторе:
sudo nano /etc/mongod.conf
Здесь нужно внести несколько важных изменений.
Сначала найдите строку bindIp в разделе net: и настройте MongoDB для прослушивания всех адресов, изменив 127.0.0.1 на 0.0.0.0. Ниже в тот же раздел вы можете добавить конфигурацию SSL:
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
ssl:
mode: requireSSL
PEMKeyFile: /etc/ssl/mongo.pem
Включите авторизацию клиентов в разделе # security:
# security
security:
authorization: enabled
Также инструмент миграции данных требует, чтобы у параметра failIndexKeyTooLong было значение false:
setParameter:
failIndexKeyTooLong: false
Примечание: В конфигурационных файлах MongoDB, которые основаны на YAML, все пробелы и отступы важны. При копировании конфигурации убедитесь, что вы сохранили отступы.
Сохраните и закройте файл.
Прежде чем перезапустить сервис mongod, нужно добавить пользователя с ролью admin. Подключитесь к текущему экземпляру MongoDB:
mongo --port 27017
Создайте админа и выйдите. Вместо 8host укажите имя вашего пользователя, а вместо password – свой надежный пароль.
use admin
db.createUser({
user: "8host",
pwd: "password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
exit
Перезапустите сервис:
sudo service mongod restart
2: Миграция данных приложения с Parse
Теперь, когда у вас есть экземпляр MongoDB с поддержкой удаленных подключений, вы можете использовать инструмент миграции данных Parse, чтобы переместить приложение на новый сервер.
Учетные данные MongoDB для инструмента миграции данных
Создайте локальное подключение с помощью аккаунта админа:
mongo --port 27017 --ssl --sslAllowInvalidCertificates --authenticationDatabase admin --username 8host --password
Вам будет предложено ввести пароль, который вы установили ранее.
После подключения выберите имя базы данных для хранения данных приложения. Например, если вы переносите приложение под названием Todo, вы можете использовать БД todo. Вам также потребуется выбрать еще один надежный пароль для пользователя, который называется parse.
В оболочке mongo передайте этому пользователю доступ к database_name:
use database_name
db.createUser({ user: "parse", pwd: "password", roles: [ "readWrite", "dbAdmin" ] })
Запуск процесса переноса данных
В браузере войдите в Parse и откройте настройки своего приложения. В разделе General найдите кнопку Migrate и нажмите ее.
Вам будет предложено ввести строку подключения MongoDB. Используйте следующий формат:
mongodb://parse:password@your_domain_name:27017/database_name?ssl=true
Например, если вы используете домен example.com, пользователя parse, пароль foo и БД todo, ваша строка подключения будет выглядеть так:
mongodb://parse:foo@example.com:27017/todo?ssl=true
Не забудьте указать ?ssl=true в конце, иначе соединение не будет выполнено. Введите строку подключения в диалоговое окно.
Нажмите Begin the migration. Вы должны увидеть прогресс копирования снапшота базы данных Parse на ваш сервер, а затем синхронизации новых данных со снапшотом. Продолжительность этого процесса будет зависеть от количества передаваемых данных и может занять много времени.
Проверка перемещенных данных
По завершении процесса миграции будет запущен этап проверки. Сейчас важно убедиться, что данные действительно переданы, и протестировать локальный экземпляр Parse Server.
Вернитесь к своей оболочке mongo и изучите локальную базу данных. Получите доступ к БД и просмотрите содержащиеся в ней коллекции:
use database_name
show collections
Sample Output for Todo App
Todo
_Index
_SCHEMA
_Session
_User
_dummy
system.indexes
Также можно изучить контент с помощью метода .find():
db.ApplicationName.find()
Sample Output for Todo App
> db.Todo.find()
{ "_id" : "hhbrhmBrs0", "order" : NumberLong(1), "_p_user" : "_User$dceklyR50A", "done" : false, "_acl" : { "dceklyR50A" : { "r" : true, "w" : true } }, "_rperm" : [ "dceklyR50A" ], "content" : "Migrate this app to my own server.", "_updated_at" : ISODate("2016-02-08T20:44:26.157Z"), "_wperm" : [ "dceklyR50A" ], "_created_at" : ISODate("2016-02-08T20:44:26.157Z") }
Ваш результат, конечно, будет другим, вы должны увидеть данные своего приложения. Убедившись, что все данные на месте, выйдите из mongo и вернитесь в оболочку:
exit
3: Установка и настройка Parse Server и PM2
Теперь можно перейти к установке самого Parse Server и интеграции с остальной частью системы. Предоставьте Parse Server выделенного пользователя и используйте утилиту PM2 для его настройки.
Глобальная установка Parse Server и PM2
Используйте npm для глобальной установки утилиты parse-server, диспетчера процессов pm2 и их зависимостей:
sudo npm install -g parse-server pm2
Создание выделенного пользователя и домашнего каталога
Вместо пользователя root или sudo для запуска parse-server используйте специального системного пользователя, который называется parse:
sudo useradd --create-home --system parse
Установите для него пароль:
sudo passwd parse
Вам будет предложено ввести пароль дважды.
Теперь используйте команду su, чтобы стать пользователем parse:
sudo su parse
Перейдите в его домашний каталог:
cd ~
Запись или миграция файла cloud code
Создайте каталог для cloud code:
mkdir -p ~/cloud
Отредактируйте /home/parse/cloud/main.js:
nano ~/cloud/main.js
Для тестирования можно вставить такие строки:
Parse.Cloud.define('hello', function(req, res) {
res.success('Hi');
});
Кроме того, вы можете перенести любой cloud code вашего приложения, скопировав его из раздела Cloud Code в настройках вашего приложения в панели Parse Dashboard.
Выйдите и сохраните файл.
Извлечение ключей и настройка /home/parse/ecosystem.json
PM2 – многофункциональный менеджер процессов, популярный у разработчиков Node.js. Мы будем использовать утилиту pm2 для настройки экземпляра parse-server и управления его работой в дальнейшем.
Вам нужно извлечь некоторые из ключей вашего приложения. На панели инструментов Parse нажмите App Settings, затем Security & Keys.
Здесь вам нужны идентификатор приложения и главный ключ (Application ID и Master Key). Другие ключи (ключи клиента, JavaScript, .NET и REST API) могут потребоваться для поддержки старых сборок клиента, но если они установлены, они требуются во всех запросах. Если у вас нет оснований использовать другие ключи, вы должны извлечь только Application ID и Master Key.
Затем отредактируйте файл /home/parse/ecosystem.json:
nano ecosystem.json
Вставьте следующие строки, указав свою строку подключения MongoDB, Application ID и Master Key:
{
"apps" : [{
"name" : "parse-wrapper",
"script" : "/usr/bin/parse-server",
"watch" : true,
"merge_logs" : true,
"cwd" : "/home/parse",
"env": {
"PARSE_SERVER_CLOUD_CODE_MAIN": "/home/parse/cloud/main.js",
"PARSE_SERVER_DATABASE_URI": "mongodb://parse:password@your_domain_name:27017/database_name?ssl=true",
"PARSE_SERVER_APPLICATION_ID": "your_application_id",
"PARSE_SERVER_MASTER_KEY": "your_master_key",
}
}]
}
Объект env используется для установки переменных среды. Если вам нужно настроить дополнительные ключи, parse-сервер также распознает следующие переменные:
- PARSE_SERVER_COLLECTION_PREFIX
- PARSE_SERVER_CLIENT_KEY
- PARSE_SERVER_REST_API_KEY
- PARSE_SERVER_DOTNET_KEY
- PARSE_SERVER_JAVASCRIPT_KEY
- PARSE_SERVER_DOTNET_KEY
- PARSE_SERVER_FILE_KEY
- PARSE_SERVER_FACEBOOK_APP_IDS
Сохраните и закройте ecosystem.json.
Запустите сценарий с помощью pm2:
pm2 start ecosystem.json
...
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Process launched
┌───────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │
├───────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ parse-wrapper │ 0 │ fork │ 3499 │ online │ 0 │ 0s │ 13.680 MB │ enabled │
└───────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
Теперь нужно сохранить этот список процессов:
pm2 save
[PM2] Dumping processes
Список процессов pm2, выполняющийся для пользователя parse, теперь должен быть сохранен в /home/parse/.pm2.
Теперь нужно убедиться, что процесс parse-wrapper, который вы определили ранее в ecosystem.json, восстанавливается при каждом перезапуске сервера. К счастью, pm2 может генерировать и устанавливать сценарий самостоятельно.
Выйдите в сессию обычного пользователя sudo:
exit
С помощью pm2 можно определить, какие скрипты инициализации для Ubuntu будут выполняться как пользователь parse, используя /home/parse как домашний каталог:
sudo pm2 startup ubuntu -u parse --hp /home/parse/
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Generating system init script in /etc/init.d/pm2-init.sh
[PM2] Making script booting at startup...
[PM2] -ubuntu- Using the command:
su -c "chmod +x /etc/init.d/pm2-init.sh && update-rc.d pm2-init.sh defaults"
System start/stop links for /etc/init.d/pm2-init.sh already exist.
[PM2] Done.
4: Установка и настройка Nginx
Мы будем использовать веб-сервер Nginx в качестве обратного прокси-сервера для parse-server, чтобы безопасно обслуживать Parse API через TLS/SSL.
Согласно требованиям мануала вы настроили сервер по умолчанию отвечать на ваше доменное имя с помощью SSL-сертификата Let’s Encrypt. Сейчас нужно обновить этот файл конфигурации, добавив туда информацию прокси.
Откройте /etc/nginx/sites-enabled/default:
sudo nano /etc/nginx/sites-enabled/default
Внутри основного блока server (он должен уже содержать блок location) нужно добавить еще один элемент location для обработки проксирования URL-адресов /parse/:
. . .
# Pass requests for /parse/ to Parse Server instance at localhost:1337
location /parse/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:1337/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
Сохраните и закройте файл. Перезапустите Nginx:
sudo service nginx restart
* Restarting nginx nginx
...done.
5: Тестирование Parse Server
На этом этапе вы должны иметь следующие компоненты:
- Сертификат TLS/SSL, предоставленный Let’s Encrypt
- Экземпляр MongoDB, защищенный сертификатом Let’s Encrypt
- parse-server, запущенный как пользователь parse по порту 1337, настроенный с помощью ключей приложения
- pm2, управляющий процессом parse-server пользователя parse и запускающий сценарий для перезапуска pm2 во время загрузки
- сервер nginx, защищенный сертификатом Let’s Encrypt и настроенный на проксирование соединений с https://your_domain_name/parse на экземпляр parse-server.
Теперь вы можете выполнить тестовые операции записи, чтения и выполнения cloud code с помощью curl.
Примечание: Команда curl не повредит тестовое приложение или версию, которая находится в разработке. Будьте осторожны при использовании curl с версией в производстве.
Запись данных с помощью POST
Вы должны передать curl несколько важных опций:
Опция | Описание |
-X POST | Устанавливает тип запроса (в противном случае по умолчанию был бы GET) |
-H “X-Parse-Application-Id:your_application_id” | Отправляет заголовок, который идентифицирует ваше приложение на parse-server |
-H “Content-Type: application/json” | Отправляет заголовок, который помогает parse-server обнаружить данные в формате JSON |
-d ‘{json_data} | Отправляет сами данные |
В результате будет такая команда:
curl -X POST \
-H "X-Parse-Application-Id: your_application_id" \
-H "Content-Type: application/json" \
-d '{"score":1337,"playerName":"8host","cheatMode":false}' \
https://your_domain_name/parse/classes/GameScore
{"objectId":"YpxFdzox3u","createdAt":"2016-02-18T18:03:43.188Z"}
Чтение данных с помощью GET
Поскольку curl отправляет запросы GET по умолчанию и вам не нужно добавлять какие-либо данные, теперь достаточно отправить Application ID:
curl -H "X-Parse-Application-Id: your_application_id" https://your_domain_name/parse/classes/GameScore
{"results":[{"objectId":"BNGLzgF6KB","score":1337,"playerName":"8host","cheatMode":false,"updatedAt":"2016-02-17T20:53:59.947Z","createdAt":"2016-02-17T20:53:59.947Z"},{"objectId":"0l1yE3ivB6","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T03:57:00.932Z","createdAt":"2016-02-18T03:57:00.932Z"},{"objectId":"aKgvFqDkXh","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T04:44:01.275Z","createdAt":"2016-02-18T04:44:01.275Z"},{"objectId":"zCKTgKzCRH","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T16:56:51.245Z","createdAt":"2016-02-18T16:56:51.245Z"},{"objectId":"YpxFdzox3u","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T18:03:43.188Z","createdAt":"2016-02-18T18:03:43.188Z"}]}
Выполнение тестового cloud code
Простой POST-запрос без реальных данных для https://your_domain_name/parse/functions/hello запустит функцию hello(), определенную в /home/parse/cloud/main.js:
curl -X POST \
-H "X-Parse-Application-Id: your_application_id" \
-H "Content-Type: application/json" \
-d '{}' \
https://your_domain_name/parse/functions/hello
{"result":"Hi"}
Если вы вместо этого перенесли свой собственный cloud code, вы можете протестировать его с помощью функции из main.js.
6: Настройка приложения на Parse Server и завершение миграции
Следующим шагом будет изменение самого клиентского приложения для использования конечной точки API Parse Server. Обратитесь к официальной документации по использованию Parse SDK с Parse Server. Вам понадобится последняя версия SDK для вашей платформы. Как и в вышеописанных тестах с curl, используйте эту строку для URL-адреса сервера:
https://your_domain_name/parse
Вернитесь на панель инструментов Parse в браузере откройте вкладку Migration. Нажмите кнопку Finalize.
Теперь ваше приложение должно быть перенесено.
Заключение
Данный мануал предлагает базовые шаги для переноса приложения Parse и установки Parse Server в единой системе Ubuntu. Конфигурация, которую мы описали здесь, подходит для приложения с низким трафиком и скромной пользовательской базой. Для хостинга большего приложения может потребоваться несколько серверов (для обеспечения избыточного хранения данных и балансировки нагрузки между конечными точками API). Даже небольшие проекты, вероятно, могут потребовать настройки инфраструктуры, о которой здесь не рассказывается.
В дополнение к официальной документации Parse Server и отслеживанию проблем проекта на GitHub при устранении неполадок вы можете изучить следующие темы: