内容


IBM Bluemix 云平台上的 NodeRed

Comments

如果您没有 Bluemix 帐户,需要获得一个帐户。Bluemix 帐户的注册方便快捷,您可以获得 30 天的试用期,这会为您提供探索本教程中涵盖的服务的足够时间。如果您已经有一个帐户,请跳到下一步。

Bluemix 是一个平台即服务 (PaaS) 产品,允许您创建、部署和运行应用程序。所以您无需将时间重点用于探究 IT 基础架构,可以专注于手头的重要工作:向您的用户提供新功能。在探索 Bluemix 的过程中,查阅成本估算器。您会惊喜地发现,PaaS 应用程序非常便宜。请注意,如果您决定注册使用 Bluemix 超过 30 天,运行此试验可能会产生少量的成本。

引言

NodeRed 是一个基于 Nodejs 编程语言的,可视化的编程工具,用于集成硬件,应用程序接口和在线服务。它提供了一个以浏览器为基础的流程编辑器,可以很容易的通过各种服务或设备的编程组件创建自己的工作流。支持实时的扩展设备或服务组建和部署工作流。

NodeRed 是一个开放源代码的项目,可以运行在本地服务器上,也可以运行在云端。Bluemix 云计算平台就引入了 NodeRed 运行时。在 Bluemix 云计算平台上的 NodeRed 运行时,与社区版本稍有不同。在 Bluemix 云计算平台,将 NodeRed 运行时与持久化分离,利用 Bluemix 云计算平台提供的持久化服务,将 NodeRed 的配置信息,流程定义的信息保存于 Cloudant NoSQL DB。这更方便用户定制化数据的保存与恢复,也会带来一些小小的问题,本文主要介绍 Bluemix 云计算平台中的 NodeRed 的不同点,可能遇到的问题以及如何解决这些问题。

Bluemix 云平台中的 NodeRed

Bluemix 云平台中的 Node-Red 和社区版本稍有不同。在 Bluemix 平台有两个样板文件和 Node-Red 相关,一个是 Node-Red Starter,它包含一个 Nodejs 应用程序和一个 Cloudant NoSQL DB,另一个是 Internet of Things Platform Starter,它包含一个 Nodejs 应用程序,一个 Cloudant NoSQL DB 和一个 Watson IOT Platform。

在 Bluemix 云平台中,Cloudant NoSQL DB 是 Node-Red 应用程序的一个必要的服务。Cloudant NoSQL DB 用来存储 Node-Red 应用程序的配置信息,实时扩展的设备或服务组件以及工作流的定义。

在社区版的 Node-Red 应用程序中,通常用一个 flow.json 文件存储工作流的定义,文件通常放在"default"目录下。

但是在 Bluemix 版的 Node-Red 应用程序中,我们使用 Cloudant NoSQL DB 存储这些配置信息和工作流定义。这更符合云计算的特点,计算与持久化分离。只要相应的 Cloudant NoSQL DB 服务没有丢失,所有的配置信息和工作流定义就不会丢失,就可以很容易的恢复 Node-Red 应用程序并保留相应的配置和工作流。我们还可以通过 Cloudant NoSQL DB 的 Replication 功能很容易的实现配置信息和工作流信息的备份和恢复。

1. Cloudant NoSQL DB

IBM® Cloudant® 是 IBM 提供的全运维管理非关系型 JSON 数据库服务,旨在确保应用与其数据库之间的数据流始终无中断、高性能地运行。这样开发人员就可以自由地构建更多产品,发展更快且能够充分地休养生息。

1.1. 命名规则

在 Bluemix 云平台中,我们对 Node-Red 应用程序绑定的 Cloudant NoSQL DB 服务的名字是有要求的。这个名字应该符合这样的命名规则"<Node-Red 应用名称>-cloudantNoSQLDB"。否则 Node-Red 应用程序会因为无法连接到 Cloudant NoSQL DB 而无法启动。如果你不想使用这个的命名规则,那么你需要定义一个定制的环境变量去指定 Cloudant NoSQL DB 服务的名字。

变量名字是:NODE_RED_STORAGE_NAME

下图显示如何设置一个用户定义的环境变量,值是:<你的 Cloudant NoSQL DB 服务名字>。

当你成功创建了一个 Node-Red 应用程序后,打开应用程序的仪表板,点击"Connections",你会找到绑定的 Cloudant NoSQL DB。

1.2.Cloudant NoSQL DB 中存储的数据

点击这个 Cloudant NoSQL DB 服务就会进入这个服务的介绍页面,点击"LAUNCH",就可以进入到 Cloudant NoSQL DB 的仪表板。

在 Cloudant NoSQL DB 仪表板我们可以找一个名字为"nodered"的数据库,Node-Red 应用程序的配置信息,实时扩展的设备和服务组件信息还有工作流的定义都保存在这个数据库中。我们可以通过 Cloudant NoSQL DB 提供的 Replication 功能简单的实现这个数据库的备份和恢复工作。详情可以参考 Cloudant NoSQL DB 的文档[是否在这里加个引用?链接是什么。

打开 nodered 数据库,我们可以看到四个文档(也可称之为表)

_design/library

系统自动生成,用于创建视图,方便 Node-Red 应用程序加载存储在数据库中的数据。这个文档和具体的应用程序无关,我们不用关心。

node-red-chl-001/credential

node-red-chl-001/flow

node-red-chl-001/settings

这三个文档用户存储应用程序的配置信息和工作流定义,NodeRed 应用程序每次启动时都会去连接绑定的 Cloudant NoSQL DB,从数据库中倒入配置信息和工作流定义。每一次用户部署工作流时,NodeRed 应用程序会将最新的配置信息和工作流定义写入数据库。

由于 NodeRed 应用程序中所有的配置信息和工作流定义都存储在 Cloudant NoSQL DB 中,所以为了保护自己的工作成果,一定要保护好 Cloudant NoSQL DB 实例。做好备份工作,以防止服务被人为删除或数据丢失。

1.3 多 NodeRed 应用程序共享 Cloudant NoSQL DB

有时候我们可能需要创建多个 NodeRed 应用程序,并且希望它们享同一个 Cloudant NoSQL DB 实例。

从上一章节的图中我们可以看到每个文档名字的前面部分都是 Node-Red 应用程序的名字。Node-Red 应用程序根据名字加载存储的数据。这就导致,如果应用程序的名字改变了,就无法加载之前的数据。因为应用程序可以通过名字来区分,所以我们可以用同一个 Cloudant NoSQL DB Service 存储不同 Node-Red 应用程序的配置信息和工作流, 如果你的服务配额不足的话,这会是一个解决办法,如下图所示。

1.4.重命名应用程序

有时候用户希望能够重命名自己的应用程序,但是对于 Bluemix 云平台上的 NodeRed 来说可能会有一些问题。通常情况下用户在重命名 NodeRed 应用程序之后会发现原来的工作流都不见了。就像我们上一章节提到的,应用程序是通过应用程序的名字从数据库里面读取配置信息和工作流的定义。一旦应用程序的名字变了,也就读不到相应的配置和工作流定义了。

假如你需要重命名你的应用程序,在配置了 NODE_RED_STORAGE_NAME 变量之后(参考 1.1 命名规则)新的应用程序会创建新的文档,你需要拷贝原文档的内容到新的文档,这样新的应用程序就可以加载之前的工作流。

1.5.组件冲突

NodeRed 提供了一个"Manage Patette"的功能,用于实时安装拓展新的组件,但是"Manage Patette"只提供了组件安装功能,没有组件卸载功能。有可能我们安装的两个组件是相互冲突的,这就需要我们卸载其中的一个组件。由于,NodeRed 并没有提供卸载功能,我们只能手工从 Cloudant NoSQL DB 实例中将相应的组件删除。

在 1.2 Cloudant NoSQL DB 中存储的数据章节中我们提到了这个表 node-red-chl-001/settings 。里面包含了所有已经安装的组件。事实上我们安装组件有两种方式,一种是上面提到的通过"Manage Patette",另一种是通过修改 package.json。通过修改 package.json,添加新的 dependencies,并重新部署到 Bluemix 也可以安装新的组件。所有这些已安装的组件都可以在 node-red-chl-001/settings 这个表里面找到。

对于通过"Manage Patette"安装的组件,从 node-red-chl-001/settings 表里面删除相应的定义,重启应用程序就可以删除相应组件 。

对于通过 package.json 安装的组件,从数据库中删除是没有意义的,应用程序总是优先根据 package.json 安装组件,并把相应的信息写入数据库。

如果我们想要卸载通过 package.json 安装的组件,首先需要将相应组件从 package.json 中删除,但是这还不够。前面说过,NodeRed 运行时是基于 Nodejs 的。Bluemix 上的 NodeRed 运行时也是一个 Nodejs 运行时。Nodejs buildpack 有一个环境变量 NODE_MODULES_CACHE,默认值是 true。这意味着 buildpack 每次都会尝试通过 cache 去安装组件。所以我们还需要把这个环境变量的值改成 false,然后重新部署到 Bluemix 即可。我们可以通过添加一个环境变量到 manifest.yml 的方式修改变量值,下面是一个例子,仅供参考。

applications:
- path: .
  memory: 512M
  instances: 1
  domain: mybluemix.net
  name: chl-iot-test-001
  host: chl-iot-test-001
  disk_quota: 1024M
  services:
  - Object Storage-ny
  - chl-iot-test-001-cloudantNoSQLDB
  - chl-iot-test-001-iotf-service
  env:
    NODE_MODULES_CACHE: false

2.保护你的 NodeRed 应用程序

默认情况下,NodeRed 是开放的,所有人都可以通过网址访问你的 NodeRed 应用程序,编辑工作流,访问工作流接口。出于保护自己工作成果考虑我们需要对我们的应用程序加以保护。Bluemix 云平台上的 NodeRed 提供了简单的方式去保护自己的工作流和应用程序接口。

打开 Node-Red 应用程序的仪表盘,选择"Environment Variables",增加下面两个用户定制变量:

NODE_RED_USERNAME:用户名

NODE_RED_PASSWORD:密码

或者也可以通过在 manifest.yml 中添加环境变量来达到相同的目的,下面是个例子:

applications:
- path: .
  memory: 512M
  instances: 1
  domain: mybluemix.net
  name: chl-iot-test-001
  host: chl-iot-test-001
  disk_quota: 1024M
  services:
  - Object Storage-ny
  - chl-iot-test-001-cloudantNoSQLDB
  - chl-iot-test-001-iotf-service
  env:
    NODE_RED_USERNAME: 用户名
NODE_RED_PASSWORD: 密码

2.2.配置不同权限的多个用户

有时,你可能需要更强大的保护功能,想要为你的编辑器配置多个用户,不同的用户拥有不同的权限,这样能更好的保护你的应用程序。下面的方法可以帮助你实现这个功能。

首先,下载 starter 代码或者启用(enable) Continuous Delivery,这样你就可以编辑 starter 代码。

找到 bluemix-settings.js 文件,增加"adminAuth"到"settings". 主要包括下面几项内容:

type: "credentials",
sessionExpiryTime: 600,    #表示超市时间,秒为单位
users: [
    {
         username: "admin",   #用户名,明文
         password: "$2a$08$TnhJDZ0OkfEzxjiTldK3c.Mtm0Ixk96JFRna95ij8xB2uMXbmxYZ6",   #密码,要求填写摘要信息
         permissions: "*"     #所有权限(读/写)
    },
    {
         username: "test",   
         password: "$2a$08$TnhJDZ0OkfEzxjiTldK3c.Mtm0Ixk96JFRna95ij8xB2uMXbmxYZ6",  
         permissions: "read"     #所有权限(读/写)
    }
]

需要注意的是密码要求是摘要值,你可以通过下面这个命令获得你的密码的摘要值:

node-red-admin hash-pw

但在用这个命令之前,你需要通过下面的命令安装这个工具:

npm install -g node-red-admin

下面是一个例子,可供参考:

adminAuth: {
        type: "credentials",
        sessionExpiryTime: 600,
        users: [
            {
                username: "admin",
                password: "$2a$08$TnhJDZ0OkfEzxjiTldK3c.Mtm0Ixk96JFRna95ij8xB2uMXbmxYZ6",
                permissions: "*"
            },
            {
                username: "test01",
                password: "$2a$08$wGH7On0OjViUzRrhzwEh4ertLPTIy/BSCuIcD/zAQ9augOR8idgXe",
                permissions: "*"
            },
            {
                username: "test02",
                password: "$2a$08$AavRt2wTeYlmRNgiPUA4JutvipvcWeHAO0oxZhYOw3cf6oefoFYse",
                permissions: "read"
            }
        ]
    }

除了增加"adminAuth",我们还需要注释掉下面的代码,这段代码用来处理第一节的用户定义变量(为你的编辑器配置一个用户):

/*
if (process.env.NODE_RED_USERNAME && process.env.NODE_RED_PASSWORD) {
    settings.adminAuth = {
        type: "credentials",
        users: function(username) {
            if (process.env.NODE_RED_USERNAME == username) {
                return when.resolve({username:username,permissions:"*"});
            } else {
                return when.resolve(null);
            }
        },
        authenticate: function(username, password) {
            if (process.env.NODE_RED_USERNAME == username &&
                process.env.NODE_RED_PASSWORD == password) {
                return when.resolve({username:username,permissions:"*"});
            } else {
                return when.resolve(null);
            }
        }
    }
}
*/

2.3.保护你的接口

或许你不仅是想要保护你的工作流编辑器,还想保护你通过工作流定义的一些应用程序接口。下面的方法可以用来保护你的基于 http 协议的应用程序接口。

找到 bluemix-settings.js 文件,增加"httpNodeAth"到"settings". 我们可以提供一个用户名和密码用于访问当前应用程序的域。

下面是个例子,可供参考:

httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},

密码要求是摘要值,可以通过 "node-red-admin hash-pw" 来得到。

下面是一个非常简单的工作流,通过"httlp in" node 定义了一个接口,只是简单的返回客户的输入。

[{"id":"73bc582a.5edd28","type":"http in","z":"945d36a6.28097","name":"","url":"/test","method":"get","swaggerDoc":"","x":236,"y":232.25,"wires":[["5e42c301.fb1f2c"]]},{"id":"5e42c301.fb1f2c","type":"function","z":"945d36a6.28097","name":"","func":"\nreturn msg;","outputs":1,"noerr":0,"x":392,"y":240.75,"wires":[["dd0f3150.2641f"]]},{"id":"dd0f3150.2641f","type":"http response","z":"945d36a6.28097","name":"","x":556,"y":237.5,"wires":[]}]

你可以通过 Node-Red 应用程序的 Import->Clipboard 把它倒入到你的应用程序里。如果不加接口保护,任何人都可以通过这个 curl 命令调用这个接口 :

curl https://node-red-chl-001.mybluemix.net/test?test=haha

返回值是:

{"test":"haha"}

加了接口保护,这个命令会返回:

Unauthorized

你需要通过下面的命令访问这个接口:

curl -u user:password https://node-red-chl-001.m/test?test=haha

3.安装本地的依赖库

有时候你可能想要修改 node_modules 并且希望 Bluemix 可以从你本地安装你修改过的 node_modules。这里是一个例子,你可以这样做:

首先,先在本地安装这个依赖库;

npm install cloudant

然后拷贝一份依赖库到其他目录,修改你需要修改的内容。然后修改 package.json

修改 package.json,

"dependencies": {
    …
    "cloudant": "file:./cloudant",
    …
  },

最后重新部署你的应用程序即可。

4.常见问题及解答

4.1.NodeRed 应用程序无法启动

这是最常见的一类问题,首先需要检查是不是应用程序绑定的 Cloudant NoSQL DB 被人为删除了,如果 Cloudant NoSQL DB 还在,那检查命名规则是不是符合要求,详细信息可以参考 1.1 命名规则。

4.2.部署工作流失败

通常有两个问题会导致部署工作流失败:

4.2.1.多实例

NodeRed 在支持多实例的时候有些问题,这个是已知问题,NodeRed 在运行时是支持多实例的,多实例可以提供更好的性能。但在多实例的情况下,编辑工作流和部署工作流会带来多实例之间同步的问题。所以,如果实在工作流开发阶段,我们建议采用单实例模式。

4.2.2.Cloudant NoSQL DB 问题

这个问题和 4.1 类似,如果 NodeRed 应用程序处于运行中,有人删除了 Cloudant NoSQL DB,NodeRed 以及运行中的工作流不会受到影响,但是你无法编辑部署新的工作流。而且一旦你尝试重启 NodeRed,NodeRed 将无法启动,而且所有的配置信息和工作流都会丢失。

4.3.工作流丢失

工作流是存储在 Cloudant NoSQL DB 中,如果 DB 实例没有被删除,DB 内容没有人为删除,工作流就不会丢失。如果发现你的工作流丢失了,除了要排除是否有人人为的删除这些工作流之外,要查看一下是否有人重命名了 NodeRed 应用程序,这会导致 NodeRed 应用程序无法从数据库中找到相应的配置信息和工作流定义。详细信息可参考 1.4 重命名应用程序。

4.4.组件冲突

已知 node-red-dashboard 和 node-red-contrib-ui 相互冲突,它们绑定了相同的 route "ui"。解决冲突的办法详见 1.5 组件冲突。

4.5.保护 NodeRed

详见 2.保护你的 NodeRed 应用程序

结束语

本文主要阐述了 Bluemix 云平台中的 NodeRed 有哪些特点,介绍了由于云平台的特点可能引起一些问题和解决问题的办法。并介绍了如何保护自己的工作流和接口和一些常见问题的解决方法。本文在写作过程中主要参考了 NodeRed 的官方文档。也可以从这里了解到更多更新的关于 NodeRed 的内容:https://nodered.org/


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Cloud computing, Open source
ArticleID=1047426
ArticleTitle=IBM Bluemix 云平台上的 NodeRed
publish-date=08072017