OpenEdge

OpenEdge由主程序和应用模块构成,通过加载应用配置来运行模块,目前支持两种运行模式,分别是docker容器模式和native进程模式。

Docker容器模式结构图:

Docker容器模式结构图

Native进程模式结构图:

Native进程模式结构图

主程序(master)

主程序负责所有模块的管理、云同步等,由模块引擎、云代理和API构成。

模块引擎(engine)

模块引擎负责模块的启动、停止、重启、监听和守护,目前支持docker容器模式和native进程模式。

模块引擎从工作目录的var/db/openedge/module/module.yml配置中加载模块列表,并以列表的顺序逐个启动模块。模块引擎会为每个模块启动一个守护协程对模块状态进行监听,如果模块异常退出,会根据模块的Restart Policy配置项执行重启或退出。主程序关闭后模块引擎会按照列表的逆序逐个关闭模块。

提示:工作目录可在OpenEdge启动时通过-w指定,默认为OpenEdge的可执行文件所在目录的上一级目录。

Docker容器模式下,模块通过docker client启动entry指定的模块镜像,并自动加入自定义网络(openedge)中,由于docker自带了DNS server,模块间可通过模块名进行互相通讯。另外模块可通过expose配置项来向外暴露端口;通过resources配置项限制模块可使用的资源,目前支持CPU、内存和进程数的限制。配置参考

Docker容器模式下,模块在容器中的工作目录是根目录:/,配置路径是:/etc/openedge/module.yml,资源读取目录是:/var/db/openedge/module/<模块名>,持久化数据输出目录是:/var/db/openedge/volume/<模块名>,日志输出目录是:/var/log/openedge/<模块名>。具体的映射如下:

- /var/db/openedge/module//module.yml:/etc/openedge/module.yml- /var/db/openedge/module/:/var/db/openedge/module/- /var/db/openedge/volume/- /var/log/openedge/:/var/log/openedge/

提示:应用模块在云端被修改后mark值会发生变化,和git的修订版本类似。

Native进程模式下,通过syscall启动entry指定模块可执行文件,模块间可通过localhost(127.0.0.1)进行互相通讯,不支持资源隔离和资源限制

云代理(agent)

云代理负责和云端管理套件通讯,走MQTT和HTTPS通道,MQTT强制SSL/TLS证书双向认证,HTTPS强制SSL/TLS证书单向认证。配置参考cloud

OpenEdge启动和热加载(reload)完成后会通过云代理上报一次设备信息,目前上报的内容如下:

- go_version:OpenEdge主程序的Golang版本- bin_version:OpenEdge主程序的版本- conf_version:OpenEdge主程序加载应用的版本- reload_error:OpenEdge主程序加载应用的报错信息,如果有的话- os:设备的系统,比如:linux、windows、darwin- bit:设备CPU位数,比如:32、64- arch:设备CPU架构,比如:amd64- gpu\:设备的第n个GPU的型号- gpu\_mem_total:设备的第n个GPU的显存总容量- gpu\_mem_free:设备的第n个GPU的显存剩余容量- mem_total:设备的内存总容量- mem_free:设备的内存剩余容量- swap_total:设备的交换空间总容量- swap_free:设备的交换空间剩余容量

云代理接收到云端管理套件的应用下发指令后,OpenEdge开始执行热加载,流程如下图:

热加载流程

注意:目前热加载采用全量更新的方式,既先停止所有老应用模块再启动所有新应用模块,因此模块提供的服务会中断。另外解压新应用包会直接覆盖老应用的文件,多余的老应用文件不会被清理,后续会考虑加入清理逻辑。

提示:如果设备无法连接外网或者脱离云端管理,可移除cloud配置项,离线运行。

API(api)

OpenEdge主程序会暴露一组HTTP API,目前支持获取空闲端口,模块的启动和停止。API server在linux系统下默认采用unix domain socket,工作目录下的var/openedge.sock;其他环境采用TCP,默认监听tcp://127.0.0.1:50050。开发者可以通过api配置项修改监听的地址。为了方便管理,我们对模块做了一个划分,从var/db/openedge/module/module.yml中加载的模块称为常驻模块,通过API启动的模块称为临时模块,临时模块遵循谁启动谁负责停止的原则。OpenEdge退出时,会先逆序停止所有常驻模块,常驻模块停止过程中也会调用API来停止其启动的模块,最后如果还有遗漏的临时模块,会随机全部停止。访问API需要提供账号和密码,设置如下两个请求头:

- x-iot-edge-username:账号名称,即常驻模块名- x-iot-edge-password:账号密码,即常驻模块的token,使用module.GetEnv(module.EnvOpenEdgeModuleToken)从环境变量中获取,OpenEdge主程序启动时会为每个常驻模块生成临时的token。

官方提供的函数计算模块会调用这个API来启停函数实例(runtime)模块,函数计算模块停止时需要负责将其启动的临时模块全部停掉。

环境变量(env)

OpenEdge目前会给模块设置如下几个系统环境变量:

- OPENEDGE_HOST_OS:OpenEdge所在设备(宿主机)的系统类型- OPENEDGE_MASTER_API:OpenEdge主程序的API地址- OPENEDGE_MODULE_MODE:OpenEdge主程序的运行模式- OPENEDGE_MODULE_TOKEN:OpenEdge主程序分配给常驻模块的临时token,可作为常驻模块访问主程序API的密码

官方提供的函数计算模块就是通过读取OPENEDGE_MASTER_API来连接OpenEdge主程序的,比如linux系统下OPENEDGE_MASTER_API默认是unix://var/openedge.sock;其他系统的docker容器中OPENEDGE_MASTER_API默认是tcp://host.docker.internal:50050;其他系统的native模式下OPENEDGE_MASTER_API默认是tcp://127.0.0.1:50050。

注意:应用中配置的环境变量如果和上述系统环境变量相同会被覆盖。

官方模块

目前官方提供了若干模块,用于满足部分常见的应用场景,当然开发者也可以开发自己的模块,只要符合自定义模块的加载要求。

Hub模块(openedge-hub)

Hub模块是一个单机版的消息订阅和发布中心,采用MQTT 3.1.1协议,结构图如下:

Hub模块结构图

目前支持4种接入方式:tcp、ssl(tcp+ssl)、ws(websocket)及wss(websocket+ssl),MQTT协议支持度如下:

- 支持connect、disconnect、subscribe、publish、unsubscribe、ping等功能- 支持QoS等级0和1的消息发布和订阅- 支持retain、will message、clean session- 支持订阅含有"+"、"#"等通配符的主题- 支持符合约定的clientid和payload的校验- 暂时不支持发布和订阅以"$"为前缀的主题- 暂时不支持client的keep alive特性以及QoS等级2的发布和订阅

注意

- 发布和订阅主题中含有的分隔符"/"最多不超过8个,主题名称长度最大不超过255个字符- 消息报文默认最大长度位32k,可支持的最大长度为268,435,455(byte),不到256m,可通过message配置项进行修改- clientid支持大小写字母、数字、下划线、连字符(减号)和空字符(空字符表示client为临时连接,强制cleansession=true), 最大长度不超过128个字符- 消息的QoS只能降不能升,比如原消息的QoS为0时,即使订阅QoS为1,消息仍然以QoS为0的等级发送。

Hub模块支持简单的主题路由,比如订阅主题为t的消息并以新主题t/topic发布回broker。参考配置

函数计算模块(openedge-function)

函数计算提供基于MQTT消息机制,弹性、高可用、扩展性好、响应快的的计算能力,并且兼容百度云-函数计算CFC。函数通过一个或多个具体的实例执行,每个实例都是一个独立的进程,现采用grpc server运行函数实例。所有函数实例由实例池(pool)负责管理生命周期,支持自动扩容和缩容。结构图如下:

函数计算模块结构图

注意: 如果函数执行错误,函数计算会返回如下格式的消息,供后续处理。其中packet是函数输入的消息(被处理的消息),不是函数返回的消息。

  1. {
  2. "errorMessage": "rpc error: code = Unknown desc = Exception calling application",
  3. "errorType": "*errors.Err",
  4. "packet": {
  5. "Message": {
  6. "Topic": "t",
  7. "Payload": "eyJpZCI6MSwiZGV2aWNlIjoiMTExIn0=",
  8. "QOS": 0,
  9. "Retain": false
  10. },
  11. "Dup": false,
  12. "ID": 0
  13. }
  14. }

函数计算python27 runtime模块(openedge-function-runtime-python27)

Python函数与百度云-函数计算CFC类似,用户通过编写的自己的函数来处理消息,可进行消息的过滤、转换和转发等,使用非常灵活。

Python函数的输入输出可以是JSON格式也可以是二进制形式。消息payload在作为参数传给函数前会尝试一次JSON解码(json.loads(payload)),如果成功则传入字典(dict)类型,失败则传入原二进制数据。

Python函数支持读取环境变量,比如os.environ['PATH']。

Python函数支持读取上下文,比如context['functionName']。

Python函数实现举例:

  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3. """
  4. module to say hi
  5. """
  6. def handler(event, context):
  7. """
  8. function handler
  9. """
  10. event['functionName'] = context['functionName']
  11. event['functionInvokeID'] = context['functionInvokeID']
  12. event['functionInstanceID'] = context['functionInstanceID']
  13. event['messageQOS'] = context['messageQOS']
  14. event['messageTopic'] = context['messageTopic']
  15. event['sayhi'] = '你好,世界!'
  16. return event

提示:Native进程模式下,若要运行本代码库提供的sayhi.py,需要自行安装python2.7,且需要基于python2.7安装protobuf3、grpcio、pyyaml(采用pip安装即可,pip install grpcio protobuf pyyaml)。

此外,对于Native进程模式python脚本运行环境的构建,推荐通过virtualenv构建虚拟环境,并在此基础上安装相关依赖,相关步骤如下:



  1. # install virtualenv via pip
    [sudo] pip install virtualenv
    # test your installation
    virtualenv version
    # build workdir run environment
    cd /path/to/native/workdir
    virtualenv native/workdir
    # install requirements
    source bin/activate # activate virtualenv
    pip install grpcio protobuf pyyaml # install grpc, protobuf3, yaml via pip
    # test native mode
    bin/openedge # run openedge under native mode
    deactivate # deactivate virtualenv


远程通讯模块(openedge-remote-mqtt)

远程通讯模块目前支持MQTT协议,可桥接两个MQTT server,用于订阅一个server的消息并转发给另一个server。目前支持配置多路消息转发,可配置多个remote和hub同时进行消息同步,结构图如下:

远程通讯模块结构图

如上图示,这里,OpenEdge本地Hub模块与远程云端Hub平台之间通过OpenEdge远程通讯模块(openedge-remote-mqtt)实现消息的转发、同步,进一步地,通过在两端接入MQTT Client即可实现“端云协同式”的消息转发与传递。

最后更新于 2018-12-28 10:23:09

原文: https://openedge.tech/docs/overview/OpenEdge-design