插件

EMQX 支持通过插件扩展自定义业务逻辑,或通过插件的协议扩展接口实现其他协议适配,本章节将指导您进行插件的开发。

插件开发和运行基本流程如下:

  • 通过 EMQX 提供的插件模板生成对应的插件 tar.gz 包。
  • 通过 Dashboard 或 CLI 安装插件包,
  • 通过 Dashboard 或 CLI 启动/停止/卸载插件。

前置准备:

插件开发

EMQX 提供了一个基础的插件模板 emqx-plugin-template插件 - 图1 (opens new window),你可以基于它开始开发您的插件。此处以访问控制插件为例,指导您一步步开发自己的插件:

1. 下载插件模板 emqx-plugin-template

  1. git clone https://github.com/emqx/emqx-plugin-template

查看目录结构,这是一个标准的 Erlang Application 应用。

  1. $ ls
  2. LICENSE _build get-rebar3
  3. Makefile check-vsn.sh priv
  4. README.md rebar.config src

2. 测试编译环境

不改任何代码,直接运行 make rel 测试是否可以正常编译打包插件。

第一次编译过程较长,因为它依赖于 EMQX 主项目(方便插件直接使用主项目的各种函数),需要下载依赖,并编译主项目。

编译环境请参照 源码编译安装 EMQX 配置。 {% endemqxce %}

3. 挂载钩子函数

查看目录结构:

  1. > tree src/
  2. src/
  3. ├── emqx_cli_demo.erl
  4. ├── emqx_plugin_template.app.src
  5. ├── emqx_plugin_template.erl
  6. ├── emqx_plugin_template_app.erl
  7. └── emqx_plugin_template_sup.erl

emqx_plugins_template_app.erl 是应用启动入口。你可以在这里定义需要启动的监控树,并挂载 EMQX 的钩子函数。此模板插件中注册了所有的钩子函数,使用前请删除不需要的钩子

此示例中只需要使用到认证和授权 2 个钩子,可以修改emqx_plugins_template:load/1为:

  1. load(Env) ->
  2. emqx_hooks:add('client.authenticate', {?MODULE, on_client_authenticate, [Env]}, ?HP_HIGHEST),
  3. emqx_hooks:add('client.authorize', {?MODULE, on_client_authorize, [Env]}, ?HP_HIGHEST),
  4. ok.

即:当客户端认证时执行我们自定义的 on_client_authenticate/3 函数,当客户端做授权控制检查时执行on_client_authorize/5函数。

由于 EMQX 内部功能也会挂载钩子函数,并且其他插件也会挂载相同的钩子函数,所以我们必须在挂载钩子时指定它的执行的顺序。?HP_HIGHEST 即指定当前的钩子函数最高优先级,优先级越高越先被执行。

4. 编写自定义访问控制代码

  1. %% 只允许 clientid [A-Za-z0-9_] 的客户端连接。
  2. on_client_authenticate(_ClientInfo = #{clientid := ClientId}, Result, _Env) ->
  3. case re:run(ClientId, "^[A-Za-z0-9_]+$", [{capture, none}]) of
  4. match -> {ok, Result};
  5. nomatch -> {stop, {error, banned}}
  6. end.
  7. %% 只允许订阅 /room/{clientid} 的主题,但是可以发送消息给任意主题。
  8. on_client_authorize(_ClientInfo = #{clientid := ClientId}, subscribe, Topic, Result, _Env) ->
  9. case emqx_topic:match(Topic, <<"/room/", ClientId/binary>>) of
  10. true -> {ok, Result};
  11. false -> stop
  12. end;
  13. on_client_authorize(_ClientInfo, _Pub, _Topic, Result, _Env) -> {ok, Result}.

通过以上 2 个钩子函数,我们只让 clientid 格式符合规范的客户端登录。并且只能订阅 /room/{clientid} 主题,这样就实现了一个简单的聊天室功能:客户端可以发消息给任意客户端,但每个客户端只能订阅与自己相关的主题。

提示

  1. 需要先把配置中的 authorization.no_match 设置为 deny,默认拒绝未经授权的操作。
  2. 要设置同样的订阅规则,无需开发插件,可以通过 EMQX 内置的 基于文件进行授权 来实现。

5. 打包插件

通过 rebar.config 中修改插件的版本信息:

  1. {relx, [ {release, {emqx_plugin_template, "5.0.0-rc.3"}, [emqx_plugin_template, map_sets]}
  2. , {dev_mode, false}
  3. , {include_erts, false}
  4. ]}.
  5. %% Additional info of the plugin
  6. {emqx_plugrel,
  7. [ {authors, ["EMQX Team"]}
  8. , {builder,
  9. [ {name, "EMQX Team"}
  10. , {contact, "emqx-support@emqx.io"}
  11. , {website, "www.emqx.com"}
  12. ]}
  13. , {repo, "https://github.com/emqx/emqx-plugin-template"}
  14. , {functionality, ["Demo"]}
  15. , {compatibility,
  16. [ {emqx, "~> 5.0"}
  17. ]}
  18. , {description, "This is a demo plugin"}
  19. ]
  20. }.

再次运行打包命令:

  1. make rel
  2. ...
  3. ===> Release successfully assembled: _build/default/rel/emqx_plugin_template
  4. ===> [emqx_plugrel] creating _build/default/emqx_plugrel/emqx_plugin_template-5.0.0-rc.3.tar.gz

命令会提示生成名称为 插件名-版本.tar.gz 的插件包。

6. 安装并启动插件

编译完成的包可以通过 CLI 进行安装:

  1. ./bin/emqx_ctl plugins install {pluginName}

7. 卸载插件

当你不需要插件,可以通过 CLI 卸载插件:

  1. ./bin/emqx_ctl plugins uninstall {pluginName}