Ekuiper-快速上手

介绍和背景

背景和目标

eKuiper 的主要目标是在边缘端提供一个流媒体软件框架(类似于 Apache Flink

Ekuiper 规则引擎概述

基本原理和设计思想

LF Edge eKuiper 是物联网数据分析和流式计算引擎。它是一个通用的边缘计算服务或中间件,为资源有限的边缘网关或设备而设计

eKuiper 采用 Go 语言编写,其架构如下图所示:

在这里插入图片描述

使用 eKuiper,一般需要完成以下三个步骤。

  • 创建流,就是你定义数据源的地方
  • 写规则
    • 为数据分析写 SQL
    • 指定一个保存分析结果的目标
  • 部署,并且运行规则

源从其他系统(如 EdgeX foundry)将数据输入到 eKuiper,这些系统被定义为流

应用优势

作为规则引擎,用户可以通过 REST-API 或 CLI 提交计算作业即规则。eKuiper 规则/SQL 解析器或图规则解析器将解析、规划和优化规则,使其成为一系列算子的流程,如果需要的话,算子可以利用流式运行时和状态存储

算子之间是松耦合的,通过 Go 通道进行异步通信。受益于 Go 的并发模型,规则运行时可以做到:

  • 以异步和非阻塞的方式进行通信。
  • 充分利用多核计算。
  • 算子层可伸缩。
  • 规则之间相互隔离。

这些有助于 eKuiper 实现低延迟和高吞吐量的数据处理。

应用案例和实际用途

快速上手

  1. 拉取镜像

https://hub.docker.com/r/lfedge/ekuiper/tags 拉取 eKuiper 的 Docker 镜像

  1. 设置 eKuiper 源为一个 MQTT 服务器。本例使用位于 tcp://broker.emqx.io:1883 的 MQTT 服务器, broker.emqx.io 是一个由 EMQ 提供的公有 MQTT 服务器
docker run -p 9081:9081 -d --name kuiper -e MQTT_SOURCE__DEFAULT__SERVER="tcp://broker.emqx.io:1883" lfedge/ekuiper:$tag
  1. 创建流(stream)- 流式数据的结构定义,类似于数据库中的表格类型定义。比如说要发送温度与湿度的数据到 broker.emqx.io,这些数据将会被在本地运行的 eKuiper docker 实例中处理
  • 以下的步骤将创建一个名字为 demo 的流,并且数据将会被发送至 devices/device_001/messages 主题,这里的 device_001 可以是别的设备,比如 device_002,所有的这些数据会被 demo 流订阅并处理
-- In host
docker exec -it kuiper /bin/sh

-- In docker instance
-- 创建流
bin/kuiper create stream demo '(temperature float, humidity bigint) WITH (FORMAT="JSON", DATASOURCE="devices/+/messages")'
Connecting to 127.0.0.1:20498...
Stream demo is created.

bin/kuiper query
Connecting to 127.0.0.1:20498...
kuiper > select * from demo where temperature > 30;
Query was submit successfully.
  1. 使用 MQTT X 来发布传感器数据到服务器 tcp://broker.emqx.io:1883的主题 devices/device_001/messages

当且仅当如果我们输入的 temperature > 30 时才会显示对应的输出,< 30 的数据就会被自动过滤掉
在这里插入图片描述

使用 Ekuiper 管理控制台

以一个实际例子来说明如何使用管理控制台对 eKuiper 节点进行操作与管理。文中将订阅来自于 MQTT 服务器的数据,通过 eKuiper 写好的规则,经过处理后发送到指定的文件中,演示说明如下:

  • 通过管理控制台创建一个 eKuiper 节点
  • 创建一个流,用于订阅 MQTT 服务器中的数据,本例演示订阅 MQTT 服务器,相关信息如下所示。
    • 地址为:tcp://broker.emqx.io:1883
    • 主题为:devices/device_001/messages
    • 数据为:{"temperature": 40, "humidity" : 20}
  • 创建一个规则,用于计算订阅到的数据,并将数据写入目标 (sink) 端「本例演示将订阅到的消息写入到文件中」
  • eKuiper 目前已经支持多种源和目标。用户只需安装相对应的插件,便能实现对应的功能「本例的源为 MQTT 源是内置支持,无需安装;目标为文件 (file)」

Ekuiper-manager 架构设计

  • UI 端:可视化的界面,便于用户操作
  • Kuiper-manager:管理控制台,本质是一个反向 HTTP 代理服务,提供用户管理,权限验证等服务。既可以部署在云端,也可以部署在边缘端
  • eKuiper 实例,被管理的 eKuiper 节点实例,eKuiper-manager 可以同时管理多个 eKuiper 节点
    在这里插入图片描述

使用 docker-compose 进行安装

services:
    manager:
       image: emqx/ekuiper-manager
       container_name: ekuiper-manager
       ports:
       - "9082:9082"
       restart: unless-stopped
       environment:
         # setting default eKuiper service, works since 1.8.0
         DEFAULT_EKUIPER_ENDPOINT: "http://10.37.18.97:9081"
    ekuiper:
       image: lfedge/ekuiper
       ports:
         - "9081:9081"
         - "10.37.18.97:20498:20498"
       container_name: ekuiper
       hostname: ekuiper
       restart: unless-stopped
       user: root
       volumes:
         - /tmp/data:/kuiper/data
         - /tmp/log:/kuiper/log
       environment:
         MQTT_SOURCE__DEFAULT__SERVER: "tcp://broker.emqx.io:1883"
         KUIPER__BASIC__CONSOLELOG: "true"
         KUIPER__BASIC__IGNORECASE: "false"

注意上面高亮的地方换成自己部署 ekuiper 的主机地址

性能和扩展性

与EdgeX集成

运行容器

下载 docker-compose 文件 edgex-compose/docker-compose-no-secty.yml at main · edgexfoundry/edgex-compose

启动docker-compose容器

docker-compose -f ./docker-compose-no-secty.yml up -d --build

查看容器状态

docker-compose -p edgex stats

在这里插入图片描述

edgex 默认使用 redis 作为消息总线,我们进入到 redis 容器

订阅redis的所有channel查看消费的消息
PSUBSCRIBE edgex.events.*
输出结果如下;4) 即为我们设备产生的数据

1) "pmessage"
2) "edgex.events.*"
3) "edgex.events.device.device-virtual.Random-Float-Device.Random-Float-Device.Float64"
4) "{\"apiVersion\":\"v3\",\"receivedTopic\":\"\",\"correlationID\":\"a86e1157-4212-4a3a-8829-7dcd7c479f11\",\"requestID\":\"\",\"errorCode\":0,\"payload\":\"eyJhcGlWZXJzaW9uIjoidjMiLCJyZXF1ZXN0SWQiOiJiM2RlZTM0YS0yYWMxLTQ0OTQtYjVjMy1hZTI3MGQ5YTA4MDUiLCJldmVudCI6eyJhcGlWZXJzaW9uIjoidjMiLCJpZCI6IjA4Yjk3Zjg3LTY5NjEtNDYzZi1hYzg0LTRjMTBkM2NjZmM5NiIsImRldmljZU5hbWUiOiJSYW5kb20tRmxvYXQtRGV2aWNlIiwicHJvZmlsZU5hbWUiOiJSYW5kb20tRmxvYXQtRGV2aWNlIiwic291cmNlTmFtZSI6IkZsb2F0NjQiLCJvcmlnaW4iOjE3MTY3MDgxNzM5MzAyMDMxMzIsInJlYWRpbmdzIjpbeyJpZCI6ImJiNjI5Y2JmLWI5ZDktNGRhOS1iZDY1LWJkZGNmNzA1Yzk3NSIsIm9yaWdpbiI6MTcxNjcwODE3MzkzMDIwMzEzMiwiZGV2aWNlTmFtZSI6IlJhbmRvbS1GbG9hdC1EZXZpY2UiLCJyZXNvdXJjZU5hbWUiOiJGbG9hdDY0IiwicHJvZmlsZU5hbWUiOiJSYW5kb20tRmxvYXQtRGV2aWNlIiwidmFsdWVUeXBlIjoiRmxvYXQ2NCIsInZhbHVlIjoiLTcuMzg3MzI0ZSszMDYifV19fQ==\",\"contentType\":\"application/json\"}"

1) "pmessage"
2) "edgex.events.*"
3) "edgex.events.device.device-virtual.Random-Boolean-Device.Random-Boolean-Device.Bool"
4) "{\"apiVersion\":\"v3\",\"receivedTopic\":\"\",\"correlationID\":\"592546ca-85ed-48f0-ac4d-78a2ea32799d\",\"requestID\":\"\",\"errorCode\":0,\"payload\":\"eyJhcGlWZXJzaW9uIjoidjMiLCJyZXF1ZXN0SWQiOiI0ODNmMTViMi05MmRhLTRiZDMtOTg1My0yZDRjYWQwMjIzNWIiLCJldmVudCI6eyJhcGlWZXJzaW9uIjoidjMiLCJpZCI6ImMxZDU3MTFkLTc3MDMtNDJhYy1hNzhmLTFiNzIwNTI3ZDAwOSIsImRldmljZU5hbWUiOiJSYW5kb20tQm9vbGVhbi1EZXZpY2UiLCJwcm9maWxlTmFtZSI6IlJhbmRvbS1Cb29sZWFuLURldmljZSIsInNvdXJjZU5hbWUiOiJCb29sIiwib3JpZ2luIjoxNzE2NzA4MTczOTM3MDgwNjMwLCJyZWFkaW5ncyI6W3siaWQiOiJkODg2M2U0ZC02YmY1LTRhMmItYTkwNC03NDc4Y2IwMGEyZWYiLCJvcmlnaW4iOjE3MTY3MDgxNzM5MzcwODA2MzAsImRldmljZU5hbWUiOiJSYW5kb20tQm9vbGVhbi1EZXZpY2UiLCJyZXNvdXJjZU5hbWUiOiJCb29sIiwicHJvZmlsZU5hbWUiOiJSYW5kb20tQm9vbGVhbi1EZXZpY2UiLCJ2YWx1ZVR5cGUiOiJCb29sIiwidmFsdWUiOiJmYWxzZSJ9XX19\",\"contentType\":\"application/json\"}"

仔细观察上面的事件以及实际的设备的名称

访问 curl http://127.0.0.1:59882/api/v2/device/all 获取到下面的设备所有信息

在这里插入图片描述
在这里插入图片描述

可以发现事件的后缀就是对应着设备的 deviceName

对 payload 进行 base64 反编码可以得出如下结果

{
  "apiVersion": "v3",
  "requestId": "b3dee34a-2ac1-4494-b5c3-ae270d9a0805",
  "event": {
    "apiVersion": "v3",
    "id": "08b97f87-6961-463f-ac84-4c10d3ccfc96",
    "deviceName": "Random-Float-Device",
    "profileName": "Random-Float-Device",
    "sourceName": "Float64",
    "origin": 1716708173930203132,
    "readings": [
      {
        "id": "bb629cbf-b9d9-4da9-bd65-bddcf705c975",
        "origin": 1716708173930203132,
        "deviceName": "Random-Float-Device",
        "resourceName": "Float64",
        "profileName": "Random-Float-Device",
        "valueType": "Float64",
        "value": "-7.387324e+306"
      }
    ]
  }
}
{
  "apiVersion": "v3",
  "requestId": "483f15b2-92da-4bd3-9853-2d4cad02235b",
  "event": {
    "apiVersion": "v3",
    "id": "c1d5711d-7703-42ac-a78f-1b720527d009",
    "deviceName": "Random-Boolean-Device",
    "profileName": "Random-Boolean-Device",
    "sourceName": "Bool",
    "origin": 1716708173937080630,
    "readings": [
      {
        "id": "d8863e4d-6bf5-4a2b-a904-7478cb00a2ef",
        "origin": 1716708173937080630,
        "deviceName": "Random-Boolean-Device",
        "resourceName": "Bool",
        "profileName": "Random-Boolean-Device",
        "valueType": "Bool",
        "value": "false"
      }
    ]
  }
}

获取 ekuiper 的容器 ip

➜  ~ docker inspect 503cf110e559 | grep -i ipaddr
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.24.0.12",

案例一:直接上报设备产生的数据

创建流

请将 $eKuiper_server 替换为本地运行的 eKuiper 实例的地址

实际上上面docker-compose里面都做了端口映射,可直接将 eKuiper_server 定义成 127.0.0.1 即可

在这里插入图片描述

curl -X POST \
  http://$eKuiper_server:59720/streams \
  -H 'Content-Type: application/json' \
  -d '{
  "sql": "create stream demo() WITH (FORMAT=\"JSON\", TYPE=\"edgex\")"
}'

进入到 ekuiper 里面查看创建的流 stream

/kuiper/bin $ ./kuiper show streams
Connecting to 127.0.0.1:20498...
demo

现在流已经创建好了,但是你可能好奇 eKuiper 是如何知道消息总线的地址和端口,因为此类信息在 CREATE STREAM 并未指定。实际上这些信息是在配置文件 etc/sources/edgex.yaml 中指定的,你可以在命令行窗口中输入 cat etc/sources/edgex.yaml 来查看文件的内容。如果你有不同的服务器、端口和服务的地址,请更新相应的配置。正如之前提到的,这些配置选项可以在容器启动的时候进行重写

/kuiper/etc/sources $ cat edgex.yaml
application_conf:
  port: 5571
  protocol: tcp
  server: localhost
  topic: application
default:
  port: 6379
  protocol: redis
  server: edgex-redis
  topic: edgex/rules-events
  type: redis
mqtt_conf:
  optional:
    ClientId: client1
  port: 1883
  protocol: tcp
  server: 127.0.0.1
  topic: events
  type: mqtt
创建规则

我们创建一条规则,将分析结果发送至 MQTT 服务器

以下例子将选出所有 events 主题上所有的数据,分析结果将被

  • 发布到公共的 MQTT 服务器 broker.emqx.io 的主题 result 上;
  • 打印至日志文件
curl -X POST \
  http://$eKuiper_server:59720/rules \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "rule1",
  "sql": "SELECT * FROM demo",
  "actions": [
    {
      "mqtt": {
        "server": "tcp://broker.emqx.io:1883",
        "topic": "result",
        "clientId": "demo_001"
      }
    },
    {
      "log":{}
    }
  ]
}'

查看规则

/kuiper/bin $ ./kuiper show rules
Connecting to 127.0.0.1:20498...
[
  {
    "id": "rule1",
    "status": "Running"
  }
]

/kuiper/bin $ ./kuiper describe rule rule1
Connecting to 127.0.0.1:20498...
{
  "triggered": true,
  "id": "rule1",
  "sql": "SELECT * FROM demo",
  "actions": [
    {
      "mqtt": {
        "clientId": "demo_001",
        "server": "tcp://broker.emqx.io:1883",    定义的设备数据上报地址
        "topic": "result"                         定义的MQTT的topic
      }
    },
    {
      "log": {}
    }
  ],
  "options": {
    "isEventTime": false,
    "lateTolerance": 1000,
    "concurrency": 1,
    "bufferLength": 1024,
    "sendMetaToSink": false,
    "sendError": true,
    "qos": 0,
    "checkpointInterval": 300000
  }
}

docker logs 查看 ekuiper 的日志信息
在这里插入图片描述

可观察到相关的数据

监控分析结果

上面我们定义的设备的数据上报地址为 mqtt 的地址

使用 mosquitto_sub 进行 MQTT 消息订阅就能看到我们设备经过 ekuiper 发送到 MQTT 的消息

➜  ~ mosquitto_sub -h broker.emqx.io -t result
[{"Float64":1.658207e+307}]
[{"Float32":-8.653245654362261e+37}]
[{"Int8":-69}]
[{"Int64":-5707572273003489628}]
[{"Int32":-1320144333}]
[{"Int16":11173}]
[{"Bool":true}]
[{"Uint8":68}]
[{"Uint16":63161}]
[{"Uint32":3342819840}]
[{"Uint64":11984961581557470757}]
[{"Bool":true}]

可以看到我们这里显示的消息类型其实有所有设备的消息,这是因为我们规则引擎里面定义了对应的 topic 为 edgex 的 "edgex/events/#"

EdgeX v2 消息总线具有多级主题,以便消费者可以高效地按主题过滤消息。 参考docs.edgexfoundry.org

如果我们只想规只考虑来自 Random-Boolean-Device 的数据,我们可以修改规则引擎的 docker compose 文件来更改主题并将消息类型修改为 request,如下所示

...
  ...
  rulesengine:
    ...
    environment:
      ...
      EDGEX__DEFAULT__TOPIC: edgex/events/#/Random-Boolean-Device/#
      EDGEX__DEFAULT__MESSAGETYPE: request
      ...

上面的 MESSAGETYPE 代表 EdgeX 的消息类型
在这里插入图片描述

再次订阅消息就只会有 bool 类型的消息

➜  ~ mosquitto_sub -h broker.emqx.io -t result
[{"Bool":true}]
[{"Bool":false}]
[{"Bool":false}]
[{"Bool":true}]
  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值