EMQX规则链,配置数据转发后,payload里有中文就会是乱码,没有中文就是好的. 有什么解决办法?

环境信息

  • EMQX 版本:4.3.11

  • 操作系统及版本:Docker 镜像部署 emqx:4.3.11-alpine-amd64

  • 其他:MQTTX 客户端,或者emqx 的 dashboard 的 websock 工具发布消息

问题描述

  1. Docker 镜像部署 emqx:4.3.11-alpine-amd64

  2. 登入 http://localhost:18083/ ,配置规则链:
    规则 SQL:

    SELECT
      *
    FROM
    "t/#"
    

    响应动作 :类型: inspect
    并关联一个资源

  3. 通过MQTTX客户端,发送如下消息:

    {
      "msg":"中文"
    }
    

后端日志如下:

cdc-iot-emqx | [inspect]
cdc-iot-emqx |  Selected Data: #{clientid => <<"mqttx_d3a1f0b5">>,
cdc-iot-emqx |                          event => 'message.publish',
cdc-iot-emqx |                          flags => #{dup => false,retain => false},
cdc-iot-emqx |                          headers =>
cdc-iot-emqx |                              #{peerhost => <<"172.18.0.1">>,properties => #{},
cdc-iot-emqx |                                proto_ver => 4,protocol => mqtt,
cdc-iot-emqx |                                username => <<"u-emqx-client">>},
cdc-iot-emqx |                          id => <<"0005D9C42C7D2C22BCDA00000D750001">>,
cdc-iot-emqx |                          metadata => #{rule_id => <<"rule:235895">>},
cdc-iot-emqx |                          node => '7a9b273680fe@172.18.0.2',
cdc-iot-emqx |                          payload =>
cdc-iot-emqx |                              <<123,10,32,32,34,109,115,103,34,58,34,228,184,
cdc-iot-emqx |                                173,230,150,135,34,10,125>>,
cdc-iot-emqx |                          peerhost => <<"172.18.0.1">>,pub_props => #{},
cdc-iot-emqx |                          publish_received_at => 1646811466771,qos => 1,
cdc-iot-emqx |                          timestamp => 1646811466771,topic => <<"t/a">>,
cdc-iot-emqx |                          username => <<"u-emqx-client">>}
cdc-iot-emqx |  Envs: #{'__bindings__' =>
cdc-iot-emqx |                     #{'Id' => <<"inspect_1646638394825865500">>,
cdc-iot-emqx |                       'Params' => #{}},
cdc-iot-emqx |                 clientid => <<"mqttx_d3a1f0b5">>,event => 'message.publish',
cdc-iot-emqx |                 flags => #{dup => false,retain => false},
cdc-iot-emqx |                 headers =>
cdc-iot-emqx |                     #{peerhost => <<"172.18.0.1">>,properties => #{},
cdc-iot-emqx |                       proto_ver => 4,protocol => mqtt,
cdc-iot-emqx |                       username => <<"u-emqx-client">>},
cdc-iot-emqx |                 id => <<"0005D9C42C7D2C22BCDA00000D750001">>,
cdc-iot-emqx |                 metadata => #{rule_id => <<"rule:235895">>},
cdc-iot-emqx |                 node => '7a9b273680fe@172.18.0.2',
cdc-iot-emqx |                 payload =>
cdc-iot-emqx |                     <<123,10,32,32,34,109,115,103,34,58,34,228,184,173,230,150,
cdc-iot-emqx |                       135,34,10,125>>,
cdc-iot-emqx |                 peerhost => <<"172.18.0.1">>,pub_props => #{},
cdc-iot-emqx |                 publish_received_at => 1646811466771,qos => 1,
cdc-iot-emqx |                 timestamp => 1646811466771,topic => <<"t/a">>,
cdc-iot-emqx |                 username => <<"u-emqx-client">>}
cdc-iot-emqx |  Action Init Params: #{}

其中 payload => <<123,10,32,32,34,109,115,103,34,58,34,228,184, 173,230,150,135,34,10,125>>, 是乱码, 后续的响应动作无法进行payload数据选择,完成规定动作.

但客户端发送消息没有中文,就是好. 发送的消息如下:

{
  "msg":"chinese"
}

后端日志如下:

| [inspect]
cdc-iot-emqx |  Selected Data: #{clientid => <<"mqttx_d3a1f0b5">>,
cdc-iot-emqx |                          event => 'message.publish',
cdc-iot-emqx |                          flags => #{dup => false,retain => false},
cdc-iot-emqx |                          headers =>
cdc-iot-emqx |                              #{peerhost => <<"172.18.0.1">>,properties => #{},
cdc-iot-emqx |                                proto_ver => 4,protocol => mqtt,
cdc-iot-emqx |                                username => <<"u-emqx-client">>},
cdc-iot-emqx |                          id => <<"0005D9C446664B53BCDA00000D750002">>,
cdc-iot-emqx |                          metadata => #{rule_id => <<"rule:235895">>},
cdc-iot-emqx |                          node => '7a9b273680fe@172.18.0.2',
cdc-iot-emqx |                          payload => <<"{\n  \"msg\":\"chinese\"\n}">>,
cdc-iot-emqx |                          peerhost => <<"172.18.0.1">>,pub_props => #{},
cdc-iot-emqx |                          publish_received_at => 1646811901479,qos => 1,
cdc-iot-emqx |                          timestamp => 1646811901479,topic => <<"t/a">>,
cdc-iot-emqx |                          username => <<"u-emqx-client">>}
cdc-iot-emqx |  Envs: #{'__bindings__' =>
cdc-iot-emqx |                     #{'Id' => <<"inspect_1646638394825865500">>,
cdc-iot-emqx |                       'Params' => #{}},
cdc-iot-emqx |                 clientid => <<"mqttx_d3a1f0b5">>,event => 'message.publish',
cdc-iot-emqx |                 flags => #{dup => false,retain => false},
cdc-iot-emqx |                 headers =>
cdc-iot-emqx |                     #{peerhost => <<"172.18.0.1">>,properties => #{},
cdc-iot-emqx |                       proto_ver => 4,protocol => mqtt,
cdc-iot-emqx |                       username => <<"u-emqx-client">>},
cdc-iot-emqx |                 id => <<"0005D9C446664B53BCDA00000D750002">>,
cdc-iot-emqx |                 metadata => #{rule_id => <<"rule:235895">>},
cdc-iot-emqx |                 node => '7a9b273680fe@172.18.0.2',
cdc-iot-emqx |                 payload => <<"{\n  \"msg\":\"chinese\"\n}">>,
cdc-iot-emqx |                 peerhost => <<"172.18.0.1">>,pub_props => #{},
cdc-iot-emqx |                 publish_received_at => 1646811901479,qos => 1,
cdc-iot-emqx |                 timestamp => 1646811901479,topic => <<"t/a">>,
cdc-iot-emqx |                 username => <<"u-emqx-client">>}
cdc-iot-emqx |  Action Init Params: #{}

其中的payload: payload => <<"{\n \"msg\":\"chinese\"\n}">>,则是好的.


日志:

https://www.icode9.com/content-4-1278181.html
这篇文章是在代码里指定消息编码格式.
但是现在的问题是,用MQTTX发消息,规则链直接进行数据转发,没机会用代码指定编码.

消息编码是你发送时就应该做的,确保你的中文是 UTF8 编码,接收端也按照 UTF8 进行解码就行

我用的是MQTTX 图形客户端,没有找到设置中文utf-8编码的地方

用websock tool也是一样.

我用emqx broker 桥接,中间打印出来的payload是中文正确的,经过规则链后就乱码了.

能确认下,是不是规则链模块的bug?

在erlang里面utf8是正确的编码,

如果你用全英文的,资源能收到,那用中文也是能收到,有可能的原因是收到了没有做utf8解析,失败了导致你的资源端没有显示吧?

谢谢你的回复.
不过日志显示 在 selected data 已经是乱码了
cdc-iot-emqx | [inspect]
cdc-iot-emqx | Selected Data: #{clientid => <<“mqttx_d3a1f0b5”>>,
cdc-iot-emqx | event => ‘message.publish’,

cdc-iot-emqx | payload =>
cdc-iot-emqx | <<123,10,32,32,34,109,115,103,34,58,34,228,184,
cdc-iot-emqx | 173,230,150,135,34,10,125>>,

我配置的动作是直接取去payload的数据,插入数据库, 如:insert into test.t_mqtt_msg(ts, msgid, topic1, qos, payload) values (now, ‘${id}’, ‘${topic}’, ${qos}, ‘${payload.msg}’)

现在是跟随这个手册https://docs.emqx.com/zh/enterprise/v4.4/rule/backend_tdengine.html#%E9%80%9A%E8%BF%87%E5%8F%91%E9%80%81%E6%95%B0%E6%8D%AE%E5%88%B0-web-%E6%9C%8D%E5%8A%A1%E5%86%99%E5%85%A5
在测试这个用法时候,发现中文不能用.

请问,按照这个介绍,我如何让中文可以正常工作,插入中文数据到数据库.

谢谢

版本发布 | EMQX 企业版 changelog

Force utf8 json encoding by default #3287 by terry-xiaoyu · Pull Request #3299 · emqx/emqx (github.com)

这个在4.0.4上已修复Utf8的问题,你用的4.3.11应该没有这种问题才对。

可能出问题的地方:

  1. emqx没有响应你的动作,把请求发出去。
  2. 你的web服务器收到了utf8的请求,无法处理(可能是web服务器要支持utf8,需要做什么设置,比如mysql连接时就要支持encode为utf8.)

你可以在emqx上使用tcpdump抓包配合wireshark查看,看看数据有没有发过去web服务器上,格式是不是正确。

通过在 sql 规则使用 json_decode解决了该问题:
json_decode(payload) AS payload

多谢