本文最后更新于:June 30, 2023 pm

本文作者:[wangwenhai] # 概要:本文主要介绍EMQX插件开发中的一些细节.

image-20191126223605770

1. 背景概述

本文主要讲一下最新版的EMQX的插件开发.关于插件开发环境准备,请看之前的文章,这里讲讲插件开发中的高级功能:自定义参数配置.

2. 案例学习

在此时前我们先看下几个典型的插件:

1. Mysql插件

image-20191126214116896

大概熟悉一下插件的基本结构:其实我们发现EMQX的插件就是一个很普通的OTP应用,其中代码在src目录下,配置在etc下.

我们首先看下Mysql插件的的配置:

## MySQL server address.
## 为了节省篇幅,我把不重要的全部删了,留下关键几个配置
auth.mysql.server = 127.0.0.1:3306
auth.mysql.pool = 8
auth.mysql.username =
auth.mysql.password =
auth.mysql.database = mqtt

这些配置主要用来配置Mysql的Host,端口,密码等等,我们可以很容易集成进我们的应用中.

2. MongoDb插件

image-20191126214558153

其中MongoDB插件和Mysql插件没区别,结构都是完全一样的,因此我们可以按照这个结构来设计插件.

下面是MongoDb插件的配置:

## MongoDB Topology Type.
## 为了节省篇幅,我把不重要的全部删了,留下关键几个配置
auth.mongo.type = single
auth.mongo.server = 127.0.0.1:27017
auth.mongo.pool = 8

同样和Mysql一样,都是方便用户自定义配置参数进来.

4. 自定义插件

看完了上面两个插件的配置以后,我们发现个规律:配置文件基本都是满足Key-Value这种形式,Key作为配置项,Value作为参数值.理解了这种格式以后,我们可在自定义插件开发中加入进来.

​ 因为EMQX的参数配置使用了一个库:cuttlefish,大家可以去github上找找文档,这个库中文文档比较少,建议大家直接看库文档即可.

1. 新建插件

## 如果没安装插件模板,先安装插件模板
wget https://s3.amazonaws.com/rebar3/rebar3 && chmod +x rebar3
./rebar3 local install
mkdir -p ~/.config/rebar3/templates
git clone https://github.com/emqx/rebar3_emqx_plugin ~/.config/rebar3/templates
## 如果上面的工作都已经完成的话,直接新建插件模板
rebar3 new emqx-plugin <plugin-name>

经过上述步骤,我们已经新建了一个插件模板,比如我新建了一个:advisory_plugin.项目结构如下:

image-20191126221244880

2. 配置插件

接下来我们把插件配置进EMQX里面.

首先需要clone下emqx-rel项目,这个是编译EMQX的入口.

git clone https://github.com/emqx/emqx-rel.git emqx-rel
cd emqx-rel && make
./_build/emqx/rel/emqx/bin/emqx console

确认没问题以后,我们开始配置插件.在配置插件之前,记得把代码提交到git服务器上,这里我用gitee做演示,因为国内速度比较快.

  1. 打开rebar.config文件,在deps节点找到合适的位置加入自己的插件地址:

    { advisory_plugin, { git , "https://gitee.com/lagrangewang/advisory_plugin.git" , {branch, "master"} } }

    image-20191126222939838

  2. 在relx节点找到合适的位置,加入以下内容:

    {advisory_plugin, load}

    image-20191126223252312

到此为止我们的插件就装好了.我们按照EMQX的官网文档,编译完成,启动EMQX,可以看到如下:

3. 配置参数

接下来进入比较重要的环节:自定义插件参数.我们在本案例里面演示了如何配置单个或者,多个URL地址.

首先打开插件目录下的etc目录,找到conf文件,加入我们自己的配置项:

# 单个配置项
advisory_plugin.destination = http://localhost:2500/ezlinker/data/in
# 多个配置项
advisory_plugin.server.1 = http://1:2500/ezlinker/data/in
advisory_plugin.server.2 = http://2:2500/ezlinker/data/in

这里需要注意的是,单个配置项一般为K-V键值对的形式.而多个项需要满足如下格式:

k.${name}

其中${name}是个占位符,可以自定义表示多个参数的序号,或者名字,建议用序号来表示.

4. 映射参数

接下来,最后一个环节,映射自定义参数:

打开priv目录下的schema文件,首先映射我们的单配置项:

%% advisory_plugin config
{mapping, "advisory_plugin.destination", "advisory_plugin.destination", [
  {datatype, string}
]}.

其中:mapping表示参数映射,第二个参数表示etc下的conf文件中的名称,第三个参数表示配置文件的键,用来在程序中获取.

5. 转换参数

多项参数比较麻烦,还需要一个转换器,同样在schema文件中,定义一个转换器:

{translation,
 "advisory_plugin.server",
  fun(Conf) ->
      Urls = cuttlefish_variable:filter_by_prefix("advisory_plugin.server", Conf),
      [ Url || Url <- Urls]
  end
}.

这段代码可以理解为:获取配置中advisory_plugin.server对应的值,返回一个列表,配置文件之间的关系如图所示:

image-20191126230712872

6. 获取参数

  1. 单项参数获取
%%参数说明
%%?APP:插件模块
%%destination:mapping的第二个参数的Key
%%"http://127.0.0.1":如果获取失败的默认值
Url = application:get_env(?APP, destination, "http://127.0.0.1")
  1. 多项参数获取

    Urls = application:get_env(?APP, server, "http://127.0.0.1"),
    lists:foreach(fun(U) -> 
        {[_N,_K,_S],Url} = U,
        io:format("Url is : ~p~n", [Url]) end, Urls),

7.总结

本文主要讲了以下知识点:

  1. 创建插件

  2. 注册插件

  3. 编译测试

  4. 自定义开发

  5. 单项参数的配置和获取

  6. 多项参数的定义和获取