深入了解IoTAgent-JSON:物联网中间件解决方案
逐步指南
引言
本指南将逐步展示如何部署和配置IoTAgent-JSON物联网代理,用于将设备连接到外部的NGSI代理(即上下文代理)。
IoTAgent-JSON物联网代理作为一个网关,使用MQTT协议与NGSI代理(或使用NGSI协议的其他组件)进行通信。通信基于一系列单向的MQTT主题(即:每个主题用于发布设备信息或订阅实体更新,但不是两者兼具)。每个主题都有相同的前缀,形式如下:
/<apiKey>/<deviceId>/topicSpecificPart
其中apiKey
是用于逻辑分组设备(和安全问题)的字母数字字符串,deviceId
是唯一标识设备的ID。API密钥可以为IoT代理的一个实例全局配置,或为特定设备组专门配置(如后续章节所述)。
该协议的详细规范可在此处找到。
本指南将通过一个常见场景的逐步示例来展示代理的使用,从IoT代理设置到测量报告(包括单独配置设备的情况和首先配置具有新API密钥的设备组的情况)。开始指南前,请确保满足下一节中的所有要求。
在开始教程之前,我们需要一些关于即将部署服务的信息。我们将使用以下数据,模拟智能家居应用:
- 服务:myhome
- 子服务:/environment
- 设备ID:sensor01、sensor02 和 actuator01
先决条件
本逐步指南假设您将在一台单独的机器上安装所有软件,该机器安装了Red Hat 6.5 Linux。因此,它可能不适用于生产目的的架构,但应作为一个开发机来测试MQTT物联网代理。所有命令都应该在同一台机器上执行(甚至包括curl和mosquitto-pub命令),但将它们更改为从外部机器执行应该是一个简单的任务。
本教程选择的MQTT代理是Mosquitto,尽管可以用任何其他标准MQTT代理替代。本指南还将使用Mosquitto命令工具来测试安装和展示模拟设备与上下文代理之间的信息交换。
推荐软件及版本列表如下:
- Orion上下文代理(v2.5.0)
- Node.js(v10)
- Mosquitto(v1.4.7)(开箱即用设置)
- Curl(v7.19.7)
- Git(v1.7.1)
这些是编写本教程时使用的版本,但任何高于这些版本的版本也应该工作(早期版本也可能工作,但也可能不工作,因此我们鼓励您使用高于这些版本的版本)。
为了提高可读性,所有命令都将以root身份执行。要使用其他用户,请给予其适当权限并像往常一样使用sudo(从RPM包安装会为代理创建一个特殊用户,但在本教程中不会使用)。
使用默认API密钥配置单个设备
安装IoT代理
安装IoT代理有多种方式。在本教程中,我们将从仓库克隆代理的最新版本。有关不同设置,请查看主README.md文件中的安装指南。
我们将在/opt
仓库中安装我们的IoT代理。要执行此操作,请转到文件夹并使用以下命令克隆仓库:
cd /opt
git clone https://github.com/telefonicaid/iotagent-json.git
现在仓库已被克隆,请进入新目录并使用以下命令安装依赖项:
cd iotagent-json
npm install
现在,通过执行以下命令在后台运行代理:
nohup bin/iotagent-json &> /var/log/iotAgent&
代理现在应该在北端口(默认为4041)监听。使用netstat命令检查:
netstat -ntpl | grep 4041
您应该看到如下输出:
tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN 18388/node
检查一切是否正常工作的简单方法是从IoT代理的北端口获取版本:
curl http://localhost:4041/iot/about
结果将是一个JSON文档,指示IoTAgent-JSON IoTA版本和正在使用的IoTA库版本:
{
"libVersion": "0.9.5",
"port": 4041,
"baseRoot": "/",
"version": "0.1.5"
}
您也可以在nohup命令创建的/var/log/iotAgent
文件中检查日志。
IoT代理配置
IoTAgent的所有配置都可以通过修改单个文件config.js
来完成。默认值应该满足本教程的需求。
有关这些值的详细描述,请查看iotagent-node-lib配置文档。
在遵循本教程时,您可能想要更改的一个配置值是logLevel
。如果您在遵循指南时遇到任何问题,或者您只是想了解IoTA内部发生了什么,请将其值设置为DEBUG。
还要注意,deviceRegistry的配置类型设置为memory。这意味着当IoT代理重新启动时,设备注册表的所有内容都将从内存中擦除。这意味着在测试环境中使用,它将迫使您在重新启动代理后重新配置所有设备。要获得持久的注册表,请查看文档了解如何将IoTA连接到MongoDB实例。
配置设备
为了开始使用IoTA,必须配置新设备。我们将使用curl命令创建它。执行以下命令:
curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"devices": [
{
"device_id": "sensor01",
"entity_name": "LivingRoomSensor",
"entity_type": "multiSensor",
"attributes": [
{ "object_id": "t", "name": "Temperature", "type": "celsius" },
{ "object_id": "l", "name": "Luminosity", "type": "lumens" }
]
}
]
}
' 'http://localhost:4041/iot/devices'
这个命令将创建最简单的设备类型,只声明了两个活动属性:温度和亮度。
我们还没有为我们的设备创建特定配置,因此API密钥将是IoTA的默认密钥(即:1234)。这个默认API密钥可以在配置文件中更改。
使用设备发送测量值
现在我们可以模拟一些设备的测量值。由于我们的设备具有设备ID sensor01,我们正在使用的API密钥是默认的1234,我们可以使用以下命令使用mosquitto命令行客户端发送测量值:
mosquitto_pub -t /1234/sensor01/attrs -m '{"l":4,"t": "31.5"}'
这个命令应该将所有信息发布到上下文代理。对设备实体执行queryContext操作应该给出我们发布的信息:
curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{
"entities": [
{
"isPattern": "false",
"id": "LivingRoomSensor",
"type": "multiSensor"
}
]
}' 'http://localhost:1026/v1/queryContext'
结果响应应如下所示:
{
"contextResponses": [
{
"contextElement": {
"type": "multiSensor",
"isPattern": "false",
"id": "LivingRoomSensor",
"attributes": [
{
"name": "Luminosity",
"type": "lumens",
"value": "4"
},
{
"name": "Temperature",
"type": "celsius",
"value": "31.5"
}
]
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
从上下文代理检索配置参数
IoTAgent-JSON物联网代理提供了一种特殊机制,用于从代表设备的实体中检索信息,以便设备配置。这种机制基于两个特殊主题,后缀分别为/configuration/commands和/configuration/values。
为了测试此功能,我们首先将为代表设备的上下文代理实体添加一些配置属性。我们将使用以下NGSI请求添加sleepTime属性:
curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Cache-Control: no-cache" -d '{
"value" : "300"
}' 'http://localhost:1026/v1/contextEntities/LivingRoomSensor/attributes/sleepTime'
当IoT代理请求配置值时,它会向上下文代理请求这些值。一旦收集到这些值,它将通过带有'/configuration/values'后缀的主题将它们发送到设备。要使用我们的模拟设备检查此操作,请执行以下行:
mosquitto_sub -t /1234/sensor01/configuration/values
将此命令保留在单独的窗口中,同时执行以下步骤。
现在我们可以发送类似以下的MQTT请求,向IoT代理请求属性值:
mosquitto_pub -t /1234/sensor01/configuration/commands -m '{ "type": "configuration", "fields": [ "sleepTime" ] }'
如果我们现在返回到订阅窗口,我们应该能够看到sleepTime命令的值:
{ "sleepTime": "300", "dt": "20160209T111442Z" }
与设备请求的所有信息一起,IoT代理将在响应的dt字段中报告服务器时间。
使用配置配置多个设备
在需要配置具有类似特征的一组设备的情况下,可以为它们创建公共配置。此配置配置可用于通过为每个组建立特定的API密钥来分隔服务之间的设备消息。这可用于保护特定设备组的访问权限(在Mosquitto MQTT代理的最后一节中将展示如何实现这一点的示例)。
配置
首先,我们将使用引言部分定义的数据配置一个新的配置。为此,我们将发出以下命令:
curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"services": [
{
"resource": "/iot/json",
"apikey": "AAFF9977",
"type": "potSensor"
}
]
}
' 'http://localhost:4041/iot/services'
这将使该服务、子服务和类型下配置的设备使用提供的APIKey作为MQTT主题中的APIKey前缀。
配置设备
对于支持自动设备配置的IoT代理,配置一个配置就足以开始使用使用该配置的设备。对于那些不支持的代理,每个特定设备必须配置,以便在设备注册表中保存其deviceID。设备配置与单个设备的配置非常似:
curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"devices": [
{
"device_id": "sensor02",
"entity_name": "RosesPot",
"entity_type": "potSensor",
"attributes": [
{
"name": "humidity",
"type": "degrees"
},
{
"name": "happiness",
"type": "subjective"
}
]
}
]
}
' 'http://localhost:4041/iot/devices'
发送测量数据
现在我们可以像单个设备配置的情况一样模拟测量。使用以下命令发送新的模拟测量:
mosquitto_pub -t /AAFF9977/sensor02/attrs -m '{"humidity": 76,"happiness": "Not bad"}'
请注意,在这种情况下,API密钥不是默认的,而是我们在配置API中定义的。
我们可以通过再次调用上下文代理来检查一切是否正常:
curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{
"entities": [
{
"isPattern": "false",
"id": "RosesPot",
"type": "potSensor"
}
]
}' 'http://localhost:1026/v1/queryContext'
我们将得到类似这样的响应:
{
"contextResponses" : [
{
"contextElement" : {
"type" : "potSensor",
"isPattern" : "false",
"id" : "RosesPot",
"attributes" : [
{
"name" : "happiness",
"type" : "subjective",
"value" : "Not bad"
},
{
"name" : "humidity",
"type" : "degrees",
"value" : "76"
}
]
},
"statusCode" : {
"code" : "200",
"reasonPhrase" : "OK"
}
}
]
}
这表明我们发送的测量信息已正确写入上下文代理。
使用ACL保护配置访问权限
概述
使用特殊API密钥使IoT代理管理员有机会为每组设备设置不同的MQTT代理级别权限,使用不同的授权机制分隔不同组的访问。
使用开箱即用的Mosquitto设置,任何设备(实际上,任何MQTT客户端)都可以冒充其他设备发送信息或读取其实体中的信息,只需知道它们的API密钥和设备ID。为了避免这个问题,我们将创建一个ACL,为我们的配置赋予特殊权限,并为该组的设备设置一组凭据(应与设备秘密共享)。为了简单起见,我们将使用一组用户和密码凭据,所有该组的设备都使用相同的凭据(也可以使用其他认证方式,如证书,请查阅Mosquitto文档了解其他选项)。
IoTA访问也可能发生设备冒充问题(因为IoTA是另一个MQTT客户端,默认情况下是匿名的)。为了保护IoTA的交互,将创建另一个用户。
配置
为了创建用户,我们将使用mosquitto提供的密码工具。执行以下命令:
touch /etc/mosquitto/pwfile
mosquitto_passwd -b /etc/mosquitto/pwfile iota iota
mosquitto_passwd -b /etc/mosquitto/pwfile potteduser pottedpass
这将创建两组凭据(登录/密码):iota/iota 和 potteduser/pottedpass。
可以使用ACL文件赋予不同主题的权限。要创建一个ACL文件,只需创建一个新的`/etc/mosquitto/aclfile`文件,内容如下:
topic read $SYS/#
topic write /1234/+/attrs
topic write /1234/+/attrs/#
topic write /1234/+/configuration/commands
topic read /1234/+/configuration/values
user iota
topic /#
user potteduser
topic write /AAFF9977/+/attrs
topic write /AAFF9977/+/attrs/#
topic write /AAFF9977/+/configuration/commands
topic read /AAFF9977/+/configuration/values
pattern write $SYS/broker/connection/%c/state
此文件中有三个感兴趣的部分:
- 1. 第一部分为默认API密钥(本例中为1234)定义了一组主题。这些主题根据设备将要执行的动作被标记为读或写。禁止除所定义动作之外的访问,以及向读主题发布或相反的操作。这确保了没有设备能冒充IoT代理,但这并不阻止一个设备冒充其他设备。此访问是匿名的。
- 2. iota用户是认证的,可以访问一切,因为假设是代理的所有者(只有管理员应该访问此用户)。
- 3. 对于potteduser账户,权限与匿名设备类似,但前缀是不同的API密钥。这确保了来自其他组的设备(假定没有作为potteduser的有效凭据)无法冒充该组的设备,或订阅该组设备发送的信息。
在我们重新开始测试之前,还需要做两个更改。首先,我们应该在IoTA配置中添加Mosquitto的IoTA凭据,以便其获得MQTT代理主题的完全访问权限。为此,请编辑`/opt/iotajson/config.js`文件,将config.mqtt部分更改为如下所示:
config.mqtt = {
host: "localhost",
port: 1883,
defaultKey: "1234",
username: "iota",
password: "iota",
};
最后一个操作是编辑`/etc/mosquitto/mosquitto.conf`,将aclfile和pwfile文件添加到配置中。完成的配置应该类似于以下内容:
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
#acl_file /etc/mosquitto/aclfile
password_file /etc/mosquitto/pwfile
include_dir /etc/mosquitto/conf.d
完成所有更改后,重启mosquitto:
service mosquitto restart
并重新运行IoT代理(您可以使用ps或netstat检查其PID并杀死它)。
测试
配置和设备配置
为了测试ACL文件,首先像前一章中那样配置配置和设备,但使用不同的设备,数据如下:
- 名称:DaisyPot
- 设备ID:sensor03
重要的是,您配置的配置使用的API密钥与ACL中声明的完全相同。
设备配置请求如下:
curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"devices": [
{
"device_id": "sensor03",
"entity_name": "DaisyPot",
"entity_type": "potSensor",
"attributes": [
{
"name": "humidity",
"type": "degrees"
},
{
"name": "happiness",
"type": "subjective"
}
]
}
]
}
' 'http://localhost:4041/iot/devices'
发送测量数据
现在我们可以尝试使用与第一种情况相同的命令发送新的测量数据:
mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}'
如果我们使用queryContext检查更改是否已传递到上下文代理,我们会发现这些测量数据已被忽略:
curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{
"entities": [
{
"isPattern": "false",
"id": "DaisyPot",
"type": "potSensor"
}
]
}' 'http://localhost:1026/v1/queryContext'
检查IoTAgent日志,您会看到请求完全被忽略了。问题在于,客户端试图以匿名方式发布到仅允许potteduser发布新消息的受ACL保护的主题。如果我们使用我们为用户生成的凭证再次尝试:
mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}' -u potteduser -P pottedpass
并再次执行queryContext操作,我们将获得更新后的实体:
{
"contextResponses": [
{
"contextElement": {
"type": "potSensor",
"isPattern": "false",
"id": "DaisyPot",
"attributes": [
{
"name": "happiness",
"type": "subjective",
"value": " "
},
{
"name": "humidity",
"type": "degrees",
"value": " "
}
]
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
这表明我们发送的测量信息已经正确地传输到了上下文代理。
安装
安装JSON物联网代理有三种方式:使用Git、RPM或Docker镜像。
使用GIT
要安装TT代理,只需克隆项目并安装依赖项:
git clone https://github.com/telefonicaid/iotagent-json.git
npm install
要启动物联网代理,从项目的根文件夹中输入:
bin/iotagent-json
使用RPM
项目包含一个脚本,用于生成可在Red Hat 6.5兼容的Linux发行版上安装的RPM。RPM依赖于Node.js 0.10版本,因此建议使用EPEL仓库。
要创建RPM,请在/rpm文件夹内执行以下脚本:
create-rpm.sh -v <versionNumber> -r <releaseNumber>
一旦RPM生成,可以使用以下命令安装:
yum localinstall --nogpg <nameOfTheRPM>.rpm
将作为linux服务安装,可以像往常一样使用service命令启动:
service iotaJSON start
使用Docker
Docker Hub上提供了一个Docker容器。它将使用config.js中定义的默认设置启动容器。
docker run -it --init fiware/iotagent-json
要使用您自己的配置,可以挂载本地配置文件:
docker run -it --init -v <path-to-configuration-file>:/opt/iotajson/new_config.js fiware/iotagent-json -- new_config.js
作为替代,也可以使用环境变量传递配置,如“使用环境变量配置”小节所述。
使用
要执行JSON物联网代理,只需从根文件夹执行以下命令:
bin/iotagentMqtt.js
这将在前台启动JSON物联网代理。使用标准Linux命令将其设置为在后台运行。
无参数启动时,物联网代理将预期在根文件夹中找到一个带有配置的config.js文件。可以传递一个参数,带有新配置文件的路径(相对于应用程序文件夹),以替代默认配置。
配置
概述
物联网代理的所有配置都存储在一个配置文件中(通常安装在根文件夹中)。
这个配置文件是一个JavaScript文件,包含三个配置章节:
- iota:此对象存储IoT代理北端口的配置,完全由IoT代理库管理。更多关于这些选项的信息可以在这里找到。
- mqtt:此对象存储特定于MQTT的配置。详细描述可在下一节中找到。
- http:此对象存储特定于HTTP的配置。详细描述可在下一节中找到。
还有一些全局配置选项:
- configRetrieval:此标志指示是否应使用来自库最新版本的双向插件处理传入IoT代理的通知,或使用JSON特定的配置检索机制(如用户手册中所述)。不允许同时使用这两种机制。
- config.defaultKey:设备缺乏提供的配置时使用的默认API密钥。
- config.defaultTransport:用于解析传入命令和懒惰属性的MQTT传输协议代码,以防无法为设备推断传输协议。
- compressTimestamp:此标志启用时间戳压缩机制,如用户手册中所述。
MQTT配置
以下是目前可用的MQTT配置选项:
- protocol:用于连接MQTT代理的协议(mqtt、mqtts、tcp、tls、ws、wss)。默认为mqtt
- host:MQTT代理的主机。
- port:MQTT代理监听的端口。
- defaultKey:在没有配置的情况下为设备配置的默认API密钥。
- ca:用于验证服务器证书的ca证书(可选)。默认信任Mozilla精心策划的知名CA。当使用此选项明确指定CA时,Mozilla的CA将被完全替换。
- cert:PEM格式的证书链,用于验证连接到MQTT代理(可选)。仅在使用mqtts、tls或wss作为连接协议时使用。
- key:PEM格式的可选私钥,用于客户端连接MQTT代理(可选)。仅在使用mqtts、tls或wss作为连接协议时使用。包含的CA列表将用于确定服务器是否获得授权。
- rejectUnauthorized:是否拒绝未经提供的CA授权的任何连接。此选项仅在使用mqtts、tls或wss协议时有效(默认为true)。如果使用自签名证书,请将其设置为false,但请注意,您将暴露于中间人攻击,因此这是不推荐用于生产环境的配置。
- username:标识IOTA对MQTT代理的用户名(可选)。
- password:如果提供了用户名,则使用的密码(可选)。
- qos:QoS级别:至多一次(0),至少一次(1),正好一次(2)。 (默认为0)。
- retain:保留标志(默认为false)。
- retries:MQTT连接错误重试次数(默认为5次)。
- retryTime:MQTT连接重试间隔时间(默认为5秒)。
- keepalive:客户端与MQTT代理之间保持连接打开的时间(默认为60秒)。如果您遇到断开连接问题,建议使用大于0的值(如本例所述)。
- avoidLeadingSlash:此标志设置代理是否发布带有斜杠(旧版本中的默认)或不带斜杠的主题。请参见讨论。
- clean:此标志默认为true,设置为false以接收离线时的QoS 1和2消息。
- clientId:标识mqtt代理中的客户端的字符串ID。默认使用由固定前缀iotajson_和随机后缀组成的字符串,即iotajson_43bf8a3a。
TLS选项(即ca、cert、key、rejectUnauthorized)直接与Node.js的tls模块支持的选项相关。
AMQP绑定配置
config.amqp部分的配置文件包含连接到AMQP代理所需的所有信息。接受以下属性:
- host:AMQP代理所在的主机。
- port:AMQP代理监听的端口
- username:标识IOTA对AMQP代理的用户名(可选)。
- password:如果提供了用户名,则使用的密码(可选)。
- exchange:AMQP代理中的交换机
- queue:AMQP代理中的队列
- durable:持久队列标志(默认为false)。
- retries:AMQP连接错误重试次数(默认为5次)。
- retryTime:AMQP连接重试间隔时间(默认为5秒)。
HTTP绑定配置
config.http部分的配置文件包含启动HTTP传输协议绑定的HTTP服务器所需的所有信息。接受以下选项:
- port:南端口,HTTP监听器将在此监听设备的信息。
- timeout:HTTP端点的HTTP超时时间(以毫秒为单位)。
- key:HTTPS绑定的私钥路径
- cert:HTTPS绑定的证书路径
使用环境变量配置
一些更常见的变量可以使用环境变量配置。覆盖config.iota集中的一般参数的变量在IoTA库配置手册中进行了描述。
与全局配置相关的变量在下表中描述。
环境变量 | 配置属性 |
---|---|
IOTA_CONFIG_RETRIEVAL | configRetrieval |
IOTA_DEFAULT_KEY | defaultKey |
IOTA_DEFAULT_TRANSPORT | defaultTransport |
与特定JSON绑定相关的变量在下表中描述。
环境变量 | 配置属性 |
---|---|
IOTA_MQTT_PROTOCOL | mqtt.protocol |
IOTA_MQTT_HOST | mqtt.host |
IOTA_MQTT_PORT | mqtt.port |
IOTA_MQTT_CA | mqtt.ca |
IOTA_MQTT_CERT | mqtt.cert |
IOTA_MQTT_KEY | mqtt.key |
IOTA_MQTT_REJECT_UNAUTHORIZED | mqtt.rejectUnauthorized |
IOTA_MQTT_USERNAME | mqtt.username |
IOTA_MQTT_PASSWORD | mqtt.password |
IOTA_MQTT_QOS | mqtt.qos |
IOTA_MQTT_RETAIN | mqtt.retain |
IOTA_MQTT_RETRIES | mqtt.retries |
IOTA_MQTT_RETRY_TIME | mqtt.retryTime |
IOTA_MQTT_KEEPALIVE | mqtt.keepalive |
IOTA_MQTT_AVOID_LEADING_SLASH | mqtt.avoidLeadingSlash |
IOTA_MQTT_CLEAN | mqtt.clean |
IOTA_MQTT_CLIENT_ID | mqtt.clientId |
IOTA_MQTT_DISABLED | mqtt.disabled |
IOTA_AMQP_HOST | amqp.host |
IOTA_AMQP_PORT | amqp.port |
IOTA_AMQP_USERNAME | amqp.username |
IOTA_AMQP_PASSWORD | amqp.password |
IOTA_AMQP_EXCHANGE | amqp.exchange |
IOTA_AMQP_QUEUE | amqp.queue |
IOTA_AMQP_DURABLE | amqp.durable |
IOTA_AMQP_RETRIES | amqp.retries |
IOTA_AMQP_RETRY_TIME | amqp.retryTime |
IOTA_AMQP_DISABLED | amqp.disabled |
IOTA_HTTP_HOST | http.host |
IOTA_HTTP_PORT | http.port |
IOTA_HTTP_TIMEOUT | http.timeout |
IOTA_HTTP_KEY | http.key |
IOTA_HTTP_CERT | http.cert |
(HTTP相关的环境变量将在即将推出的HTTP绑定中使用)
IOTA_MQTT_CA、IOTA_MQTT_CERT、IOTA_MQTT_KEY环境变量应提供文件名,其内容将用于配置属性。
高性能配置
Node.js是单线程的并使用非阻塞I/O,允许它扩展到数万个并发操作。然而,Node.js有一些薄弱点和漏洞,可能会导致基于Node.js的系统在遇到快速流量增长时表现出性能不足。
此外,了解运行node.js服务器的环境很重要,因为它有限制。主机上有两种类型的限制:硬件和软件。硬件限制很容易发现。您的应用程序可能正在消耗所有内存,并需要使用磁盘继续工作。通过升级您的物理或虚拟主机来增加更多内存似乎是正确的选择。
此外,Node.js应用程序也有软件内存限制(由V8强加),因此在执行服务时我们不能忘记这些限制。在64位环境中,您的应用程序默认运行在1 GB的V8限制下。如果您的应用程序在高流量场景中运行,您将需要更高的限制。其他参数也是如此。
这意味着我们需要对node.js的执行和系统配置进行一些更改:
Node.js标志
- --use-idle-notification 关闭使用空闲通知以减少内存占用。
- --expose-gc 使用expose-gc命令启用垃圾收集器的手动控制。在IoT代理的情况下,没有实现,因为需要在服务器代码中实现对垃圾收集器的调用,不过推荐的值是每30秒。
- --max-old-space-size=xxxx 在这种情况下,我们希望增加每个V8节点进程的堆内存限制,以便使用最大容量而不是64位机器上的默认1.4Gb(32位机器上为512Mb)。建议至少使用物理或虚拟实例总内存的一半。
用户软件限制
Linux内核提供了一些关于系统相关限制和最大值的配置。在有多个用户的分布式环境中,通常需要控制每个用户可用的资源。然而,当只有一个可用用户但这个用户由于高性能应用程序需要大量资源时,默认限制不适当,需要更改以满足高性能要求。这些限制包括最大文件句柄计数、最大文件锁计数、最大进程计数等。
您可以通过执行命令查看系统的限制:
bash
ulimit -a
您可以在limits.conf文件中定义相应的限制。此配置文件语法的描述适用于/etc/security/limits.conf文件和/etc/security/limits.d目录中的*.conf文件。您可以在limits.con - linux手册页中获取有关limits.conf的更多信息。建议更改的值如下:
core
核心文件大小的限制,以KB为单位,我们建议将硬类型和软类型都更改为无限。
* soft core unlimited
* hard core unlimited
data
最大数据大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。
* soft data unlimited
* hard data unlimited
fsize
最大文件大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。
* soft fsize unlimited
* hard fsize unlimited
memlock
最大锁定内存地址空间,以KB为单位,我们建议将硬类型和软类型都更改为无限。
* memlock unlimited
* memlock unlimited
nofile
最大打开文件描述符数量,我们建议将硬类型和软类型都更改为65535。
* soft nofile 65535
* hard nofile 65535
RSS
最大常驻集大小,以KB为单位(在Linux 2.4.30及更高版本中忽略),我们建议将硬类型和软类型都更改为无限。
* soft rss unlimited
* hard rss unlimited
stack
最大堆栈大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。
* soft stack unlimited
* hard stack unlimited
nproc
最大进程数,我们建议将硬类型和软类型都更改为无限。
* soft nproc unlimited
* hard nproc unlimited
您可以查看此文件夹中提供的limits.conf文件,了解所有提供的值。
配置内核参数
sysctl用于在运行时修改内核参数。我们计划修改相应的/etc/sysctl.conf文件。您可以在sysctl和sysctl.conf的相应手册页中获取更多信息。您可以使用命令sysctl -a搜索所有内核参数
fs.file-max
可分配的最大文件句柄数,推荐值为1000000。
fs.file-max = 1000000
fs.nr_open
可以打开的最大文件句柄数,推荐值为1000000。
fs.nr_open = 1000000
net.netfilter.nf_conntrack_max
连接跟踪表的大小。默认值是nf_conntrack_buckets值的4倍。
net.nf_conntrack_max = 1048576
有关任何其他内核参数的更多详细信息,请查看示例sysctl.conf文件。
打包
唯一允许的包类型是RPM。要执行打包脚本,系统中必须有RPM构建工具。
从项目的根文件夹创建RPM,使用以下命令:
cd rpm
./create-rpm.sh -v <version-number> -r <release-number>
其中<version-number>是您希望包具有的版本(x.y.z),<release-number>是依赖于先前安装的递增数字。
回复