Kuiper 正式成爲 EdgeX 規則引擎

概覽

EdgeX Geneva 版本中, EMQ X Kuiper - 基於 SQL 的輕量級流式數據處理軟件與 EdgeX 進行了集成。在進入這篇教程之前,讓我們先花一些時間來了解一些 Kuiper 的基本知識。EMQ X Kuiper 是 Golang 實現的輕量級物聯網邊緣分析、流式處理開源軟件,可以運行在各類資源受限的邊緣設備上。Kuiper 基於源 (Source)SQL (業務邏輯處理)目標 (Sink) 的方式來支持流式數據處理。

  • 源(Source):流式數據的數據源,例如來自於 MQTT 服務器 的數據。在 EdgeX 的場景下,數據源就是 EdgeX 消息總線(EdgeX message bus),可以是來自於 ZeroMQ 或者 MQTT 服務器;

  • SQL:SQL 是你流式數據處理指定業務邏輯的地方,Kuiper 提供了 SQL 語句可以對數據進行抽取、過濾和轉換;

  • 目標(Sink):目標用於將分析結果發送到特定的目標。例如,將分析結果發送到另外的 MQTT 服務器,或者一個 HTTP Rest 地址;

在這裏插入圖片描述

使用 Kuiper,一般需要完成以下三個步驟。

  • 創建流,就是你定義數據源的地方
  • 寫規則
    • 爲數據分析寫 SQL
    • 指定一個保存分析結果的目標
  • 部署,並且運行規則

該教程描述如何使用 Kuiper 處理來自於 EdgeX 消息總線的數據。

Kuiper EdgeX 集成

在不同的微服務之間,EdgeX 使用消息總線進行數據交換。它包含了一個抽象的消息總線接口,並分別實現了 ZeroMQ 與 MQTT,在不同的微服務之間信息交互的支持。Kuiper 和 EdgeX 的集成工作包含了以下三部分,

  • 擴展了一個 EdgeX 消息總線源,支持從 EdgeX 消息總線中接收數據

  • 爲了可以分析數據,Kuiper 需知道傳入的數據流的格式。一般來說,用戶最好在創建流的時候指定被分析的流數據的格式。如下所示,一個 demo 流包含了一個名爲 temperature 的字段。這與在關係型數據庫中創建表格定義的時候非常像。在創建了流定義以後,Kuiper 可以在編譯或者運行時對進入的數據進行類型檢查,相應錯誤也會報告給用戶。

    CREATE STREAM demo (temperature bigint) WITH (FORMAT="JSON"...)
    

    然而在 EdgeX 中,數據類型定義在 EdgeX Core contract Service 中已經指定,爲了提升使用體驗,用戶可以在創建流的時候不指定數據類型。Kuiper 源會在初始化規則的時候,從 Core contract Service 中獲取所有的 value descriptors 定義(所以如果有任何數據類型定義的變化,你需要重啓規則)。當接收到來自於消息總線的數據的時候,會根規則轉換爲相應的數據類型

  • 擴展支持 EdgeX 消息總線目標(sink),用於將處理結果寫回至 EdgeX 消息總線。用戶也可以選擇將分析結果發送到 Kuiper 之前已經支持的 RestAPI 接口等。

在這裏插入圖片描述

運行 EdgeX Docker 實例

打開 EdgeX develop-scripts 項目,並且下載 Geneva 版本的 Docker compose file,然後啓動所有的 EdgeX 容器。

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

所有的容器啓動完畢之後,請使用 docker ps 命令確定所有的容器已經正常啓動。

$ docker ps
CONTAINER ID        IMAGE                                                                  COMMAND                  CREATED             STATUS              PORTS                                                                                              NAMES
5618c93027a9        nexus3.edgexfoundry.org:10004/docker-device-virtual-go:master          "/device-virtual --p…"   37 minutes ago      Up 37 minutes       0.0.0.0:49990->49990/tcp                                                                           edgex-device-virtual
fabe6b9052f5        nexus3.edgexfoundry.org:10004/docker-edgex-ui-go:master                "./edgex-ui-server"      37 minutes ago      Up 37 minutes       0.0.0.0:4000->4000/tcp                                                                             edgex-ui-go
950135a7041d        emqx/kuiper:0.3.1                                                      "/usr/bin/docker-ent…"   37 minutes ago      Up 37 minutes        0.0.0.0:20498->20498/tcp, 9081/tcp, 0.0.0.0:48075->48075/tcp                                       edgex-kuiper
c49b0d6f9347        nexus3.edgexfoundry.org:10004/docker-support-scheduler-go:master       "/support-scheduler …"   37 minutes ago      Up 37 minutes       0.0.0.0:48085->48085/tcp                                                                           edgex-support-scheduler
4265dcc2bb48        nexus3.edgexfoundry.org:10004/docker-core-command-go:master            "/core-command -cp=c…"   37 minutes ago      Up 37 minutes       0.0.0.0:48082->48082/tcp                                                                           edgex-core-command
4667160e2f41        nexus3.edgexfoundry.org:10004/docker-app-service-configurable:master   "/app-service-config…"   37 minutes ago      Up 37 minutes       48095/tcp, 0.0.0.0:48100->48100/tcp                                                                edgex-app-service-configurable-rules
9bbfe95993f5        nexus3.edgexfoundry.org:10004/docker-core-metadata-go:master           "/core-metadata -cp=…"   37 minutes ago      Up 37 minutes       0.0.0.0:48081->48081/tcp, 48082/tcp                                                                edgex-core-metadata
2e342a3aae81        nexus3.edgexfoundry.org:10004/docker-support-notifications-go:master   "/support-notificati…"   37 minutes ago      Up 37 minutes       0.0.0.0:48060->48060/tcp                                                                           edgex-support-notifications
3cfc628e013a        nexus3.edgexfoundry.org:10004/docker-sys-mgmt-agent-go:master          "/sys-mgmt-agent -cp…"   37 minutes ago      Up 37 minutes       0.0.0.0:48090->48090/tcp                                                                           edgex-sys-mgmt-agent
f69e9c4d6cc8        nexus3.edgexfoundry.org:10004/docker-core-data-go:master               "/core-data -cp=cons…"   37 minutes ago      Up 37 minutes       0.0.0.0:5563->5563/tcp, 0.0.0.0:48080->48080/tcp                                                   edgex-core-data
9e5091928409        nexus3.edgexfoundry.org:10004/docker-support-logging-go:master         "/support-logging -c…"   37 minutes ago      Up 37 minutes       0.0.0.0:48061->48061/tcp                                                                           edgex-support-logging
74e8668f892c        redis:5.0.7-alpine                                                     "docker-entrypoint.s…"   37 minutes ago      Up 37 minutes       0.0.0.0:6379->6379/tcp                                                                             edgex-redis
9b341bb217f9        consul:1.3.1                                                           "docker-entrypoint.s…"   37 minutes ago      Up 37 minutes       0.0.0.0:8400->8400/tcp, 8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:8500->8500/tcp   edgex-core-consul
ed7ad5ae08b2        nexus3.edgexfoundry.org:10004/docker-edgex-volume:master               "/bin/sh -c '/usr/bi…"   37 minutes ago      Up 37 minutes                                                                                                          edgex-files

創建流

該步驟是創建一個可以從 EdgeX 消息總線進行數據消費的流。有兩種方法來支持管理流,你可以選擇喜歡的方式。

方式1: 使用 Rest API

請注意: EdgeX 中的 Kuiper Rest 接口使用48075端口,而不是缺省的9081端口。所以在 EdgeX 調用 Kuiper Rest 的時候,請將文檔中所有的 9081 替換爲 48075。

請將 $kuiper_server 替換爲本地運行的 Kuiper 實例的地址。

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

關於其它 API,請參考該文檔.

方式2: 使用 Kuiper 命令行

使用以下命令,進入運行中的 Kuiper docker 實例。

docker exec -it kuiper /bin/sh

使用以下命令,創建一個名爲 demo 的流定義.

bin/cli create stream demo'() WITH (FORMAT="JSON", TYPE="edgex")'

其它命令行,請參考該文檔


現在流已經創建好了,但是你可能好奇 Kuiper 是如何知道消息總線的地址和端口,因爲此類信息在 CREATE STREAM 並未指定。實際上這些信息是在配置文件 etc/sources/edgex.yaml 中指定的,你可以在命令行窗口中輸入 cat etc/sources/edgex.yaml 來查看文件的內容。如果你有不同的服務器、端口和服務的地址,請更新相應的配置。正如之前提到的,這些配置選項可以在容器啓動的時候進行重寫。

#Global Edgex configurations
default:
  protocol: tcp
  server: localhost
  port: 5566
  topic: events
  serviceServer: http://localhost:48080
.....  

更多關於配置文件的信息,請參考該文檔.

創建規則

讓我們創建一條規則,將分析結果發送至 MQTT 服務器,關於 MQTT 目標的相關配置,請參考這個鏈接。與創建流的過程類似,你可以選擇使用 REST 或者命令行來管理規則。

以下例子將選出所有 events 主題上所有的數據,分析結果將被

  • 發佈到公共的 MQTT 服務器 broker.emqx.io 的主題result 上;
  • 打印至日誌文件

選項1: 使用 Rest API

curl -X POST \
  http://$kuiper_server:9081/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":{}
    }
  ]
}

選項2: 使用 Kuiper 命令行

你可以使用任意編輯器來創建一條規則,將下列內容拷貝到編輯器中,並命名爲 rule.txt

{
  "sql": "SELECT * from demo",
  "actions": [
    {
      "mqtt": {
        "server": "tcp://broker.emqx.io:1883",
        "topic": "result",
        "clientId": "demo_001"
      }
    },
    {
      "log":{}
    }
  ]
}

在運行的容器中,執行以下命令。

# bin/cli create rule rule1 -f rule.txt
Connecting to 127.0.0.1:20498...
Creating a new rule from file rule.txt.
Rule rule1 was created successfully, please use 'cli getstatus rule rule1' command to get rule status.

如想將結果發送到別的目標,請參考 Kuiper 中支持的其它目標。你現在可以看一下在 log/stream.log中的日誌文件,查看規則的詳細信息。

time="2020-04-17T06:32:24Z" level=info msg="Serving kuiper (version - 0.3.1-4-g9e63fe1) on port 20498, and restful api on port 9081. \n" file="server.go:101"
time="2020-04-17T06:32:24Z" level=info msg="The connection to edgex messagebus is established successfully." file="edgex_source.go:95" rule=rule1
time="2020-04-17T06:32:24Z" level=info msg="Successfully subscribed to edgex messagebus topic events." file="edgex_source.go:104" rule=rule1
time="2020-04-17T06:32:24Z" level=info msg="The connection to server tcp://broker.emqx.io:1883 was established successfully" file="mqtt_sink.go:161" rule=rule1
time="2020-04-17T06:32:25Z" level=info msg="Get 24 of value descriptors from service." file="edgex_source.go:223"
time="2020-04-17T06:32:25Z" level=info msg="sink result for rule rule1: [{\"int32\":-697766590}]" file="log_sink.go:16" rule=rule1
time="2020-04-17T06:32:25Z" level=info msg="sink result for rule rule1: [{\"int8\":-47}]" file="log_sink.go:16" rule=rule1
time="2020-04-17T06:32:25Z" level=info msg="sink result for rule rule1: [{\"int16\":-318}]" file="log_sink.go:16" rule=rule1
time="2020-04-17T06:32:25Z" level=info msg="sink result for rule rule1: [{\"int64\":-8680421421398846880}]" file="log_sink.go:16" rule=rule1
time="2020-04-17T06:32:31Z" level=info msg="sink result for rule rule1: [{\"bool\":true}]" file="log_sink.go:16" rule=rule1

監控分析結果

因爲所有的分析結果都被髮布到tcp://broker.emqx.io:1883,你可以直接使用以下的 mosquitto_sub 命令來監聽結果,你也可以參考別的 MQTT 客戶端工具.

# mosquitto_sub -h broker.emqx.io -t result
[{"bool":true}]
[{"bool":false}]
[{"bool":true}]
[{"randomvalue_int16":3287}]
[{"float64":8.41326e+306}]
[{"randomvalue_int32":-1872949486}]
[{"randomvalue_int8":-53}]
[{"int64":-1829499332806053678}]
[{"int32":-1560624981}]
[{"int16":8991}]
[{"int8":-4}]
[{"bool":true}]
[{"bool":false}]
[{"float64":1.737076e+306}]
...

你也可以敲入以下的命令來查看規則執行的狀態。相關的查看規則狀態的 REST API 也有提供,請檢查相關文檔.

# bin/cli getstatus rule rule1
Connecting to 127.0.0.1:20498...
{
  "source_demo_0_records_in_total": 29,
  "source_demo_0_records_out_total": 29,
  "source_demo_0_exceptions_total": 0,
  "source_demo_0_process_latency_ms": 0,
  "source_demo_0_buffer_length": 0,
  "source_demo_0_last_invocation": "2020-04-17T10:30:09.294337",
  "op_preprocessor_demo_0_records_in_total": 29,
  "op_preprocessor_demo_0_records_out_total": 29,
  "op_preprocessor_demo_0_exceptions_total": 0,
  "op_preprocessor_demo_0_process_latency_ms": 0,
  "op_preprocessor_demo_0_buffer_length": 0,
  "op_preprocessor_demo_0_last_invocation": "2020-04-17T10:30:09.294355",
  "op_filter_0_records_in_total": 29,
  "op_filter_0_records_out_total": 21,
  "op_filter_0_exceptions_total": 0,
  "op_filter_0_process_latency_ms": 0,
  "op_filter_0_buffer_length": 0,
  "op_filter_0_last_invocation": "2020-04-17T10:30:09.294362",
  "op_project_0_records_in_total": 21,
  "op_project_0_records_out_total": 21,
  "op_project_0_exceptions_total": 0,
  "op_project_0_process_latency_ms": 0,
  "op_project_0_buffer_length": 0,
  "op_project_0_last_invocation": "2020-04-17T10:30:09.294382",
  "sink_sink_mqtt_0_records_in_total": 21,
  "sink_sink_mqtt_0_records_out_total": 21,
  "sink_sink_mqtt_0_exceptions_total": 0,
  "sink_sink_mqtt_0_process_latency_ms": 0,
  "sink_sink_mqtt_0_buffer_length": 1,
  "sink_sink_mqtt_0_last_invocation": "2020-04-17T10:30:09.294423"

總結

在本教程中,我們介紹了使用 EdgeX Kuiper 規則引擎的非常簡單的例子,如果使用過程中發現任何問題,請到 EdgeX,或者 Kuiper Github 中報問題。

更多練習

目前的規則沒有過濾發送給 Kuiper 的任何數據,那麼如何過濾數據呢?請使用刪除規則,然後試着更改一下 SQL 語句,完成更改後,重新部署規則。這時候如果監聽 MQTT 服務的結果主題,檢查一下相關的規則是否起作用?

擴展閱讀

如想了解更多的 EMQ X Kuiper 的信息,請參考以下資源。

本文作者: EMQ X
原文鏈接:https://www.emqx.io/cn/blog/kuiper-becomes-edgex-rule-engine
版權聲明: 本文爲 EMQ 原創,轉載請註明出處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章