介绍
Parse 是一个移动后端即服务平台,自 2013 年起归 Facebook 所有。 2016 年 1 月,Parse 宣布其托管服务将于 2017 年 1 月 28 日完全关闭。
幸运的是,Parse 还发布了 一个开源 API 服务器 ,与托管服务的 API 兼容,称为 Parse Server。 Parse Server 正在积极开发中,似乎很可能会吸引大型开发人员社区。 它可以部署到运行 Node.js 和 MongoDB 的一系列环境中。
本指南侧重于将预先存在的 Parse 应用程序迁移到在 Ubuntu 14.04 上运行的 Parse Server 的独立实例。 它对所有连接使用 TLS/SSL 加密,使用 Let's Encrypt 提供的证书,这是一个提供免费证书的新证书颁发机构。 它包括一些特定于 DigitalOcean 和 Ubuntu 14.04 的细节,但应该广泛适用于运行最近由 Debian 派生的 GNU/Linux 发行版的系统。
警告: 强烈建议先使用应用程序的开发或测试版本测试此过程,然后再尝试使用面向用户的生产应用程序。 也强烈建议您结合官方迁移文档阅读本指南。
先决条件
本指南基于 How To Run Parse Server on Ubuntu 14.04。 它需要以下内容:
- Ubuntu 14.04 服务器,配置有非 root
sudo
用户 - Node.js 5.6.x
- MongoDB 3.0.x
- 指向服务器的域名
- 要迁移的 Parse App
- Nginx 使用 Let's Encrypt 证书安装和配置 SSL。 如何在 Ubuntu 14.04 上使用 Let's Encrypt 保护 Nginx 将引导您完成整个过程。
目标服务器应该有足够的存储空间来处理您应用的所有数据。 由于 Parse 最终压缩数据,因此他们正式建议您提供至少 10 倍于托管应用程序使用的存储空间。
第 1 步 – 配置 MongoDB 以进行迁移
Parse 为现有应用程序提供了迁移工具。 为了使用它,我们需要向外部连接打开 MongoDB,并使用 Let's Encrypt 的 TLS/SSL 证书副本保护它。 首先将 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
现在,在 nano
(或您选择的文本编辑器)中打开 /etc/mongod.conf
:
sudo nano /etc/mongod.conf
在这里,我们将进行一些重要的更改。
首先,在 net:
部分中查找 bindIp
行,并通过将 127.0.0.1
更改为 0.0.0.0
来告诉 MongoDB 监听所有地址。 在此下方,将 SSL 配置添加到同一部分:
/etc/mongod.conf
# network interfaces net: port: 27017 bindIp: 0.0.0.0 ssl: mode: requireSSL PEMKeyFile: /etc/ssl/mongo.pem
接下来,在 # security
下,启用客户端授权:
/etc/mongod.conf
# security security: authorization: enabled
最后,迁移工具需要我们将failIndexKeyTooLong
参数设置为false
:
/etc/mongod.conf
setParameter: failIndexKeyTooLong: false
注意: MongoDB 配置文件中的空白很重要,它基于 YAML。 复制配置值时,请确保保留缩进。
退出并保存文件。
在重启 mongod
服务之前,我们需要添加一个具有 admin
角色的用户。 连接到正在运行的 MongoDB 实例:
mongo --port 27017
创建管理员用户并退出。 请务必将 sammy 替换为您想要的用户名,将 password 替换为强密码。
use admin db.createUser({ user: "sammy", pwd: "password", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] }) exit
重启mongod
服务:
sudo service mongod restart
第 2 步 – 从 Parse 迁移应用程序数据
现在您有了一个可远程访问的 MongoDB 实例,您可以使用 Parse 迁移工具将应用程序的数据传输到您的服务器。
为迁移工具配置 MongoDB 凭据
我们将从本地连接我们的新管理员用户开始:
mongo --port 27017 --ssl --sslAllowInvalidCertificates --authenticationDatabase admin --username sammy --password
应该会提示您输入之前设置的密码。
连接后,为数据库选择一个名称来存储应用程序的数据。 例如,如果您正在迁移一个名为 Todo 的应用程序,您可能会使用 todo
。 您还需要为名为 parse 的用户选择另一个强密码。
在 mongo
shell 中,授予此用户对 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
,否则连接失败。 在对话框中输入连接字符串,如下所示:
单击开始迁移。 您应该看到将 Parse 托管数据库的快照复制到服务器的进度对话框,然后在拍摄快照后同步新数据。 此过程的持续时间将取决于要传输的数据量,并且可能很大。
验证数据迁移
完成后,迁移过程将进入验证步骤。 尚未完成迁移。 您首先要确保数据已实际传输,并测试 Parse Server 的本地实例。
返回到您的 mongo
shell,并检查您的本地数据库。 首先访问 database_name 并检查它包含的集合:
use database_name
show collections
Sample Output for Todo AppTodo _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
并返回 shell:
exit
第 3 步 – 安装和配置 Parse Server 和 PM2
使用 MongoDB 中的应用程序数据,我们可以继续安装 Parse Server 本身,并与系统的其余部分集成。 我们将给 Parse Server 一个专用用户,并使用一个名为 PM2 的实用程序来配置它并确保它始终运行。
全局安装 Parse Server 和 PM2
使用 npm
全局安装 parse-server
实用程序、pm2
进程管理器及其依赖项:
sudo npm install -g parse-server pm2
创建专用解析用户和主目录
我们将创建一个名为 parse 的系统用户,而不是以 root 或您的 sudo
用户身份运行 parse-server
:
sudo useradd --create-home --system parse
现在为 parse 设置密码:
sudo passwd parse
系统将提示您输入两次密码。
现在,使用 su
命令成为 parse 用户:
sudo su parse
切换到 parse 的主目录:
cd ~
编写或迁移云代码文件
创建云代码目录:
mkdir -p ~/cloud
编辑/home/parse/cloud/main.js
:
nano ~/cloud/main.js
出于测试目的,您可以粘贴以下内容:
/home/parse/cloud/main.js
Parse.Cloud.define('hello', function(req, res) { res.success('Hi'); });
或者,您可以迁移为您的应用程序定义的任何云代码,方法是从 Parse Dashboard 上应用程序设置的 Cloud Code 部分复制它。
退出并保存。
检索密钥并写入 /home/parse/ecosystem.json
PM2 是一个功能丰富的流程管理器,深受 Node.js 开发人员的欢迎。 我们将使用 pm2
实用程序来配置我们的 parse-server
实例并使其长期运行。
您需要为您的应用检索一些密钥。 在 Parse 仪表板中,单击应用设置其次是安全和密钥 :
其中,仅需要 Application ID 和 Master Key。 其他(客户端、JavaScript、.NET 和 REST API 密钥) 可能 是支持旧客户端构建所必需的,但如果设置,则在所有请求中都需要。 除非您有理由不相信,否则您应该从仅使用应用程序 ID 和主密钥开始。
准备好这些密钥后,编辑一个名为 /home/parse/ecosystem.json
的新文件:
nano ecosystem.json
粘贴以下内容,更改配置值以反映您的 MongoDB 连接字符串、应用程序 ID 和主密钥:
{ "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-server
还可以识别以下变量:
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
Sample Output... [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
保存这个进程列表:
pm2 save
Sample Output[PM2] Dumping processes
正在为 parse 用户运行的进程列表 pm2
现在应该存储在 /home/parse/.pm2
中。
现在我们需要确保每次重新启动服务器时恢复我们之前在 ecosystem.json
中定义的 parse-wrapper
进程。 幸运的是,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 Web 服务器提供 反向代理 到 parse-server
,以便我们可以通过 TLS/SSL 安全地提供 Parse API。
在先决条件中,您设置了 default
服务器以响应您的域名,并使用 Let's Encrypt 证书提供的 SSL。 我们将使用我们的代理信息更新此配置文件。
在 nano
(或您选择的编辑器)中打开 /etc/nginx/sites-enabled/default
:
sudo nano /etc/nginx/sites-enabled/default
在主 server
块内(它应该已经包含一个 location /
块)添加另一个 location
块来处理 /parse/
URL 的代理:
/etc/nginx/sites-enabled/default
. . . # 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
Output * Restarting nginx nginx ...done.
第 5 步 – 测试解析服务器
在这个阶段,您应该具备以下条件:
- Let's Encrypt 提供的 TLS/SSL 证书
- MongoDB,由 Let's Encrypt 证书保护
parse-server
在端口 1337 上的 parse 用户下运行,配置了您的应用所需的密钥pm2
管理 parse 用户下的parse-server
进程,以及启动时重启pm2
的启动脚本nginx
,使用 Let's Encrypt 证书保护,并配置为将https://your_domain_name/parse
的连接代理到parse-server
实例
现在应该可以使用 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":"Sammy","cheatMode":false}' \ https://your_domain_name/parse/classes/GameScore
样本输出
{"objectId":"YpxFdzox3u","createdAt":"2016-02-18T18:03:43.188Z"}
使用 GET 读取数据
由于 curl
默认发送 GET 请求,并且我们不提供任何数据,因此您只需发送应用程序 ID 即可读取一些示例数据:
curl -H "X-Parse-Application-Id: your_application_id" https://your_domain_name/parse/classes/GameScore
样本输出
{"results":[{"objectId":"BNGLzgF6KB","score":1337,"playerName":"Sammy","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"}]}
执行示例云代码
一个没有实际数据到 https://your_domain_name/parse/functions/hello
的简单 POST 将运行 /home/parse/cloud/main.js
中定义的 hello()
函数:
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"}
如果您已经迁移了自己的自定义云代码,则可以使用 main.js
中的已知函数进行测试。
第 6 步 – 为 Parse Server 配置您的应用程序并完成迁移
您的下一步将是更改您的客户端应用程序本身以使用 Parse Server API 端点。 有关使用 Parse SDK 和 Parse Server 的信息,请参阅 官方文档 。 您将需要适用于您的平台的最新版本的 SDK。 与上面基于 curl
的测试一样,使用此字符串作为服务器 URL:
https://your_domain_name/parse
返回浏览器中的 Parse 仪表板和 Migration 选项卡:
点击 Finalize 按钮:
现在应该迁移您的应用程序。
结论和后续步骤
本指南提供了一个功能起点,用于将 Parse 托管的应用程序迁移到单个 Ubuntu 系统(例如 DigitalOcean droplet)上的 Parse Server 安装。 我们所描述的配置对于具有适度用户群的低流量应用程序来说应该是足够的。 托管大型应用程序可能需要多个系统来提供冗余数据存储和 API 端点之间的负载平衡。 即使是小型项目也可能涉及我们尚未直接解决的基础设施问题。
除了阅读 Parse Server 官方文档并在排查问题时跟踪项目 的 GitHub 问题外,您不妨探索以下主题: