如何在Ubuntu14.04上将Parse应用程序迁移到ParseServer

来自菜鸟教程
跳转至:导航、​搜索

介绍

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.pemprivkey1.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.pemmongodb 用户拥有,并且只能由其所有者读取:

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 IDMaster 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 问题外,您不妨探索以下主题: