Merge branch 'master' into fix-gw-api-erros
This commit is contained in:
commit
d995842f36
|
@ -113,7 +113,7 @@ the check/consume will succeed, but it will be forced to wait for a short period
|
|||
|
||||
burst {
|
||||
desc {
|
||||
en: """The burst, This value is based on rate.</br>
|
||||
en: """The burst, This value is based on rate.<br/>
|
||||
This value + rate = the maximum limit that can be achieved when limiter burst."""
|
||||
zh: """突发速率。
|
||||
突发速率允许短时间内速率超过设置的速率值,突发速率 + 速率 = 当前桶能达到的最大速率值"""
|
||||
|
@ -171,7 +171,7 @@ Once the limit is reached, the restricted client will be slow down even be hung
|
|||
en: """The bytes_in limiter.
|
||||
This is used to limit the inbound bytes rate for this EMQX node.
|
||||
Once the limit is reached, the restricted client will be slow down even be hung for a while."""
|
||||
zh: """流入字节率控制器.
|
||||
zh: """流入字节率控制器。
|
||||
这个是用来控制当前节点上的数据流入的字节率,每条消息将会消耗和其二进制大小等量的令牌,当达到最大速率后,会话将会被限速甚至被强制挂起一小段时间"""
|
||||
}
|
||||
label: {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@
|
|||
{emqx_license,2}.
|
||||
{emqx_management,1}.
|
||||
{emqx_management,2}.
|
||||
{emqx_management,3}.
|
||||
{emqx_mgmt_api_plugins,1}.
|
||||
{emqx_mgmt_cluster,1}.
|
||||
{emqx_mgmt_trace,1}.
|
||||
|
|
|
@ -124,7 +124,10 @@ filter_result(Delivery) ->
|
|||
max_client_num() ->
|
||||
emqx:get_config([rpc, tcp_client_num], ?DefaultClientNum).
|
||||
|
||||
-spec unwrap_erpc(emqx_rpc:erpc(A)) -> A | {error, _Err}.
|
||||
-spec unwrap_erpc(emqx_rpc:erpc(A) | [emqx_rpc:erpc(A)]) -> A | {error, _Err} | list().
|
||||
|
||||
unwrap_erpc(Res) when is_list(Res) ->
|
||||
[unwrap_erpc(R) || R <- Res];
|
||||
unwrap_erpc({ok, A}) ->
|
||||
A;
|
||||
unwrap_erpc({throw, A}) ->
|
||||
|
|
|
@ -1698,7 +1698,7 @@ desc("stats") ->
|
|||
desc("authorization") ->
|
||||
"Settings for client authorization.";
|
||||
desc("mqtt") ->
|
||||
"Global MQTT configuration.</br>\n"
|
||||
"Global MQTT configuration.<br/>"
|
||||
"The configs here work as default values which can be overridden\n"
|
||||
"in <code>zone</code> configs";
|
||||
desc("cache") ->
|
||||
|
@ -2115,11 +2115,11 @@ ref(Module, StructName) -> hoconsc:ref(Module, StructName).
|
|||
mk_duration(Desc, OverrideMeta) ->
|
||||
DefaultMeta = #{
|
||||
desc => Desc ++
|
||||
" Time interval is a string that contains a number followed by time unit:</br>\n"
|
||||
" Time interval is a string that contains a number followed by time unit:<br/>"
|
||||
"- `ms` for milliseconds,\n"
|
||||
"- `s` for seconds,\n"
|
||||
"- `m` for minutes,\n"
|
||||
"- `h` for hours;\n</br>"
|
||||
"- `h` for hours;\n<br/>"
|
||||
"or combination of whereof: `1h5m0s`"
|
||||
},
|
||||
hoconsc:mk(typerefl:alias("string", duration()), maps:merge(DefaultMeta, OverrideMeta)).
|
||||
|
|
|
@ -57,7 +57,7 @@ emqx_authn_jwt {
|
|||
endpoint {
|
||||
desc {
|
||||
en: """JWKS endpoint, it's a read-only endpoint that returns the server's public key set in the JWKS format."""
|
||||
zh: """JWKS 端点, 它是一个以 JWKS 格式返回服务端的公钥集的只读端点。"""
|
||||
zh: """JWKS 端点, 它是一个以 JWKS 格式返回服务端的公钥集的只读端点。"""
|
||||
}
|
||||
label {
|
||||
en: """JWKS Endpoint"""
|
||||
|
|
|
@ -2,7 +2,7 @@ emqx_authz_api_cache {
|
|||
authorization_cache_delete {
|
||||
desc {
|
||||
en: """Clean all authorization cache in the cluster."""
|
||||
zh: """清除集群中所有鉴权数据缓存"""
|
||||
zh: """清除集群中所有授权数据缓存。"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
emqx_authz_api_schema {
|
||||
enable {
|
||||
desc {
|
||||
en: """Set to <code>true</code> or <code>false</code> to disable this ACL provider"""
|
||||
zh: """设为 <code>true</code> 或 <code>false</code> 以启用或禁用此访问控制数据源"""
|
||||
en: """Set to <code>true</code> or <code>false</code> to disable this ACL provider."""
|
||||
zh: """设为 <code>true</code> 或 <code>false</code> 以启用或禁用此访问控制数据源。"""
|
||||
}
|
||||
label {
|
||||
en: """enable"""
|
||||
|
@ -13,7 +13,7 @@ emqx_authz_api_schema {
|
|||
type {
|
||||
desc {
|
||||
en: """Backend type."""
|
||||
zh: """数据后端类型"""
|
||||
zh: """数据后端类型。"""
|
||||
}
|
||||
label {
|
||||
en: """type"""
|
||||
|
@ -26,7 +26,7 @@ emqx_authz_api_schema {
|
|||
rules {
|
||||
desc {
|
||||
en: """Authorization static file rules."""
|
||||
zh: """静态鉴权文件规则"""
|
||||
zh: """静态授权文件规则。"""
|
||||
}
|
||||
label {
|
||||
en: """rules"""
|
||||
|
@ -39,7 +39,7 @@ emqx_authz_api_schema {
|
|||
method {
|
||||
desc {
|
||||
en: """HTTP method."""
|
||||
zh: """HTTP 请求方法"""
|
||||
zh: """HTTP 请求方法。"""
|
||||
}
|
||||
label {
|
||||
en: """method"""
|
||||
|
@ -50,7 +50,7 @@ emqx_authz_api_schema {
|
|||
url {
|
||||
desc {
|
||||
en: """URL of the auth server."""
|
||||
zh: """认证服务器 URL"""
|
||||
zh: """认证服务器 URL。"""
|
||||
}
|
||||
label {
|
||||
en: """url"""
|
||||
|
@ -72,7 +72,7 @@ emqx_authz_api_schema {
|
|||
headers_no_content_type {
|
||||
desc {
|
||||
en: """List of HTTP headers (without <code>content-type</code>)."""
|
||||
zh: """HTTP Headers 列表(无 <code>content-type</code>)"""
|
||||
zh: """HTTP Headers 列表(无 <code>content-type</code>)。"""
|
||||
}
|
||||
label {
|
||||
en: """headers_no_content_type"""
|
||||
|
@ -83,7 +83,7 @@ emqx_authz_api_schema {
|
|||
body {
|
||||
desc {
|
||||
en: """HTTP request body."""
|
||||
zh: """HTTP 请求体"""
|
||||
zh: """HTTP 请求体。"""
|
||||
}
|
||||
label {
|
||||
en: """body"""
|
||||
|
@ -94,7 +94,7 @@ emqx_authz_api_schema {
|
|||
request_timeout {
|
||||
desc {
|
||||
en: """Request timeout."""
|
||||
zh: """请求超时时间"""
|
||||
zh: """请求超时时间。"""
|
||||
}
|
||||
label {
|
||||
en: """request_timeout"""
|
||||
|
@ -111,7 +111,7 @@ emqx_authz_api_schema {
|
|||
collection {
|
||||
desc {
|
||||
en: """`MongoDB` collection containing the authorization data."""
|
||||
zh: """`MongoDB` 鉴权数据集"""
|
||||
zh: """`MongoDB` 授权数据集。"""
|
||||
}
|
||||
label {
|
||||
en: """collection"""
|
||||
|
@ -153,7 +153,7 @@ Filter supports the following placeholders:
|
|||
cmd {
|
||||
desc {
|
||||
en: """Database query used to retrieve authorization data."""
|
||||
zh: """访问控制数据查询命令"""
|
||||
zh: """访问控制数据查询命令。"""
|
||||
}
|
||||
label {
|
||||
en: """cmd"""
|
||||
|
@ -166,7 +166,7 @@ Filter supports the following placeholders:
|
|||
query {
|
||||
desc {
|
||||
en: """Database query used to retrieve authorization data."""
|
||||
zh: """访问控制数据查询语句"""
|
||||
zh: """访问控制数据查询语句。"""
|
||||
}
|
||||
label {
|
||||
en: """query"""
|
||||
|
@ -178,8 +178,8 @@ Filter supports the following placeholders:
|
|||
|
||||
position {
|
||||
desc {
|
||||
en: """Where to place the source"""
|
||||
zh: """认证数据源位置"""
|
||||
en: """Where to place the source."""
|
||||
zh: """认证数据源位置。"""
|
||||
}
|
||||
label {
|
||||
en: """position"""
|
||||
|
|
|
@ -2,14 +2,14 @@ emqx_authz_api_settings {
|
|||
authorization_settings_get {
|
||||
desc {
|
||||
en: """Get authorization settings"""
|
||||
zh: """获取鉴权配置"""
|
||||
zh: """获取授权配置"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_settings_put {
|
||||
desc {
|
||||
en: """Update authorization settings"""
|
||||
zh: """更新鉴权配置"""
|
||||
zh: """更新授权配置"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,56 +2,56 @@ emqx_authz_api_sources {
|
|||
authorization_sources_get {
|
||||
desc {
|
||||
en: """List all authorization sources"""
|
||||
zh: """列出所有鉴权数据源"""
|
||||
zh: """列出所有授权数据源"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_sources_post {
|
||||
desc {
|
||||
en: """Add a new source"""
|
||||
zh: """添加鉴权数据源"""
|
||||
zh: """添加授权数据源"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_sources_type_get {
|
||||
desc {
|
||||
en: """Get a authorization source"""
|
||||
zh: """获取指定类型的鉴权数据源"""
|
||||
zh: """获取指定类型的授权数据源"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_sources_type_put {
|
||||
desc {
|
||||
en: """Update source"""
|
||||
zh: """更新指定类型的鉴权数据源"""
|
||||
zh: """更新指定类型的授权数据源"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_sources_type_delete {
|
||||
desc {
|
||||
en: """Delete source"""
|
||||
zh: """删除指定类型的鉴权数据源"""
|
||||
zh: """删除指定类型的授权数据源"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_sources_type_status_get {
|
||||
desc {
|
||||
en: """Get a authorization source"""
|
||||
zh: """获取指定鉴权数据源的状态"""
|
||||
zh: """获取指定授权数据源的状态"""
|
||||
}
|
||||
}
|
||||
|
||||
authorization_sources_type_move_post {
|
||||
desc {
|
||||
en: """Change the exection order of sources"""
|
||||
zh: """更新鉴权数据源的优先执行顺序"""
|
||||
zh: """更新授权数据源的优先执行顺序"""
|
||||
}
|
||||
}
|
||||
|
||||
sources {
|
||||
desc {
|
||||
en: """Authorization source"""
|
||||
zh: """鉴权数据源列表"""
|
||||
zh: """授权数据源列表"""
|
||||
}
|
||||
label {
|
||||
en: """sources"""
|
||||
|
@ -62,7 +62,7 @@ emqx_authz_api_sources {
|
|||
sources {
|
||||
desc {
|
||||
en: """Authorization sources"""
|
||||
zh: """鉴权数据源列表"""
|
||||
zh: """授权数据源列表"""
|
||||
}
|
||||
label {
|
||||
en: """sources"""
|
||||
|
@ -84,7 +84,7 @@ emqx_authz_api_sources {
|
|||
source {
|
||||
desc {
|
||||
en: """Authorization source"""
|
||||
zh: """鉴权数据源"""
|
||||
zh: """授权数据源"""
|
||||
}
|
||||
label {
|
||||
en: """source"""
|
||||
|
|
|
@ -2,41 +2,41 @@ emqx_authz_schema {
|
|||
sources {
|
||||
desc {
|
||||
en: """
|
||||
Authorization data sources.</br>
|
||||
Authorization data sources.<br/>
|
||||
An array of authorization (ACL) data providers.
|
||||
It is designed as an array, not a hash-map, so the sources can be
|
||||
ordered to form a chain of access controls.</br>
|
||||
ordered to form a chain of access controls.<br/>
|
||||
|
||||
When authorizing a 'publish' or 'subscribe' action, the configured
|
||||
sources are checked in order. When checking an ACL source,
|
||||
in case the client (identified by username or client ID) is not found,
|
||||
it moves on to the next source. And it stops immediately
|
||||
once an 'allow' or 'deny' decision is returned.</br>
|
||||
once an 'allow' or 'deny' decision is returned.<br/>
|
||||
|
||||
If the client is not found in any of the sources,
|
||||
the default action configured in 'authorization.no_match' is applied.</br>
|
||||
the default action configured in 'authorization.no_match' is applied.<br/>
|
||||
|
||||
NOTE:
|
||||
The source elements are identified by their 'type'.
|
||||
It is NOT allowed to configure two or more sources of the same type.
|
||||
"""
|
||||
zh: """
|
||||
鉴权数据源.</br>
|
||||
鉴权(ACL)数据源的列表.
|
||||
它被设计为一个数组,而不是一个散列映射,
|
||||
所以可以作为链式访问控制.</br>
|
||||
授权数据源。<br/>
|
||||
授权(ACL)数据源的列表。
|
||||
它被设计为一个数组,而不是一个散列映射,
|
||||
所以可以作为链式访问控制。<br/>
|
||||
|
||||
当授权一个 'publish' 或 'subscribe' 行为时,
|
||||
当授权一个 'publish' 或 'subscribe' 行为时,
|
||||
该配置列表中的所有数据源将按顺序进行检查。
|
||||
如果在某个客户端未找到时(使用 ClientID 或 Username),
|
||||
将会移动到下一个数据源. 直至得到 'allow' 或 'deny' 的结果.</br>
|
||||
如果在某个客户端未找到时(使用 ClientID 或 Username)。
|
||||
将会移动到下一个数据源。直至得到 'allow' 或 'deny' 的结果。<br/>
|
||||
|
||||
如果在任何数据源中都未找到对应的客户端信息,
|
||||
配置的默认行为 ('authorization.no_match') 将生效.</br>
|
||||
如果在任何数据源中都未找到对应的客户端信息。
|
||||
配置的默认行为 ('authorization.no_match') 将生效。<br/>
|
||||
|
||||
注意:
|
||||
数据源使用 'type' 进行标识.
|
||||
使用同一类型的数据源多于一次不被允许.
|
||||
注意:
|
||||
数据源使用 'type' 进行标识。
|
||||
使用同一类型的数据源多于一次不被允许。
|
||||
"""
|
||||
}
|
||||
label {
|
||||
|
@ -83,7 +83,7 @@ It is NOT allowed to configure two or more sources of the same type.
|
|||
file {
|
||||
desc {
|
||||
en: """Authorization using a static file."""
|
||||
zh: """使用静态文件鉴权"""
|
||||
zh: """使用静态文件授权"""
|
||||
}
|
||||
label {
|
||||
en: """file"""
|
||||
|
@ -109,7 +109,7 @@ and the old file will not be used anymore.
|
|||
那么可以将该文件置于任何 EMQX 可以访问到的位置。
|
||||
|
||||
如果从 EMQX Dashboard 或 HTTP API 创建或修改了规则集,
|
||||
那么EMQX将会生成一个新的文件并将它存放在 `data_dir` 下的 `authz` 子目录中,
|
||||
那么EMQX将会生成一个新的文件并将它存放在 `data_dir` 下的 `authz` 子目录中,
|
||||
并从此弃用旧的文件。"""
|
||||
}
|
||||
label {
|
||||
|
@ -123,7 +123,7 @@ and the old file will not be used anymore.
|
|||
http_get {
|
||||
desc {
|
||||
en: """Authorization using an external HTTP server (via GET requests)."""
|
||||
zh: """使用外部 HTTP 服务器鉴权(GET 请求)。"""
|
||||
zh: """使用外部 HTTP 服务器授权(GET 请求)。"""
|
||||
}
|
||||
label {
|
||||
en: """http_get"""
|
||||
|
@ -134,7 +134,7 @@ and the old file will not be used anymore.
|
|||
http_post {
|
||||
desc {
|
||||
en: """Authorization using an external HTTP server (via POST requests)."""
|
||||
zh: """使用外部 HTTP 服务器鉴权(POST 请求)。"""
|
||||
zh: """使用外部 HTTP 服务器授权(POST 请求)。"""
|
||||
}
|
||||
label {
|
||||
en: """http_post"""
|
||||
|
@ -156,7 +156,7 @@ and the old file will not be used anymore.
|
|||
url {
|
||||
desc {
|
||||
en: """URL of the auth server."""
|
||||
zh: """鉴权 HTTP 服务器地址。"""
|
||||
zh: """授权 HTTP 服务器地址。"""
|
||||
}
|
||||
label {
|
||||
en: """URL"""
|
||||
|
@ -213,7 +213,7 @@ and the old file will not be used anymore.
|
|||
mnesia {
|
||||
desc {
|
||||
en: """Authorization using a built-in database (mnesia)."""
|
||||
zh: """使用内部数据库鉴权 (mnesia)."""
|
||||
zh: """使用内部数据库授权(mnesia)。"""
|
||||
}
|
||||
label {
|
||||
en: """mnesia"""
|
||||
|
@ -226,7 +226,7 @@ and the old file will not be used anymore.
|
|||
mongo_single {
|
||||
desc {
|
||||
en: """Authorization using a single MongoDB instance."""
|
||||
zh: """使用 MongoDB 鉴权(单实例)"""
|
||||
zh: """使用 MongoDB 授权(单实例)。"""
|
||||
}
|
||||
label {
|
||||
en: """mongo_single"""
|
||||
|
@ -237,7 +237,7 @@ and the old file will not be used anymore.
|
|||
mongo_rs {
|
||||
desc {
|
||||
en: """Authorization using a MongoDB replica set."""
|
||||
zh: """使用 MongoDB 鉴权(副本集模式)"""
|
||||
zh: """使用 MongoDB 授权(副本集模式)"""
|
||||
}
|
||||
label {
|
||||
en: """mongo_rs"""
|
||||
|
@ -248,7 +248,7 @@ and the old file will not be used anymore.
|
|||
mongo_sharded {
|
||||
desc {
|
||||
en: """Authorization using a sharded MongoDB cluster."""
|
||||
zh: """使用 MongoDB 鉴权(分片集群模式)"""
|
||||
zh: """使用 MongoDB 授权(分片集群模式)。"""
|
||||
}
|
||||
label {
|
||||
en: """mongo_sharded"""
|
||||
|
@ -259,7 +259,7 @@ and the old file will not be used anymore.
|
|||
collection {
|
||||
desc {
|
||||
en: """`MongoDB` collection containing the authorization data."""
|
||||
zh: """`MongoDB` 鉴权数据集"""
|
||||
zh: """`MongoDB` 授权数据集。"""
|
||||
}
|
||||
label {
|
||||
en: """collection"""
|
||||
|
@ -278,8 +278,8 @@ Filter supports the following placeholders:
|
|||
zh: """
|
||||
在查询中定义过滤条件的条件表达式。
|
||||
过滤器支持如下占位符:
|
||||
- <code>${username}</code>: 将在运行时被替换为客户端连接时使用的用户名
|
||||
- <code>${clientid}</code>: 将在运行时被替换为客户端连接时使用的客户端标识符
|
||||
- <code>${username}</code>:将在运行时被替换为客户端连接时使用的用户名
|
||||
- <code>${clientid}</code>:将在运行时被替换为客户端连接时使用的客户端标识符
|
||||
"""
|
||||
}
|
||||
label {
|
||||
|
@ -293,7 +293,7 @@ Filter supports the following placeholders:
|
|||
mysql {
|
||||
desc {
|
||||
en: """Authorization using a MySQL database."""
|
||||
zh: """使用 MySOL 数据库鉴权"""
|
||||
zh: """使用 MySOL 数据库授权"""
|
||||
}
|
||||
label {
|
||||
en: """mysql"""
|
||||
|
@ -306,7 +306,7 @@ Filter supports the following placeholders:
|
|||
postgresql {
|
||||
desc {
|
||||
en: """Authorization using a PostgreSQL database."""
|
||||
zh: """使用 PostgreSQL 数据库鉴权"""
|
||||
zh: """使用 PostgreSQL 数据库授权"""
|
||||
}
|
||||
label {
|
||||
en: """postgresql"""
|
||||
|
@ -319,7 +319,7 @@ Filter supports the following placeholders:
|
|||
redis_single {
|
||||
desc {
|
||||
en: """Authorization using a single Redis instance."""
|
||||
zh: """使用 Redis 鉴权(单实例)"""
|
||||
zh: """使用 Redis 授权(单实例)。"""
|
||||
}
|
||||
label {
|
||||
en: """redis_single"""
|
||||
|
@ -330,7 +330,7 @@ Filter supports the following placeholders:
|
|||
redis_sentinel {
|
||||
desc {
|
||||
en: """Authorization using a Redis Sentinel."""
|
||||
zh: """使用 Redis 鉴权(哨兵模式)"""
|
||||
zh: """使用 Redis 授权(哨兵模式)。"""
|
||||
}
|
||||
label {
|
||||
en: """redis_sentinel"""
|
||||
|
@ -341,7 +341,7 @@ Filter supports the following placeholders:
|
|||
redis_cluster {
|
||||
desc {
|
||||
en: """Authorization using a Redis cluster."""
|
||||
zh: """使用 Redis 鉴权(集群模式)"""
|
||||
zh: """使用 Redis 授权(集群模式)。"""
|
||||
}
|
||||
label {
|
||||
en: """redis_cluster"""
|
||||
|
@ -365,7 +365,7 @@ Filter supports the following placeholders:
|
|||
query {
|
||||
desc {
|
||||
en: """Database query used to retrieve authorization data."""
|
||||
zh: """访问控制数据查询语句/查询命令"""
|
||||
zh: """访问控制数据查询语句/查询命令。"""
|
||||
}
|
||||
label {
|
||||
en: """query"""
|
||||
|
@ -510,44 +510,44 @@ Filter supports the following placeholders:
|
|||
metrics_total {
|
||||
desc {
|
||||
en: """The total number of times the authorization rule was triggered."""
|
||||
zh: """鉴权实例被触发的总次数。"""
|
||||
zh: """授权实例被触发的总次数。"""
|
||||
}
|
||||
label: {
|
||||
en: """The Total Number of Times the Authorization Rule was Triggered"""
|
||||
zh: """鉴权实例被触发的总次数"""
|
||||
zh: """授权实例被触发的总次数"""
|
||||
}
|
||||
}
|
||||
|
||||
nomatch {
|
||||
desc {
|
||||
en: """The number of times that no authorization rules were matched."""
|
||||
zh: """没有匹配到任何鉴权规则的次数。"""
|
||||
zh: """没有匹配到任何授权规则的次数。"""
|
||||
}
|
||||
label: {
|
||||
en: """The Number of Times that no Authorization Rules were Matched"""
|
||||
zh: """没有匹配到任何鉴权规则的次数"""
|
||||
zh: """没有匹配到任何授权规则的次数"""
|
||||
}
|
||||
}
|
||||
|
||||
allow {
|
||||
desc {
|
||||
en: """The number of times the authentication was successful."""
|
||||
zh: """鉴权成功的次数。"""
|
||||
zh: """授权成功的次数。"""
|
||||
}
|
||||
label: {
|
||||
en: """The Number of Times the Authentication was Successful"""
|
||||
zh: """鉴权成功次数"""
|
||||
zh: """授权成功次数"""
|
||||
}
|
||||
}
|
||||
|
||||
deny {
|
||||
desc {
|
||||
en: """The number of authentication failures."""
|
||||
zh: """鉴权失败的次数。"""
|
||||
zh: """授权失败的次数。"""
|
||||
}
|
||||
label: {
|
||||
en: """The Number of Authentication Failures"""
|
||||
zh: """鉴权失败次数"""
|
||||
zh: """授权失败次数"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ emqx_auto_subscribe_schema {
|
|||
auto_subscribe {
|
||||
desc {
|
||||
en: """After the device logs in successfully, the subscription is automatically completed for the device through the pre-defined subscription representation. Supports the use of placeholders."""
|
||||
zh: """设备登陆成功之后,通过预设的订阅表示符,为设备自动完成订阅。支持使用占位符。"""
|
||||
zh: """设备登录成功之后,通过预设的订阅表示符,为设备自动完成订阅。支持使用占位符。"""
|
||||
}
|
||||
lable {
|
||||
en: """Auto Subscribe"""
|
||||
|
|
|
@ -15,13 +15,13 @@ emqx_bridge_schema {
|
|||
desc {
|
||||
en: """
|
||||
The ID or the configs of the connector to be used for this bridge. Connector IDs must be of format:
|
||||
<code>{type}:{name}</code>.</br>
|
||||
<code>{type}:{name}</code>.<br/>
|
||||
In config files, you can find the corresponding config entry for a connector by such path:
|
||||
'connectors.{type}.{name}'.</br>
|
||||
'connectors.{type}.{name}'.<br/>
|
||||
"""
|
||||
zh: """
|
||||
Bridge 使用的 Connector 的 ID 或者配置。Connector ID 的格式必须为:<code>{type}:{name}</code>.</br>
|
||||
在配置文件中,您可以通过以下路径找到 Connector 的相应配置条目:'connector.{type}.{name}'。</br>"""
|
||||
Bridge 使用的 Connector 的 ID 或者配置。Connector ID 的格式必须为:<code>{type}:{name}</code>。<br/>
|
||||
在配置文件中,您可以通过以下路径找到 Connector 的相应配置条目:'connector.{type}.{name}'。<br/>"""
|
||||
}
|
||||
label: {
|
||||
en: "Connector ID"
|
||||
|
|
|
@ -25,16 +25,16 @@ emqx_bridge_webhook_schema {
|
|||
config_url {
|
||||
desc {
|
||||
en: """
|
||||
The URL of the HTTP Bridge.</br>
|
||||
The URL of the HTTP Bridge.<br/>
|
||||
Template with variables is allowed in the path, but variables cannot be used in the scheme, host,
|
||||
or port part.</br>
|
||||
or port part.<br/>
|
||||
For example, <code> http://localhost:9901/${topic} </code> is allowed, but
|
||||
<code> http://${host}:9901/message </code> or <code> http://localhost:${port}/message </code>
|
||||
is not allowed.
|
||||
"""
|
||||
zh: """
|
||||
HTTP Bridge 的 URL。</br>
|
||||
路径中允许使用带变量的模板,但是 host, port 不允许使用变量模板。</br>
|
||||
HTTP Bridge 的 URL。<br/>
|
||||
路径中允许使用带变量的模板,但是 host, port 不允许使用变量模板。<br/>
|
||||
例如,<code> http://localhost:9901/${topic} </code> 是允许的,
|
||||
但是<code> http://${host}:9901/message </code>
|
||||
或 <code> http://localhost:${port}/message </code>
|
||||
|
@ -51,13 +51,13 @@ HTTP Bridge 的 URL。</br>
|
|||
desc {
|
||||
en: """
|
||||
The MQTT topic filter to be forwarded to the HTTP server. All MQTT 'PUBLISH' messages with the topic
|
||||
matching the local_topic will be forwarded.</br>
|
||||
matching the local_topic will be forwarded.<br/>
|
||||
NOTE: if this bridge is used as the action of a rule (EMQX rule engine), and also local_topic is
|
||||
configured, then both the data got from the rule and the MQTT messages that match local_topic
|
||||
will be forwarded.
|
||||
"""
|
||||
zh: """
|
||||
发送到 'local_topic' 的消息都会转发到 HTTP 服务器。 </br>
|
||||
发送到 'local_topic' 的消息都会转发到 HTTP 服务器。 <br/>
|
||||
注意:如果这个 Bridge 被用作规则(EMQX 规则引擎)的输出,同时也配置了 'local_topic' ,那么这两部分的消息都会被转发到 HTTP 服务器。
|
||||
"""
|
||||
}
|
||||
|
@ -70,12 +70,12 @@ will be forwarded.
|
|||
config_method {
|
||||
desc {
|
||||
en: """
|
||||
The method of the HTTP request. All the available methods are: post, put, get, delete.</br>
|
||||
Template with variables is allowed.</br>
|
||||
The method of the HTTP request. All the available methods are: post, put, get, delete.<br/>
|
||||
Template with variables is allowed.<br/>
|
||||
"""
|
||||
zh: """
|
||||
HTTP 请求的方法。 所有可用的方法包括:post、put、get、delete。</br>
|
||||
允许使用带有变量的模板。</br>"""
|
||||
HTTP 请求的方法。 所有可用的方法包括:post、put、get、delete。<br/>
|
||||
允许使用带有变量的模板。<br/>"""
|
||||
}
|
||||
label: {
|
||||
en: "HTTP Method"
|
||||
|
@ -86,11 +86,11 @@ HTTP 请求的方法。 所有可用的方法包括:post、put、get、delete
|
|||
config_headers {
|
||||
desc {
|
||||
en: """
|
||||
The headers of the HTTP request.</br>
|
||||
The headers of the HTTP request.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
HTTP 请求的标头。</br>
|
||||
HTTP 请求的标头。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -103,11 +103,11 @@ HTTP 请求的标头。</br>
|
|||
config_body {
|
||||
desc {
|
||||
en: """
|
||||
The body of the HTTP request.</br>
|
||||
The body of the HTTP request.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
HTTP 请求的正文。</br>
|
||||
HTTP 请求的正文。<br/>
|
||||
允许使用带有变量的模板。"""
|
||||
}
|
||||
label: {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%% -*- mode: erlang -*-
|
||||
{application, emqx_bridge, [
|
||||
{description, "An OTP application"},
|
||||
{vsn, "0.1.3"},
|
||||
{vsn, "0.1.4"},
|
||||
{registered, []},
|
||||
{mod, {emqx_bridge_app, []}},
|
||||
{applications, [
|
||||
|
|
|
@ -94,7 +94,7 @@ direction_field(Dir, Desc) ->
|
|||
#{
|
||||
required => true,
|
||||
default => egress,
|
||||
desc => "The direction of the bridge. Can be one of 'ingress' or 'egress'.</br>" ++
|
||||
desc => "The direction of the bridge. Can be one of 'ingress' or 'egress'.<br/>" ++
|
||||
Desc
|
||||
}
|
||||
)}.
|
||||
|
|
|
@ -71,12 +71,12 @@ For more information, see: https://www.erlang.org/doc/man/erl.html
|
|||
desc {
|
||||
en: """Service discovery method for the cluster nodes."""
|
||||
zh: """集群节点发现方式。可选值为:
|
||||
- manual: 手动加入集群</br>
|
||||
- static: 配置静态节点。配置几个固定的节点,新节点通过连接固定节点中的某一个来加入集群。</br>
|
||||
- mcast: 使用 UDP 多播的方式发现节点。</br>
|
||||
- dns: 使用 DNS A 记录的方式发现节点。</br>
|
||||
- etcd: 使用 etcd 发现节点。</br>
|
||||
- k8s: 使用 Kubernetes 发现节点。</br>
|
||||
- manual: 手动加入集群<br/>
|
||||
- static: 配置静态节点。配置几个固定的节点,新节点通过连接固定节点中的某一个来加入集群。<br/>
|
||||
- mcast: 使用 UDP 多播的方式发现节点。<br/>
|
||||
- dns: 使用 DNS A 记录的方式发现节点。<br/>
|
||||
- etcd: 使用 etcd 发现节点。<br/>
|
||||
- k8s: 使用 Kubernetes 发现节点。<br/>
|
||||
"""
|
||||
}
|
||||
label {
|
||||
|
@ -111,9 +111,9 @@ For more information, see: https://www.erlang.org/doc/man/erl.html
|
|||
desc {
|
||||
en: """The Erlang distribution protocol for the cluster."""
|
||||
zh: """分布式 Erlang 集群协议类型。可选值为:
|
||||
- inet_tcp: 使用 IPv4 </br>
|
||||
- inet6_tcp 使用 IPv6 </br>
|
||||
- inet_tls: 使用 TLS,需要与 node.ssl_dist_optfile 配置一起使用。</br>
|
||||
- inet_tcp: 使用 IPv4 <br/>
|
||||
- inet6_tcp 使用 IPv6 <br/>
|
||||
- inet_tls: 使用 TLS,需要与 node.ssl_dist_optfile 配置一起使用。<br/>
|
||||
"""
|
||||
}
|
||||
label {
|
||||
|
@ -152,7 +152,7 @@ For more information, see: https://www.erlang.org/doc/man/erl.html
|
|||
|
||||
cluster_mcast_ports {
|
||||
desc {
|
||||
en: """List of UDP ports used for service discovery.</br>
|
||||
en: """List of UDP ports used for service discovery.<br/>
|
||||
Note: probe messages are broadcast to all the specified ports.
|
||||
"""
|
||||
zh: """指定多播端口。如有多个端口使用逗号 , 分隔。
|
||||
|
@ -286,7 +286,7 @@ Applicable when <code>cluster.discovery_strategy = dns</code>
|
|||
desc {
|
||||
en: """Key prefix used for EMQX service discovery."""
|
||||
zh: """指定 etcd 路径的前缀。每个节点在 etcd 中都会创建一个路径:
|
||||
v2/keys/<prefix>/<cluster.name>/<node.name> </br>
|
||||
v2/keys/<prefix>/<cluster.name>/<node.name> <br/>
|
||||
当 cluster.discovery_strategy 为 etcd 时,此配置项才有效。
|
||||
"""
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ Setting <code>cluster.k8s.address_type</code> to <code>ip</code> will
|
|||
make EMQX to discover IP addresses of peer nodes from Kubernetes API.
|
||||
"""
|
||||
zh: """当使用 k8s 方式集群时,address_type 用来从 Kubernetes 接口的应答里获取什么形式的 Host 列表。
|
||||
指定 <code>cluster.k8s.address_type</code. 为 <code>ip</code>,则将从 Kubernetes 接口中获取集群中其他节点
|
||||
指定 <code>cluster.k8s.address_type</code> 为 <code>ip</code>,则将从 Kubernetes 接口中获取集群中其他节点
|
||||
的IP地址。
|
||||
"""
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ make EMQX to discover IP addresses of peer nodes from Kubernetes API.
|
|||
|
||||
cluster_k8s_suffix {
|
||||
desc {
|
||||
en: """Node name suffix.</br>
|
||||
en: """Node name suffix.<br/>
|
||||
Note: this parameter is only relevant when <code>address_type</code> is <code>dns</code>
|
||||
or <code>hostname</code>."""
|
||||
zh: """当使用 k8s 方式并且 cluster.k8s.address_type 指定为 dns 类型时,可设置 emqx 节点名的后缀。
|
||||
|
@ -426,26 +426,26 @@ belong to different clusters from accidentally connecting to each other."""
|
|||
node_data_dir {
|
||||
desc {
|
||||
en: """
|
||||
Path to the persistent data directory.</br>
|
||||
Possible auto-created subdirectories are:</br>
|
||||
- `mnesia/<node_name>`: EMQX's built-in database directory.</br>
|
||||
For example, `mnesia/emqx@127.0.0.1`.</br>
|
||||
There should be only one such subdirectory.</br>
|
||||
Meaning, in case the node is to be renamed (to e.g. `emqx@10.0.1.1`),</br>
|
||||
the old dir should be deleted first.</br>
|
||||
- `configs`: Generated configs at boot time, and cluster/local override configs.</br>
|
||||
- `patches`: Hot-patch beam files are to be placed here.</br>
|
||||
- `trace`: Trace log files.</br>
|
||||
Path to the persistent data directory.<br/>
|
||||
Possible auto-created subdirectories are:<br/>
|
||||
- `mnesia/<node_name>`: EMQX's built-in database directory.<br/>
|
||||
For example, `mnesia/emqx@127.0.0.1`.<br/>
|
||||
There should be only one such subdirectory.<br/>
|
||||
Meaning, in case the node is to be renamed (to e.g. `emqx@10.0.1.1`),<br/>
|
||||
the old dir should be deleted first.<br/>
|
||||
- `configs`: Generated configs at boot time, and cluster/local override configs.<br/>
|
||||
- `patches`: Hot-patch beam files are to be placed here.<br/>
|
||||
- `trace`: Trace log files.<br/>
|
||||
|
||||
**NOTE**: One data dir cannot be shared by two or more EMQX nodes.
|
||||
"""
|
||||
zh: """
|
||||
节点数据存放目录,可能会自动创建的子目录如下:</br>
|
||||
- `mnesia/<node_name>`。EMQX的内置数据库目录。例如,`mnesia/emqx@127.0.0.1`。</br>
|
||||
如果节点要被重新命名(例如,`emqx@10.0.1.1`)。旧目录应该首先被删除。</br>
|
||||
- `configs`。在启动时生成的配置,以及集群/本地覆盖的配置。</br>
|
||||
- `patches`: 热补丁文件将被放在这里。</br>
|
||||
- `trace`: 日志跟踪文件。</br>
|
||||
节点数据存放目录,可能会自动创建的子目录如下:<br/>
|
||||
- `mnesia/<node_name>`。EMQX的内置数据库目录。例如,`mnesia/emqx@127.0.0.1`。<br/>
|
||||
如果节点要被重新命名(例如,`emqx@10.0.1.1`)。旧目录应该首先被删除。<br/>
|
||||
- `configs`。在启动时生成的配置,以及集群/本地覆盖的配置。<br/>
|
||||
- `patches`: 热补丁文件将被放在这里。<br/>
|
||||
- `trace`: 日志跟踪文件。<br/>
|
||||
|
||||
**注意**: 一个数据dir不能被两个或更多的EMQX节点同时使用。
|
||||
"""
|
||||
|
@ -566,9 +566,9 @@ significant: later configuration files override the previous ones.
|
|||
db_backend {
|
||||
desc {
|
||||
en: """
|
||||
Select the backend for the embedded database.</br>
|
||||
Select the backend for the embedded database.<br/>
|
||||
<code>rlog</code> is the default backend,
|
||||
that is suitable for very large clusters.</br>
|
||||
that is suitable for very large clusters.<br/>
|
||||
<code>mnesia</code> is a backend that offers decent performance in small clusters.
|
||||
"""
|
||||
zh: """ rlog是默认的数据库,他适用于大规模的集群。
|
||||
|
@ -584,20 +584,20 @@ mnesia是备选数据库,在小集群中提供了很好的性能。
|
|||
db_role {
|
||||
desc {
|
||||
en: """
|
||||
Select a node role.</br>
|
||||
Select a node role.<br/>
|
||||
<code>core</code> nodes provide durability of the data, and take care of writes.
|
||||
It is recommended to place core nodes in different racks or different availability zones.</br>
|
||||
It is recommended to place core nodes in different racks or different availability zones.<br/>
|
||||
<code>replicant</code> nodes are ephemeral worker nodes. Removing them from the cluster
|
||||
doesn't affect database redundancy</br>
|
||||
It is recommended to have more replicant nodes than core nodes.</br>
|
||||
doesn't affect database redundancy<br/>
|
||||
It is recommended to have more replicant nodes than core nodes.<br/>
|
||||
Note: this parameter only takes effect when the <code>backend</code> is set
|
||||
to <code>rlog</code>.
|
||||
"""
|
||||
zh: """
|
||||
选择节点的角色。</br>
|
||||
<code>core</code> 节点提供数据的持久性,并负责写入。建议将核心节点放置在不同的机架或不同的可用区。</br>
|
||||
<code>repliant</code> 节点是临时工作节点。 从集群中删除它们,不影响数据库冗余</br>
|
||||
建议复制节点多于核心节点。</br>
|
||||
选择节点的角色。<br/>
|
||||
<code>core</code> 节点提供数据的持久性,并负责写入。建议将核心节点放置在不同的机架或不同的可用区。<br/>
|
||||
<code>repliant</code> 节点是临时工作节点。 从集群中删除它们,不影响数据库冗余<br/>
|
||||
建议复制节点多于核心节点。<br/>
|
||||
注意:该参数仅在设置<code>backend</code>时生效到 <code>rlog</code>。
|
||||
"""
|
||||
}
|
||||
|
@ -610,17 +610,17 @@ to <code>rlog</code>.
|
|||
db_core_nodes {
|
||||
desc {
|
||||
en: """
|
||||
List of core nodes that the replicant will connect to.</br>
|
||||
List of core nodes that the replicant will connect to.<br/>
|
||||
Note: this parameter only takes effect when the <code>backend</code> is set
|
||||
to <code>rlog</code> and the <code>role</code> is set to <code>replicant</code>.</br>
|
||||
This value needs to be defined for manual or static cluster discovery mechanisms.</br>
|
||||
to <code>rlog</code> and the <code>role</code> is set to <code>replicant</code>.<br/>
|
||||
This value needs to be defined for manual or static cluster discovery mechanisms.<br/>
|
||||
If an automatic cluster discovery mechanism is being used (such as <code>etcd</code>),
|
||||
there is no need to set this value.
|
||||
"""
|
||||
zh: """当前节点连接的核心节点列表。</br>
|
||||
zh: """当前节点连接的核心节点列表。<br/>
|
||||
注意:该参数仅在设置<code>backend</code>时生效到 <code>rlog</code>
|
||||
并且设置<code>role</code>为<code>replicant</code>时生效。</br>
|
||||
该值需要在手动或静态集群发现机制下设置。</br>
|
||||
并且设置<code>role</code>为<code>replicant</code>时生效。<br/>
|
||||
该值需要在手动或静态集群发现机制下设置。<br/>
|
||||
如果使用了自动集群发现机制(如<code>etcd</code>),则不需要设置该值。
|
||||
"""
|
||||
}
|
||||
|
@ -657,15 +657,15 @@ transaction log entry.
|
|||
|
||||
db_default_shard_transport {
|
||||
desc {
|
||||
en: """Defines the default transport for pushing transaction logs.</br>
|
||||
en: """Defines the default transport for pushing transaction logs.<br/>
|
||||
This may be overridden on a per-shard basis in <code>db.shard_transports</code>.
|
||||
<code>gen_rpc</code> uses the <code>gen_rpc</code> library,
|
||||
<code>distr</code> uses the Erlang distribution.</br>"""
|
||||
<code>distr</code> uses the Erlang distribution.<br/>"""
|
||||
zh: """
|
||||
定义用于推送事务日志的默认传输。</br>
|
||||
定义用于推送事务日志的默认传输。<br/>
|
||||
这可以在 <code>db.shard_transports</code> 中基于每个分片被覆盖。
|
||||
<code>gen_rpc</code> 使用 <code>gen_rpc</code> 库,
|
||||
<code>distr</code> 使用 Erlang 发行版。</br>
|
||||
<code>distr</code> 使用 Erlang 发行版。<br/>
|
||||
"""
|
||||
}
|
||||
label {
|
||||
|
@ -676,13 +676,13 @@ This may be overridden on a per-shard basis in <code>db.shard_transports</code>.
|
|||
|
||||
db_shard_transports {
|
||||
desc {
|
||||
en: """Allows to tune the transport method used for transaction log replication, on a per-shard basis.</br>
|
||||
en: """Allows to tune the transport method used for transaction log replication, on a per-shard basis.<br/>
|
||||
<code>gen_rpc</code> uses the <code>gen_rpc</code> library,
|
||||
<code>distr</code> uses the Erlang distribution.</br>If not specified,
|
||||
<code>distr</code> uses the Erlang distribution.<br/>If not specified,
|
||||
the default is to use the value set in <code>db.default_shard_transport</code>."""
|
||||
zh: """允许为每个 shard 下的事务日志复制操作的传输方法进行调优。</br>
|
||||
zh: """允许为每个 shard 下的事务日志复制操作的传输方法进行调优。<br/>
|
||||
<code>gen_rpc</code> 使用 <code>gen_rpc</code> 库,
|
||||
<code>distr</code> 使用 Erlang 自带的 rpc 库。</br>如果未指定,
|
||||
<code>distr</code> 使用 Erlang 自带的 rpc 库。<br/>如果未指定,
|
||||
默认是使用 <code>db.default_shard_transport</code> 中设置的值。
|
||||
"""
|
||||
}
|
||||
|
@ -763,12 +763,12 @@ Ensure that the number of completed transactions is less than the <code>max_hist
|
|||
|
||||
rpc_port_discovery {
|
||||
desc {
|
||||
en: """<code>manual</code>: discover ports by <code>tcp_server_port</code>.</br>
|
||||
en: """<code>manual</code>: discover ports by <code>tcp_server_port</code>.<br/>
|
||||
<code>stateless</code>: discover ports in a stateless manner, using the following algorithm.
|
||||
If node name is <code>emqxN@127.0.0.1</code>, where the N is an integer,
|
||||
then the listening port will be 5370 + N."""
|
||||
zh: """<code>manual</code>: 通过 <code>tcp_server_port</code> 来发现端口。
|
||||
</br><code>stateless</code>: 使用无状态的方式来发现端口,使用如下算法。如果节点名称是 <code>
|
||||
<br/><code>stateless</code>: 使用无状态的方式来发现端口,使用如下算法。如果节点名称是 <code>
|
||||
emqxN@127.0.0.1</code>, N 是一个数字,那么监听端口就是 5370 + N。
|
||||
"""
|
||||
}
|
||||
|
@ -780,9 +780,9 @@ emqxN@127.0.0.1</code>, N 是一个数字,那么监听端口就是 5370 + N。
|
|||
|
||||
rpc_tcp_server_port {
|
||||
desc {
|
||||
en: """Listening port used by RPC local service.</br>
|
||||
en: """Listening port used by RPC local service.<br/>
|
||||
Note that this config only takes effect when rpc.port_discovery is set to manual."""
|
||||
zh: """RPC 本地服务使用的 TCP 端口。</br>
|
||||
zh: """RPC 本地服务使用的 TCP 端口。<br/>
|
||||
只有当 rpc.port_discovery 设置为 manual 时,此配置才会生效。
|
||||
"""
|
||||
}
|
||||
|
@ -794,10 +794,10 @@ Note that this config only takes effect when rpc.port_discovery is set to manual
|
|||
|
||||
rpc_ssl_server_port {
|
||||
desc {
|
||||
en: """Listening port used by RPC local service.</br>
|
||||
en: """Listening port used by RPC local service.<br/>
|
||||
Note that this config only takes effect when rpc.port_discovery is set to manual
|
||||
and <code>driver</code> is set to <code>ssl</code>."""
|
||||
zh: """RPC 本地服务使用的监听SSL端口。</br>
|
||||
zh: """RPC 本地服务使用的监听SSL端口。<br/>
|
||||
只有当 rpc.port_discovery 设置为 manual 且 <code> dirver </code> 设置为 <code>ssl</code>,
|
||||
此配置才会生效。
|
||||
"""
|
||||
|
@ -847,9 +847,9 @@ Note that this config only takes effect when <code>rpc.driver</code> is set to <
|
|||
|
||||
rpc_keyfile {
|
||||
desc {
|
||||
en: """Path to the private key file for the <code>rpc.certfile</code>.</br>
|
||||
en: """Path to the private key file for the <code>rpc.certfile</code>.<br/>
|
||||
Note: contents of this file are secret, so it's necessary to set permissions to 600."""
|
||||
zh: """<code>rpc.certfile</code> 的私钥文件的路径。</br>
|
||||
zh: """<code>rpc.certfile</code> 的私钥文件的路径。<br/>
|
||||
注意:此文件内容是私钥,所以需要设置权限为 600。
|
||||
"""
|
||||
}
|
||||
|
@ -861,9 +861,9 @@ Note: contents of this file are secret, so it's necessary to set permissions to
|
|||
|
||||
rpc_cacertfile {
|
||||
desc {
|
||||
en: """Path to certification authority TLS certificate file used to validate <code>rpc.certfile</code>.</br>
|
||||
en: """Path to certification authority TLS certificate file used to validate <code>rpc.certfile</code>.<br/>
|
||||
Note: certificates of all nodes in the cluster must be signed by the same CA."""
|
||||
zh: """验证 <code>rpc.certfile</code> 的 CA 证书文件的路径。</br>
|
||||
zh: """验证 <code>rpc.certfile</code> 的 CA 证书文件的路径。<br/>
|
||||
注意:集群中所有节点的证书必须使用同一个 CA 签发。
|
||||
"""
|
||||
}
|
||||
|
@ -1201,7 +1201,7 @@ Supervisor 报告的类型。默认为 error 类型。
|
|||
desc {
|
||||
en: """Enable log rotation feature."""
|
||||
zh: """启用日志轮换功能。启动后生成日志文件后缀会加上对应的索引数字,比如:log/emqx.log.1。
|
||||
系统会默认生成<code>*.siz/*.idx<code>用于记录日志位置,请不要手动修改这两个文件。
|
||||
系统会默认生成<code>*.siz/*.idx</code>用于记录日志位置,请不要手动修改这两个文件。
|
||||
"""
|
||||
}
|
||||
label {
|
||||
|
@ -1301,17 +1301,17 @@ Supervisor 报告的类型。默认为 error 类型。
|
|||
authorization {
|
||||
desc {
|
||||
en: """
|
||||
Authorization a.k.a. ACL.</br>
|
||||
In EMQX, MQTT client access control is extremely flexible.</br>
|
||||
Authorization a.k.a. ACL.<br/>
|
||||
In EMQX, MQTT client access control is extremely flexible.<br/>
|
||||
An out-of-the-box set of authorization data sources are supported.
|
||||
For example,</br>
|
||||
'file' source is to support concise and yet generic ACL rules in a file;</br>
|
||||
For example,<br/>
|
||||
'file' source is to support concise and yet generic ACL rules in a file;<br/>
|
||||
'built_in_database' source can be used to store per-client customizable rule sets,
|
||||
natively in the EMQX node;</br>
|
||||
'http' source to make EMQX call an external HTTP API to make the decision;</br>
|
||||
'PostgreSQL' etc. to look up clients or rules from external databases;</br>
|
||||
natively in the EMQX node;<br/>
|
||||
'http' source to make EMQX call an external HTTP API to make the decision;<br/>
|
||||
'PostgreSQL' etc. to look up clients or rules from external databases;<br/>
|
||||
"""
|
||||
zh: """ 授权(ACL)。EMQX 支持完整的客户端访问控制(ACL)。</br> """
|
||||
zh: """ 授权(ACL)。EMQX 支持完整的客户端访问控制(ACL)。<br/> """
|
||||
}
|
||||
label {
|
||||
en: "Authorization"
|
||||
|
@ -1321,9 +1321,9 @@ natively in the EMQX node;</br>
|
|||
|
||||
desc_cluster {
|
||||
desc {
|
||||
en: """EMQX nodes can form a cluster to scale up the total capacity.</br>
|
||||
en: """EMQX nodes can form a cluster to scale up the total capacity.<br/>
|
||||
Here holds the configs to instruct how individual nodes can discover each other."""
|
||||
zh: """EMQX 节点可以组成一个集群,以提高总容量。</br> 这里指定了节点之间如何连接。"""
|
||||
zh: """EMQX 节点可以组成一个集群,以提高总容量。<br/> 这里指定了节点之间如何连接。"""
|
||||
}
|
||||
label {
|
||||
en: "Cluster"
|
||||
|
@ -1422,11 +1422,11 @@ The new node joins the cluster by connecting to one of the bootstrap nodes."""
|
|||
|
||||
desc_rpc {
|
||||
desc {
|
||||
en: """EMQX uses a library called <code>gen_rpc</code> for inter-broker communication.</br>
|
||||
en: """EMQX uses a library called <code>gen_rpc</code> for inter-broker communication.<br/>
|
||||
Most of the time the default config should work,
|
||||
but in case you need to do performance fine-tuning or experiment a bit,
|
||||
this is where to look."""
|
||||
zh: """EMQX 使用 <code>gen_rpc</code> 库来实现跨节点通信。</br>
|
||||
zh: """EMQX 使用 <code>gen_rpc</code> 库来实现跨节点通信。<br/>
|
||||
大多数情况下,默认的配置应该可以工作,但如果你需要做一些性能优化或者实验,可以尝试调整这些参数。"""
|
||||
}
|
||||
label {
|
||||
|
@ -1472,11 +1472,11 @@ Each sink is represented by a _log handler_, which can be configured independent
|
|||
desc_log_rotation {
|
||||
desc {
|
||||
en: """
|
||||
By default, the logs are stored in `./log` directory (for installation from zip file) or in `/var/log/emqx` (for binary installation).</br>
|
||||
By default, the logs are stored in `./log` directory (for installation from zip file) or in `/var/log/emqx` (for binary installation).<br/>
|
||||
This section of the configuration controls the number of files kept for each log handler.
|
||||
"""
|
||||
zh: """
|
||||
默认情况下,日志存储在 `./log` 目录(用于从 zip 文件安装)或 `/var/log/emqx`(用于二进制安装)。</br>
|
||||
默认情况下,日志存储在 `./log` 目录(用于从 zip 文件安装)或 `/var/log/emqx`(用于二进制安装)。<br/>
|
||||
这部分配置,控制每个日志处理进程保留的文件数量。
|
||||
"""
|
||||
}
|
||||
|
@ -1489,11 +1489,11 @@ This section of the configuration controls the number of files kept for each log
|
|||
desc_log_overload_kill {
|
||||
desc {
|
||||
en: """
|
||||
Log overload kill features an overload protection that activates when the log handlers use too much memory or have too many buffered log messages.</br>
|
||||
Log overload kill features an overload protection that activates when the log handlers use too much memory or have too many buffered log messages.<br/>
|
||||
When the overload is detected, the log handler is terminated and restarted after a cooldown period.
|
||||
"""
|
||||
zh: """
|
||||
日志过载终止,具有过载保护功能。当日志处理进程使用过多内存,或者缓存的日志消息过多时该功能被激活。</br>
|
||||
日志过载终止,具有过载保护功能。当日志处理进程使用过多内存,或者缓存的日志消息过多时该功能被激活。<br/>
|
||||
检测到过载时,日志处理进程将终止,并在冷却期后重新启动。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ emqx_connector_api {
|
|||
conn_test_post {
|
||||
desc {
|
||||
en: """
|
||||
Test creating a new connector by given ID </br>
|
||||
Test creating a new connector by given ID <br/>
|
||||
The ID must be of format '{type}:{name}'
|
||||
"""
|
||||
zh: """
|
||||
通过给定的 ID 测试创建一个新的连接器 </br>
|
||||
通过给定的 ID 测试创建一个新的连接器 <br/>
|
||||
ID 的格式必须为“{type}:{name}”
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ emqx_connector_http {
|
|||
base_url {
|
||||
desc {
|
||||
en: """
|
||||
The base URL is the URL includes only the scheme, host and port.</br>
|
||||
The base URL is the URL includes only the scheme, host and port.<br/>
|
||||
When send an HTTP request, the real URL to be used is the concatenation of the base URL and the
|
||||
path parameter (passed by the emqx_resource:query/2,3 or provided by the request parameter).</br>
|
||||
path parameter (passed by the emqx_resource:query/2,3 or provided by the request parameter).<br/>
|
||||
For example: `http://localhost:9901/`
|
||||
"""
|
||||
zh: """
|
||||
base URL 只包含host和port。</br>
|
||||
发送HTTP请求时,真实的URL是由base URL 和 path parameter连接而成(通过emqx_resource:query/2,3传递,或者通过请求参数提供)。</br>
|
||||
base URL 只包含host和port。<br/>
|
||||
发送HTTP请求时,真实的URL是由base URL 和 path parameter连接而成(通过emqx_resource:query/2,3传递,或者通过请求参数提供)。<br/>
|
||||
示例:`http://localhost:9901/`
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -47,13 +47,13 @@ emqx_connector_mongo {
|
|||
server {
|
||||
desc {
|
||||
en: """
|
||||
The IPv4 or IPv6 address or the hostname to connect to.</br>
|
||||
A host entry has the following form: `Host[:Port]`.</br>
|
||||
The IPv4 or IPv6 address or the hostname to connect to.<br/>
|
||||
A host entry has the following form: `Host[:Port]`.<br/>
|
||||
The MongoDB default port 27017 is used if `[:Port]` is not specified.
|
||||
"""
|
||||
zh: """
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。</br>
|
||||
主机名具有以下形式:`Host[:Port]`。</br>
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。<br/>
|
||||
主机名具有以下形式:`Host[:Port]`。<br/>
|
||||
如果未指定 `[:Port]`,则使用 MongoDB 默认端口 27017。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -2,22 +2,22 @@ emqx_connector_mqtt_schema {
|
|||
mode {
|
||||
desc {
|
||||
en: """
|
||||
The mode of the MQTT Bridge.</br>
|
||||
The mode of the MQTT Bridge.<br/>
|
||||
|
||||
- cluster_shareload: create an MQTT connection on each node in the emqx cluster.</br>
|
||||
- cluster_shareload: create an MQTT connection on each node in the emqx cluster.<br/>
|
||||
In 'cluster_shareload' mode, the incoming load from the remote broker is shared by
|
||||
using shared subscription.</br>
|
||||
using shared subscription.<br/>
|
||||
Note that the 'clientid' is suffixed by the node name, this is to avoid
|
||||
clientid conflicts between different nodes. And we can only use shared subscription
|
||||
topic filters for 'remote_topic' of ingress connections.
|
||||
topic filters for <code>remote_topic</code> of ingress connections.
|
||||
"""
|
||||
zh: """
|
||||
MQTT 桥的模式。 </br>
|
||||
MQTT 桥的模式。 <br/>
|
||||
|
||||
- cluster_shareload:在 emqx 集群的每个节点上创建一个 MQTT 连接。</br>
|
||||
在“cluster_shareload”模式下,来自远程代理的传入负载通过共享订阅的方式接收。</br>
|
||||
请注意,“clientid”以节点名称为后缀,这是为了避免不同节点之间的clientid冲突。
|
||||
而且对于入口连接的“remote_topic”,我们只能使用共享订阅主题过滤器。
|
||||
- cluster_shareload:在 emqx 集群的每个节点上创建一个 MQTT 连接。<br/>
|
||||
在“cluster_shareload”模式下,来自远程代理的传入负载通过共享订阅的方式接收。<br/>
|
||||
请注意,<code>clientid</code> 以节点名称为后缀,这是为了避免不同节点之间的clientid冲突。
|
||||
而且对于入口连接的 <code>remote_topic</code>,我们只能使用共享订阅主题过滤器。
|
||||
"""
|
||||
}
|
||||
label: {
|
||||
|
@ -135,11 +135,11 @@ broker MUST support this feature.
|
|||
ingress_local_topic {
|
||||
desc {
|
||||
en: """
|
||||
Send messages to which topic of the local broker.</br>
|
||||
Send messages to which topic of the local broker.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
向本地broker的哪个topic发送消息。</br>
|
||||
向本地broker的哪个topic发送消息。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -152,11 +152,11 @@ Template with variables is allowed.
|
|||
ingress_local_qos {
|
||||
desc {
|
||||
en: """
|
||||
The QoS of the MQTT message to be sent.</br>
|
||||
The QoS of the MQTT message to be sent.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
待发送 MQTT 消息的 QoS。</br>
|
||||
待发送 MQTT 消息的 QoS。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -191,11 +191,11 @@ Template with variables is allowed.
|
|||
egress_remote_topic {
|
||||
desc {
|
||||
en: """
|
||||
Forward to which topic of the remote broker.</br>
|
||||
Forward to which topic of the remote broker.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
转发到远程broker的哪个topic。</br>
|
||||
转发到远程broker的哪个topic。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -208,11 +208,11 @@ Template with variables is allowed.
|
|||
egress_remote_qos {
|
||||
desc {
|
||||
en: """
|
||||
The QoS of the MQTT message to be sent.</br>
|
||||
The QoS of the MQTT message to be sent.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
待发送 MQTT 消息的 QoS。</br>
|
||||
待发送 MQTT 消息的 QoS。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -225,11 +225,11 @@ Template with variables is allowed.
|
|||
dir {
|
||||
desc {
|
||||
en: """
|
||||
The dir where the replayq file saved.</br>
|
||||
The dir where the replayq file saved.<br/>
|
||||
Set to 'false' disables the replayq feature.
|
||||
"""
|
||||
zh: """
|
||||
replayq 文件保存的目录。</br>
|
||||
replayq 文件保存的目录。<br/>
|
||||
设置为 'false' 会禁用 replayq 功能。
|
||||
"""
|
||||
}
|
||||
|
@ -242,12 +242,12 @@ replayq 文件保存的目录。</br>
|
|||
seg_bytes {
|
||||
desc {
|
||||
en: """
|
||||
The size in bytes of a single segment.</br>
|
||||
The size in bytes of a single segment.<br/>
|
||||
A segment is mapping to a file in the replayq dir. If the current segment is full, a new segment
|
||||
(file) will be opened to write.
|
||||
"""
|
||||
zh: """
|
||||
单个段的大小(以字节为单位)。</br>
|
||||
单个段的大小(以字节为单位)。<br/>
|
||||
一个段映射到 replayq 目录中的一个文件。 如果当前段已满,则新段(文件)将被打开写入。
|
||||
"""
|
||||
}
|
||||
|
@ -260,12 +260,12 @@ A segment is mapping to a file in the replayq dir. If the current segment is ful
|
|||
offload {
|
||||
desc {
|
||||
en: """
|
||||
In offload mode, the disk queue is only used to offload queue tail segments.</br>
|
||||
In offload mode, the disk queue is only used to offload queue tail segments.<br/>
|
||||
The messages are cached in the memory first, then it writes to the replayq files after the size of
|
||||
the memory cache reaches 'seg_bytes'.
|
||||
"""
|
||||
zh: """
|
||||
在Offload模式下,磁盘队列仅用于卸载队列尾段。</br>
|
||||
在Offload模式下,磁盘队列仅用于卸载队列尾段。<br/>
|
||||
消息首先缓存在内存中,然后写入replayq文件。内存缓大小为“seg_bytes” 指定的值。
|
||||
"""
|
||||
}
|
||||
|
@ -278,11 +278,11 @@ the memory cache reaches 'seg_bytes'.
|
|||
retain {
|
||||
desc {
|
||||
en: """
|
||||
The 'retain' flag of the MQTT message to be sent.</br>
|
||||
The 'retain' flag of the MQTT message to be sent.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
要发送的 MQTT 消息的“保留”标志。</br>
|
||||
要发送的 MQTT 消息的“保留”标志。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -295,11 +295,11 @@ Template with variables is allowed.
|
|||
payload {
|
||||
desc {
|
||||
en: """
|
||||
The payload of the MQTT message to be sent.</br>
|
||||
The payload of the MQTT message to be sent.<br/>
|
||||
Template with variables is allowed.
|
||||
"""
|
||||
zh: """
|
||||
要发送的 MQTT 消息的负载。</br>
|
||||
要发送的 MQTT 消息的负载。<br/>
|
||||
允许使用带有变量的模板。
|
||||
"""
|
||||
}
|
||||
|
@ -323,13 +323,13 @@ Template with variables is allowed.
|
|||
desc_ingress {
|
||||
desc {
|
||||
en: """
|
||||
The ingress config defines how this bridge receive messages from the remote MQTT broker, and then send them to the local broker.</br>
|
||||
Template with variables is allowed in 'local_topic', 'remote_qos', 'qos', 'retain', 'payload'.</br>
|
||||
The ingress config defines how this bridge receive messages from the remote MQTT broker, and then send them to the local broker.<br/>
|
||||
Template with variables is allowed in 'local_topic', 'remote_qos', 'qos', 'retain', 'payload'.<br/>
|
||||
NOTE: if this bridge is used as the input of a rule (emqx rule engine), and also local_topic is configured, then messages got from the remote broker will be sent to both the 'local_topic' and the rule.
|
||||
"""
|
||||
zh: """
|
||||
Ingress 模式定义了这个 bridge 如何从远程 MQTT broker 接收消息,然后将它们发送到本地 broker 。</br>
|
||||
允许带有的模板变量: 'local_topic'、'remote_qos'、'qos'、'retain'、'payload' 。</br>
|
||||
Ingress 模式定义了这个 bridge 如何从远程 MQTT broker 接收消息,然后将它们发送到本地 broker 。<br/>
|
||||
允许带有的模板变量: 'local_topic'、'remote_qos'、'qos'、'retain'、'payload' 。<br/>
|
||||
注意:如果这个 bridge 被用作规则的输入(emqx 规则引擎),并且还配置了 local_topic,那么从远程 broker 获取的消息将同时被发送到 'local_topic' 和规则引擎。
|
||||
"""
|
||||
}
|
||||
|
@ -342,13 +342,13 @@ Ingress 模式定义了这个 bridge 如何从远程 MQTT broker 接收消息,
|
|||
desc_egress {
|
||||
desc {
|
||||
en: """
|
||||
The egress config defines how this bridge forwards messages from the local broker to the remote broker.</br>
|
||||
Template with variables is allowed in 'remote_topic', 'qos', 'retain', 'payload'.</br>
|
||||
The egress config defines how this bridge forwards messages from the local broker to the remote broker.<br/>
|
||||
Template with variables is allowed in 'remote_topic', 'qos', 'retain', 'payload'.<br/>
|
||||
NOTE: if this bridge is used as the action of a rule (emqx rule engine), and also local_topic is configured, then both the data got from the rule and the MQTT messages that matches local_topic will be forwarded.
|
||||
"""
|
||||
zh: """
|
||||
Egress 模式定义了 bridge 如何将消息从本地 broker 转发到远程 broker。</br>
|
||||
允许带有的模板变量: 'remote_topic'、'qos'、'retain'、'payload' 。</br>
|
||||
Egress 模式定义了 bridge 如何将消息从本地 broker 转发到远程 broker。<br/>
|
||||
允许带有的模板变量: 'remote_topic'、'qos'、'retain'、'payload' 。<br/>
|
||||
注意:如果这个 bridge 作为规则(emqx 规则引擎)的输出,并且还配置了 local_topic,那么从规则引擎中获取的数据和匹配 local_topic 的 MQTT 消息都会被转发到远程 broker 。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ emqx_connector_mysql {
|
|||
server {
|
||||
desc {
|
||||
en: """
|
||||
The IPv4 or IPv6 address or the hostname to connect to.</br>
|
||||
A host entry has the following form: `Host[:Port]`.</br>
|
||||
The IPv4 or IPv6 address or the hostname to connect to.<br/>
|
||||
A host entry has the following form: `Host[:Port]`.<br/>
|
||||
The MySQL default port 3306 is used if `[:Port]` is not specified.
|
||||
"""
|
||||
zh: """
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。</br>
|
||||
主机名具有以下形式:`Host[:Port]`。</br>
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。<br/>
|
||||
主机名具有以下形式:`Host[:Port]`。<br/>
|
||||
如果未指定 `[:Port]`,则使用 MySQL 默认端口 3306。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ emqx_connector_pgsql {
|
|||
server {
|
||||
desc {
|
||||
en: """
|
||||
The IPv4 or IPv6 address or the hostname to connect to.</br>
|
||||
A host entry has the following form: `Host[:Port]`.</br>
|
||||
The IPv4 or IPv6 address or the hostname to connect to.<br/>
|
||||
A host entry has the following form: `Host[:Port]`.<br/>
|
||||
The PostgreSQL default port 5432 is used if `[:Port]` is not specified.
|
||||
"""
|
||||
zh: """
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。</br>
|
||||
主机名具有以下形式:`Host[:Port]`。</br>
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。<br/>
|
||||
主机名具有以下形式:`Host[:Port]`。<br/>
|
||||
如果未指定 `[:Port]`,则使用 PostgreSQL 默认端口 5432。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -47,13 +47,13 @@ emqx_connector_redis {
|
|||
server {
|
||||
desc {
|
||||
en: """
|
||||
The IPv4 or IPv6 address or the hostname to connect to.</br>
|
||||
A host entry has the following form: `Host[:Port]`.</br>
|
||||
The IPv4 or IPv6 address or the hostname to connect to.<br/>
|
||||
A host entry has the following form: `Host[:Port]`.<br/>
|
||||
The Redis default port 6379 is used if `[:Port]` is not specified.
|
||||
"""
|
||||
zh: """
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。</br>
|
||||
主机名具有以下形式:`Host[:Port]`。</br>
|
||||
将要连接的 IPv4 或 IPv6 地址,或者主机名。<br/>
|
||||
主机名具有以下形式:`Host[:Port]`。<br/>
|
||||
如果未指定 `[:Port]`,则使用 MongoDB 默认端口 27017。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ emqx_connector_schema {
|
|||
desc_connector {
|
||||
desc {
|
||||
en: """
|
||||
Configuration for EMQX connectors.</br>
|
||||
Configuration for EMQX connectors.<br/>
|
||||
A connector maintains the data related to the external resources, such as MySQL database.
|
||||
"""
|
||||
zh: """
|
||||
EMQX 连接器的配置。</br>
|
||||
EMQX 连接器的配置。<br/>
|
||||
连接器维护与外部资源相关的数据,比如 MySQL 数据库。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -25,14 +25,13 @@
|
|||
-define(PGSQL_DEFAULT_PORT, 5432).
|
||||
|
||||
-define(SERVERS_DESC,
|
||||
"A Node list for Cluster to connect to. The nodes should be separated with commas, such as: `Node[,Node].`\n"
|
||||
"A Node list for Cluster to connect to. The nodes should be separated with commas, such as: `Node[,Node].`<br/>"
|
||||
"For each Node should be: "
|
||||
).
|
||||
|
||||
-define(SERVER_DESC(TYPE, DEFAULT_PORT),
|
||||
"\n"
|
||||
"The IPv4 or IPv6 address or the hostname to connect to.</br>\n"
|
||||
"A host entry has the following form: `Host[:Port]`.</br>\n"
|
||||
"The IPv4 or IPv6 address or the hostname to connect to.<br/>"
|
||||
"A host entry has the following form: `Host[:Port]`.<br/>"
|
||||
"The " ++ TYPE ++ " default port " ++ DEFAULT_PORT ++ " is used if `[:Port]` is not specified."
|
||||
).
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%% -*- mode: erlang -*-
|
||||
{application, emqx_connector, [
|
||||
{description, "An OTP application"},
|
||||
{vsn, "0.1.6"},
|
||||
{vsn, "0.1.7"},
|
||||
{registered, []},
|
||||
{mod, {emqx_connector_app, []}},
|
||||
{applications, [
|
||||
|
|
|
@ -282,9 +282,9 @@ topic_mappings() ->
|
|||
ingress_desc() ->
|
||||
"\n"
|
||||
"The ingress config defines how this bridge receive messages from the remote MQTT broker, and then\n"
|
||||
"send them to the local broker.</br>\n"
|
||||
"send them to the local broker.<br/>"
|
||||
"Template with variables is allowed in 'local_topic', 'remote_qos', 'qos', 'retain',\n"
|
||||
"'payload'.</br>\n"
|
||||
"'payload'.<br/>"
|
||||
"NOTE: if this bridge is used as the input of a rule (emqx rule engine), and also local_topic is\n"
|
||||
"configured, then messages got from the remote broker will be sent to both the 'local_topic' and\n"
|
||||
"the rule.\n".
|
||||
|
@ -292,8 +292,8 @@ ingress_desc() ->
|
|||
egress_desc() ->
|
||||
"\n"
|
||||
"The egress config defines how this bridge forwards messages from the local broker to the remote\n"
|
||||
"broker.</br>\n"
|
||||
"Template with variables is allowed in 'remote_topic', 'qos', 'retain', 'payload'.</br>\n"
|
||||
"broker.<br/>"
|
||||
"Template with variables is allowed in 'remote_topic', 'qos', 'retain', 'payload'.<br/>"
|
||||
"NOTE: if this bridge is used as the action of a rule (emqx rule engine), and also local_topic\n"
|
||||
"is configured, then both the data got from the rule and the MQTT messages that matches\n"
|
||||
"local_topic will be forwarded.\n".
|
||||
|
|
|
@ -441,7 +441,7 @@ trans_description(Spec, Hocon) ->
|
|||
undefined ->
|
||||
Spec;
|
||||
Desc ->
|
||||
Desc1 = binary:replace(Desc, [<<"</br>\n">>, <<"\n">>], <<"</br>">>, [global]),
|
||||
Desc1 = binary:replace(Desc, [<<"\n">>], <<"<br/>">>, [global]),
|
||||
Spec#{description => Desc1}
|
||||
end.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ emqx_gateway_api_authn {
|
|||
|
||||
get_authn {
|
||||
desc {
|
||||
en: """Gets the configuration of the specified gateway authenticator.</br>
|
||||
en: """Gets the configuration of the specified gateway authenticator.<br/>
|
||||
Returns 404 when gateway or authentication is not enabled."""
|
||||
zh: """获取指定网关认证器的配置
|
||||
当网关或认证未启用时,返回 404。"""
|
||||
|
@ -18,11 +18,11 @@ Returns 404 when gateway or authentication is not enabled."""
|
|||
|
||||
add_authn {
|
||||
desc {
|
||||
en: """Enables the authenticator for client authentication for the specified gateway. <\br>
|
||||
When the authenticator is not configured or turned off, all client connections are assumed to be allowed. <\br>
|
||||
en: """Enables the authenticator for client authentication for the specified gateway. <br/>
|
||||
When the authenticator is not configured or turned off, all client connections are assumed to be allowed. <br/>
|
||||
Note: Only one authenticator is allowed to be enabled at a time in the gateway, rather than allowing multiple authenticators to be configured to form an authentication chain as in MQTT."""
|
||||
zh: """为指定网关开启认证器实现客户端认证的功能。<\br>
|
||||
当未配置认证器或关闭认证器时,则认为允许所有客户端的连接。<\br>
|
||||
zh: """为指定网关开启认证器实现客户端认证的功能。<br/>
|
||||
当未配置认证器或关闭认证器时,则认为允许所有客户端的连接。<br/>
|
||||
注:在网关中仅支持添加一个认证器,而不是像 MQTT 一样允许配置多个认证器构成认证链。"""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,9 +32,9 @@ including current running status, number of connections, listener status, etc.""
|
|||
|
||||
update_gateway {
|
||||
desc {
|
||||
en: """Update the gateway basic configurations and running status.</br>
|
||||
en: """Update the gateway basic configurations and running status.<br/>
|
||||
Note: The Authentication and Listener configurations should be updated by other special APIs. """
|
||||
zh: """更新指定网关的基础配置、和启用的状态。</br>
|
||||
zh: """更新指定网关的基础配置、和启用的状态。<br/>
|
||||
注:认证、和监听器的配置更新需参考对应的 API 接口。"""
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ Note: The Authentication and Listener configurations should be updated by other
|
|||
|
||||
gateway_name_in_qs {
|
||||
desc {
|
||||
en: """Gateway Name.</br>
|
||||
en: """Gateway Name.<br/>
|
||||
It's enum with `stomp`, `mqttsn`, `coap`, `lwm2m`, `exproto`
|
||||
"""
|
||||
zh: """网关名称.</br>
|
||||
zh: """网关名称.<br/>
|
||||
可取值为 `stomp`、`mqttsn`、`coap`、`lwm2m`、`exproto`
|
||||
"""
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ It's enum with `stomp`, `mqttsn`, `coap`, `lwm2m`, `exproto`
|
|||
|
||||
gateway_status_in_qs {
|
||||
desc {
|
||||
en: """Filter gateways by status.</br>
|
||||
en: """Filter gateways by status.<br/>
|
||||
It is enum with `running`, `stopped`, `unloaded`"""
|
||||
zh: """通过网关状态筛选</br>
|
||||
zh: """通过网关状态筛选<br/>
|
||||
可选值为 `running`、`stopped`、`unloaded`"""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ emqx_gateway_api_listeners {
|
|||
|
||||
add_listener {
|
||||
desc {
|
||||
en: """Create the gateway listener.</br>
|
||||
en: """Create the gateway listener.<br/>
|
||||
Note: For listener types not supported by a gateway, this API returns `400: BAD_REQUEST`."""
|
||||
zh: """为指定网关添加监听器。</br>
|
||||
zh: """为指定网关添加监听器。<br/>
|
||||
注:对于某网关不支持的监听器类型,该接口会返回 `400: BAD_REQUEST`。"""
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +46,9 @@ Note: For listener types not supported by a gateway, this API returns `400: BAD_
|
|||
|
||||
add_listener_authn {
|
||||
desc {
|
||||
en: """Enable authenticator for specified listener for client authentication.</br>
|
||||
en: """Enable authenticator for specified listener for client authentication.<br/>
|
||||
When authenticator is enabled for a listener, all clients connecting to that listener will use that authenticator for authentication."""
|
||||
zh: """为指定监听器开启认证器以实现客户端认证的能力。</br>
|
||||
zh: """为指定监听器开启认证器以实现客户端认证的能力。<br/>
|
||||
当某一监听器开启认证后,所有连接到该监听器的客户端会使用该认证器进行认证。"""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ This option specifies the QoS level for the CoAP Client when establishing a subs
|
|||
"""
|
||||
zh: """客户端订阅请求的默认 QoS 等级。
|
||||
当 CoAP 客户端发起订阅请求时,如果未携带 `qos` 参数则会使用该默认值。默认值可设置为:
|
||||
- qos0, qos1, qos2: 设置为固定的 QoS 等级
|
||||
- qos0、 qos1、qos2: 设置为固定的 QoS 等级
|
||||
- coap: 依据订阅操作的 CoAP 报文类型来动态决定
|
||||
* 当订阅请求为 `non-confirmable` 类型时,取值为 qos0
|
||||
* 当订阅请求为 `confirmable` 类型时,取值为 qos1
|
||||
|
@ -165,7 +165,7 @@ This option specifies the QoS level for the CoAP Client when publishing a messag
|
|||
|
||||
zh: """客户端发布请求的默认 QoS 等级。
|
||||
当 CoAP 客户端发起发布请求时,如果未携带 `qos` 参数则会使用该默认值。默认值可设置为:
|
||||
- qos0, qos1, qos2: 设置为固定的 QoS 等级
|
||||
- qos0、qos1、qos2: 设置为固定的 QoS 等级
|
||||
- coap: 依据发布操作的 CoAP 报文类型来动态决定
|
||||
* 当发布请求为 `non-confirmable` 类型时,取值为 qos0
|
||||
* 当发布请求为 `confirmable` 类型时,取值为 qos1
|
||||
|
@ -175,29 +175,29 @@ This option specifies the QoS level for the CoAP Client when publishing a messag
|
|||
|
||||
lwm2m {
|
||||
desc {
|
||||
en: """The LwM2M Gateway configuration. This gateway only supports the v1.0.1 protocol"""
|
||||
zh: """LwM2M 网关配置。仅支持 v1.0.1 协议"""
|
||||
en: """The LwM2M Gateway configuration. This gateway only supports the v1.0.1 protocol."""
|
||||
zh: """LwM2M 网关配置。仅支持 v1.0.1 协议。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_xml_dir {
|
||||
desc {
|
||||
en: """The Directory for LwM2M Resource definition"""
|
||||
zh: """LwM2M Resource 定义的 XML 文件目录路径"""
|
||||
en: """The Directory for LwM2M Resource definition."""
|
||||
zh: """LwM2M Resource 定义的 XML 文件目录路径。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_lifetime_min {
|
||||
desc {
|
||||
en: """Minimum value of lifetime allowed to be set by the LwM2M client"""
|
||||
zh: """允许 LwM2M 客户端允许设置的心跳最小值"""
|
||||
en: """Minimum value of lifetime allowed to be set by the LwM2M client."""
|
||||
zh: """允许 LwM2M 客户端允许设置的心跳最小值。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_lifetime_max {
|
||||
desc {
|
||||
en: """Maximum value of lifetime allowed to be set by the LwM2M client"""
|
||||
zh: """允许 LwM2M 客户端允许设置的心跳最大值"""
|
||||
en: """Maximum value of lifetime allowed to be set by the LwM2M client."""
|
||||
zh: """允许 LwM2M 客户端允许设置的心跳最大值。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,14 +207,14 @@ This option specifies the QoS level for the CoAP Client when publishing a messag
|
|||
For example, after receiving an update message from a client, any messages within this time window are sent directly to the LwM2M client, and all messages beyond this time window are temporarily stored in memory."""
|
||||
|
||||
zh: """在QMode模式下,LwM2M网关认为网络链接有效的时间窗口的值。
|
||||
例如,在收到客户端的更新信息后,在这个时间窗口内的任何信息都会直接发送到LwM2M客户端,而超过这个时间窗口的所有信息都会暂时储存在内存中"""
|
||||
例如,在收到客户端的更新信息后,在这个时间窗口内的任何信息都会直接发送到LwM2M客户端,而超过这个时间窗口的所有信息都会暂时储存在内存中。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_auto_observe {
|
||||
desc {
|
||||
en: """Automatically observe the object list of REGISTER packet"""
|
||||
zh: """自动 Observe REGISTER 数据包的 Object 列表"""
|
||||
en: """Automatically observe the object list of REGISTER packet."""
|
||||
zh: """自动 Observe REGISTER 数据包的 Object 列表。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,15 +226,15 @@ For example, after receiving an update message from a client, any messages withi
|
|||
"""
|
||||
zh: """发布UPDATE事件消息的策略。
|
||||
- always: 只要收到 UPDATE 请求,就发送更新事件。
|
||||
- contains_object_list: 仅当 UPDATE 请求携带 Object 列表时才发送更新事件
|
||||
- contains_object_list: 仅当 UPDATE 请求携带 Object 列表时才发送更新事件。
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_translators {
|
||||
desc {
|
||||
en: """Topic configuration for LwM2M's gateway publishing and subscription"""
|
||||
zh: """LwM2M 网关订阅/发布消息的主题映射配置"""
|
||||
en: """Topic configuration for LwM2M's gateway publishing and subscription."""
|
||||
zh: """LwM2M 网关订阅/发布消息的主题映射配置。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,14 +244,14 @@ For example, after receiving an update message from a client, any messages withi
|
|||
For each new LwM2M client that succeeds in going online, the gateway creates a subscription relationship to receive downstream commands and send it to the LwM2M client"""
|
||||
|
||||
zh: """下行命令主题。
|
||||
对于每个成功上线的新 LwM2M 客户端,网关会创建一个订阅关系来接收下行消息并将其发送给客户端"""
|
||||
对于每个成功上线的新 LwM2M 客户端,网关会创建一个订阅关系来接收下行消息并将其发送给客户端。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_translators_response {
|
||||
desc {
|
||||
en: """The topic for gateway to publish the acknowledge events from LwM2M client"""
|
||||
zh: """用于网关发布来自 LwM2M 客户端的确认事件的主题"""
|
||||
zh: """用于网关发布来自 LwM2M 客户端的确认事件的主题。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,28 +261,28 @@ For each new LwM2M client that succeeds in going online, the gateway creates a s
|
|||
After succeed observe a resource of LwM2M client, Gateway will send the notify events via this topic, if the client reports any resource changes"""
|
||||
|
||||
zh: """用于发布来自 LwM2M 客户端的通知事件的主题。
|
||||
在成功 Observe 到 LwM2M 客户端的资源后,如果客户端报告任何资源状态的变化,网关将通过该主题发送通知事件"""
|
||||
在成功 Observe 到 LwM2M 客户端的资源后,如果客户端报告任何资源状态的变化,网关将通过该主题发送通知事件。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_translators_register {
|
||||
desc {
|
||||
en: """The topic for gateway to publish the register events from LwM2M client."""
|
||||
zh: """用于发布来自 LwM2M 客户端的注册事件的主题"""
|
||||
zh: """用于发布来自 LwM2M 客户端的注册事件的主题。"""
|
||||
}
|
||||
}
|
||||
|
||||
lwm2m_translators_update {
|
||||
desc {
|
||||
en: """The topic for gateway to publish the update events from LwM2M client"""
|
||||
zh: """用于发布来自LwM2M客户端的更新事件的主题"""
|
||||
zh: """用于发布来自LwM2M客户端的更新事件的主题。"""
|
||||
}
|
||||
}
|
||||
|
||||
translator {
|
||||
desc {
|
||||
en: """MQTT topic that corresponds to a particular type of event."""
|
||||
zh: """配置某网关客户端对于发布消息或订阅的主题和 QoS 等级"""
|
||||
zh: """配置某网关客户端对于发布消息或订阅的主题和 QoS 等级。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,28 +412,28 @@ After succeed observe a resource of LwM2M client, Gateway will send the notify e
|
|||
gateway_common_authentication {
|
||||
desc {
|
||||
en: """Default authentication configs for all the gateway listeners. For per-listener overrides see <code>authentication</code>\n in listener configs"""
|
||||
zh: """网关的认证器配置,对该网关下所以的监听器生效。如果每个监听器需要配置不同的认证器,需要配置监听器下的 <code>authentication</code> 字段"""
|
||||
zh: """网关的认证器配置,对该网关下所以的监听器生效。如果每个监听器需要配置不同的认证器,需要配置监听器下的 <code>authentication</code> 字段。"""
|
||||
}
|
||||
}
|
||||
|
||||
tcp_udp_listeners {
|
||||
desc {
|
||||
en: """Settings for the listeners."""
|
||||
zh: """监听器配置"""
|
||||
zh: """监听器配置。"""
|
||||
}
|
||||
}
|
||||
|
||||
tcp_listeners {
|
||||
desc {
|
||||
en: """Settings for the TCP listeners."""
|
||||
zh: """配置 TCP 类型的监听器"""
|
||||
zh: """配置 TCP 类型的监听器。"""
|
||||
}
|
||||
}
|
||||
|
||||
udp_listeners {
|
||||
desc {
|
||||
en: """Settings for the UDP listeners."""
|
||||
zh: """配置 UDP 类型的监听器"""
|
||||
zh: """配置 UDP 类型的监听器。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,7 @@ After succeed observe a resource of LwM2M client, Gateway will send the notify e
|
|||
tcp_listener_tcp_opts{
|
||||
desc {
|
||||
en: """Setting the TCP socket options."""
|
||||
zh: """TCP Socket 配置"""
|
||||
zh: """TCP Socket 配置。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ EMQX will close the TCP connection if proxy protocol packet is not received with
|
|||
ssl_listener_options {
|
||||
desc {
|
||||
en: """SSL Socket options."""
|
||||
zh: """SSL Socket 配置"""
|
||||
zh: """SSL Socket 配置。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,7 +498,7 @@ EMQX will close the TCP connection if proxy protocol packet is not received with
|
|||
udp_listener_udp_opts {
|
||||
desc {
|
||||
en: """Settings for the UDP sockets."""
|
||||
zh: """UDP Socket 配置 """
|
||||
zh: """UDP Socket 配置。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,7 +535,7 @@ See: https://erlang.org/doc/man/inet.html#setopts-2"""
|
|||
udp_listener_reuseaddr {
|
||||
desc {
|
||||
en: """Allow local reuse of port numbers."""
|
||||
zh: """允许重用本地处于 TIME_WAIT 的端口号"""
|
||||
zh: """允许重用本地处于 TIME_WAIT 的端口号。"""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,9 +118,11 @@ list_nodes() ->
|
|||
Running = mria_mnesia:cluster_nodes(running),
|
||||
Stopped = mria_mnesia:cluster_nodes(stopped),
|
||||
DownNodes = lists:map(fun stopped_node_info/1, Stopped),
|
||||
[{Node, node_info(Node)} || Node <- Running] ++ DownNodes.
|
||||
[{Node, Info} || #{node := Node} = Info <- node_info(Running)] ++ DownNodes.
|
||||
|
||||
lookup_node(Node) -> node_info(Node).
|
||||
lookup_node(Node) ->
|
||||
[Info] = node_info([Node]),
|
||||
Info.
|
||||
|
||||
node_info() ->
|
||||
{UsedRatio, Total} = get_sys_memory(),
|
||||
|
@ -152,8 +154,8 @@ get_sys_memory() ->
|
|||
{0, 0}
|
||||
end.
|
||||
|
||||
node_info(Node) ->
|
||||
wrap_rpc(emqx_management_proto_v2:node_info(Node)).
|
||||
node_info(Nodes) ->
|
||||
emqx_rpc:unwrap_erpc(emqx_management_proto_v3:node_info(Nodes)).
|
||||
|
||||
stopped_node_info(Node) ->
|
||||
#{name => Node, node_status => 'stopped'}.
|
||||
|
@ -163,17 +165,19 @@ stopped_node_info(Node) ->
|
|||
%%--------------------------------------------------------------------
|
||||
|
||||
list_brokers() ->
|
||||
[{Node, broker_info(Node)} || Node <- mria_mnesia:running_nodes()].
|
||||
Running = mria_mnesia:running_nodes(),
|
||||
[{Node, Broker} || #{node := Node} = Broker <- broker_info(Running)].
|
||||
|
||||
lookup_broker(Node) ->
|
||||
broker_info(Node).
|
||||
[Broker] = broker_info([Node]),
|
||||
Broker.
|
||||
|
||||
broker_info() ->
|
||||
Info = maps:from_list([{K, iolist_to_binary(V)} || {K, V} <- emqx_sys:info()]),
|
||||
Info#{node => node(), otp_release => otp_rel(), node_status => 'Running'}.
|
||||
|
||||
broker_info(Node) ->
|
||||
wrap_rpc(emqx_management_proto_v2:broker_info(Node)).
|
||||
broker_info(Nodes) ->
|
||||
emqx_rpc:unwrap_erpc(emqx_management_proto_v3:broker_info(Nodes)).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Metrics and Stats
|
||||
|
@ -183,7 +187,7 @@ get_metrics() ->
|
|||
nodes_info_count([get_metrics(Node) || Node <- mria_mnesia:running_nodes()]).
|
||||
|
||||
get_metrics(Node) ->
|
||||
wrap_rpc(emqx_proto_v1:get_metrics(Node)).
|
||||
unwrap_rpc(emqx_proto_v1:get_metrics(Node)).
|
||||
|
||||
get_stats() ->
|
||||
GlobalStatsKeys =
|
||||
|
@ -211,7 +215,7 @@ delete_keys(List, [Key | Keys]) ->
|
|||
delete_keys(proplists:delete(Key, List), Keys).
|
||||
|
||||
get_stats(Node) ->
|
||||
wrap_rpc(emqx_proto_v1:get_stats(Node)).
|
||||
unwrap_rpc(emqx_proto_v1:get_stats(Node)).
|
||||
|
||||
nodes_info_count(PropList) ->
|
||||
NodeCount =
|
||||
|
@ -241,7 +245,7 @@ lookup_client({username, Username}, FormatFun) ->
|
|||
]).
|
||||
|
||||
lookup_client(Node, Key, {M, F}) ->
|
||||
case wrap_rpc(emqx_cm_proto_v1:lookup_client(Node, Key)) of
|
||||
case unwrap_rpc(emqx_cm_proto_v1:lookup_client(Node, Key)) of
|
||||
{error, Err} ->
|
||||
{error, Err};
|
||||
L ->
|
||||
|
@ -264,7 +268,7 @@ kickout_client({ClientID, FormatFun}) ->
|
|||
end.
|
||||
|
||||
kickout_client(Node, ClientId) ->
|
||||
wrap_rpc(emqx_cm_proto_v1:kickout_client(Node, ClientId)).
|
||||
unwrap_rpc(emqx_cm_proto_v1:kickout_client(Node, ClientId)).
|
||||
|
||||
list_authz_cache(ClientId) ->
|
||||
call_client(ClientId, list_authz_cache).
|
||||
|
@ -284,14 +288,14 @@ list_client_subscriptions(ClientId) ->
|
|||
end.
|
||||
|
||||
client_subscriptions(Node, ClientId) ->
|
||||
{Node, wrap_rpc(emqx_broker_proto_v1:list_client_subscriptions(Node, ClientId))}.
|
||||
{Node, unwrap_rpc(emqx_broker_proto_v1:list_client_subscriptions(Node, ClientId))}.
|
||||
|
||||
clean_authz_cache(ClientId) ->
|
||||
Results = [clean_authz_cache(Node, ClientId) || Node <- mria_mnesia:running_nodes()],
|
||||
check_results(Results).
|
||||
|
||||
clean_authz_cache(Node, ClientId) ->
|
||||
wrap_rpc(emqx_proto_v1:clean_authz_cache(Node, ClientId)).
|
||||
unwrap_rpc(emqx_proto_v1:clean_authz_cache(Node, ClientId)).
|
||||
|
||||
clean_authz_cache_all() ->
|
||||
Results = [{Node, clean_authz_cache_all(Node)} || Node <- mria_mnesia:running_nodes()],
|
||||
|
@ -308,10 +312,10 @@ wrap_results(Results) ->
|
|||
end.
|
||||
|
||||
clean_authz_cache_all(Node) ->
|
||||
wrap_rpc(emqx_proto_v1:clean_authz_cache(Node)).
|
||||
unwrap_rpc(emqx_proto_v1:clean_authz_cache(Node)).
|
||||
|
||||
clean_pem_cache_all(Node) ->
|
||||
wrap_rpc(emqx_proto_v1:clean_pem_cache(Node)).
|
||||
unwrap_rpc(emqx_proto_v1:clean_pem_cache(Node)).
|
||||
|
||||
set_ratelimit_policy(ClientId, Policy) ->
|
||||
call_client(ClientId, {ratelimit, Policy}).
|
||||
|
@ -357,7 +361,7 @@ do_call_client(ClientId, Req) ->
|
|||
|
||||
%% @private
|
||||
call_client(Node, ClientId, Req) ->
|
||||
wrap_rpc(emqx_management_proto_v2:call_client(Node, ClientId, Req)).
|
||||
unwrap_rpc(emqx_management_proto_v3:call_client(Node, ClientId, Req)).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Subscriptions
|
||||
|
@ -376,7 +380,7 @@ do_list_subscriptions() ->
|
|||
end.
|
||||
|
||||
list_subscriptions(Node) ->
|
||||
wrap_rpc(emqx_management_proto_v2:list_subscriptions(Node)).
|
||||
unwrap_rpc(emqx_management_proto_v3:list_subscriptions(Node)).
|
||||
|
||||
list_subscriptions_via_topic(Topic, FormatFun) ->
|
||||
lists:append([
|
||||
|
@ -385,7 +389,7 @@ list_subscriptions_via_topic(Topic, FormatFun) ->
|
|||
]).
|
||||
|
||||
list_subscriptions_via_topic(Node, Topic, _FormatFun = {M, F}) ->
|
||||
case wrap_rpc(emqx_broker_proto_v1:list_subscriptions_via_topic(Node, Topic)) of
|
||||
case unwrap_rpc(emqx_broker_proto_v1:list_subscriptions_via_topic(Node, Topic)) of
|
||||
{error, Reason} -> {error, Reason};
|
||||
Result -> M:F(Result)
|
||||
end.
|
||||
|
@ -394,7 +398,7 @@ lookup_subscriptions(ClientId) ->
|
|||
lists:append([lookup_subscriptions(Node, ClientId) || Node <- mria_mnesia:running_nodes()]).
|
||||
|
||||
lookup_subscriptions(Node, ClientId) ->
|
||||
wrap_rpc(emqx_broker_proto_v1:list_client_subscriptions(Node, ClientId)).
|
||||
unwrap_rpc(emqx_broker_proto_v1:list_client_subscriptions(Node, ClientId)).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% PubSub
|
||||
|
@ -404,7 +408,7 @@ subscribe(ClientId, TopicTables) ->
|
|||
subscribe(mria_mnesia:running_nodes(), ClientId, TopicTables).
|
||||
|
||||
subscribe([Node | Nodes], ClientId, TopicTables) ->
|
||||
case wrap_rpc(emqx_management_proto_v2:subscribe(Node, ClientId, TopicTables)) of
|
||||
case unwrap_rpc(emqx_management_proto_v3:subscribe(Node, ClientId, TopicTables)) of
|
||||
{error, _} -> subscribe(Nodes, ClientId, TopicTables);
|
||||
{subscribe, Res} -> {subscribe, Res, Node}
|
||||
end;
|
||||
|
@ -431,7 +435,7 @@ unsubscribe(ClientId, Topic) ->
|
|||
-spec unsubscribe([node()], emqx_types:clientid(), emqx_types:topic()) ->
|
||||
{unsubscribe, _} | {error, channel_not_found}.
|
||||
unsubscribe([Node | Nodes], ClientId, Topic) ->
|
||||
case wrap_rpc(emqx_management_proto_v2:unsubscribe(Node, ClientId, Topic)) of
|
||||
case unwrap_rpc(emqx_management_proto_v3:unsubscribe(Node, ClientId, Topic)) of
|
||||
{error, _} -> unsubscribe(Nodes, ClientId, Topic);
|
||||
Re -> Re
|
||||
end;
|
||||
|
@ -454,7 +458,7 @@ unsubscribe_batch(ClientId, Topics) ->
|
|||
-spec unsubscribe_batch([node()], emqx_types:clientid(), [emqx_types:topic()]) ->
|
||||
{unsubscribe_batch, _} | {error, channel_not_found}.
|
||||
unsubscribe_batch([Node | Nodes], ClientId, Topics) ->
|
||||
case wrap_rpc(emqx_management_proto_v2:unsubscribe_batch(Node, ClientId, Topics)) of
|
||||
case unwrap_rpc(emqx_management_proto_v3:unsubscribe_batch(Node, ClientId, Topics)) of
|
||||
{error, _} -> unsubscribe_batch(Nodes, ClientId, Topics);
|
||||
Re -> Re
|
||||
end;
|
||||
|
@ -477,16 +481,16 @@ get_alarms(Type) ->
|
|||
[{Node, get_alarms(Node, Type)} || Node <- mria_mnesia:running_nodes()].
|
||||
|
||||
get_alarms(Node, Type) ->
|
||||
add_duration_field(wrap_rpc(emqx_proto_v1:get_alarms(Node, Type))).
|
||||
add_duration_field(unwrap_rpc(emqx_proto_v1:get_alarms(Node, Type))).
|
||||
|
||||
deactivate(Node, Name) ->
|
||||
wrap_rpc(emqx_proto_v1:deactivate_alarm(Node, Name)).
|
||||
unwrap_rpc(emqx_proto_v1:deactivate_alarm(Node, Name)).
|
||||
|
||||
delete_all_deactivated_alarms() ->
|
||||
[delete_all_deactivated_alarms(Node) || Node <- mria_mnesia:running_nodes()].
|
||||
|
||||
delete_all_deactivated_alarms(Node) ->
|
||||
wrap_rpc(emqx_proto_v1:delete_all_deactivated_alarms(Node)).
|
||||
unwrap_rpc(emqx_proto_v1:delete_all_deactivated_alarms(Node)).
|
||||
|
||||
add_duration_field(Alarms) ->
|
||||
Now = erlang:system_time(microsecond),
|
||||
|
@ -523,10 +527,9 @@ delete_banned(Who) ->
|
|||
%%--------------------------------------------------------------------
|
||||
%% Internal Functions.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
wrap_rpc({badrpc, Reason}) ->
|
||||
unwrap_rpc({badrpc, Reason}) ->
|
||||
{error, Reason};
|
||||
wrap_rpc(Res) ->
|
||||
unwrap_rpc(Res) ->
|
||||
Res.
|
||||
|
||||
otp_rel() ->
|
||||
|
@ -546,7 +549,7 @@ check_row_limit([Tab | Tables], Limit) ->
|
|||
check_results(Results) ->
|
||||
case lists:any(fun(Item) -> Item =:= ok end, Results) of
|
||||
true -> ok;
|
||||
false -> wrap_rpc(lists:last(Results))
|
||||
false -> unwrap_rpc(lists:last(Results))
|
||||
end.
|
||||
|
||||
max_row_limit() ->
|
||||
|
|
|
@ -115,7 +115,7 @@ schema("/configs_reset/:rootname") ->
|
|||
tags => ?TAGS,
|
||||
description =>
|
||||
<<
|
||||
"Reset the config entry specified by the query string parameter `conf_path`.</br>\n"
|
||||
"Reset the config entry specified by the query string parameter `conf_path`.<br/>"
|
||||
"- For a config entry that has default value, this resets it to the default value;\n"
|
||||
"- For a config entry that has no default value, an error 400 will be returned"
|
||||
>>,
|
||||
|
|
|
@ -70,8 +70,8 @@ schema("/plugins") ->
|
|||
'operationId' => list_plugins,
|
||||
get => #{
|
||||
description =>
|
||||
"List all install plugins.</br>"
|
||||
"Plugins are launched in top-down order.</br>"
|
||||
"List all install plugins.<br/>"
|
||||
"Plugins are launched in top-down order.<br/>"
|
||||
"Using `POST /plugins/{name}/move` to change the boot order.",
|
||||
tags => ?TAGS,
|
||||
responses => #{
|
||||
|
@ -136,9 +136,9 @@ schema("/plugins/:name/:action") ->
|
|||
'operationId' => update_plugin,
|
||||
put => #{
|
||||
description =>
|
||||
"start/stop a installed plugin.</br>"
|
||||
"- **start**: start the plugin.</br>"
|
||||
"- **stop**: stop the plugin.</br>",
|
||||
"start/stop a installed plugin.<br/>"
|
||||
"- **start**: start the plugin.<br/>"
|
||||
"- **stop**: stop the plugin.<br/>",
|
||||
tags => ?TAGS,
|
||||
parameters => [
|
||||
hoconsc:ref(name),
|
||||
|
@ -272,9 +272,9 @@ fields(running_status) ->
|
|||
{status,
|
||||
hoconsc:mk(hoconsc:enum([running, stopped]), #{
|
||||
desc =>
|
||||
"Install plugin status at runtime</br>"
|
||||
"1. running: plugin is running.</br>"
|
||||
"2. stopped: plugin is stopped.</br>"
|
||||
"Install plugin status at runtime<br/>"
|
||||
"1. running: plugin is running.<br/>"
|
||||
"2. stopped: plugin is stopped.<br/>"
|
||||
})}
|
||||
].
|
||||
|
||||
|
|
|
@ -45,7 +45,16 @@ running_status() ->
|
|||
BrokerStatus = broker_status(),
|
||||
AppStatus = application_status(),
|
||||
Body = io_lib:format("Node ~ts is ~ts~nemqx is ~ts", [node(), BrokerStatus, AppStatus]),
|
||||
{200, #{<<"content-type">> => <<"text/plain">>}, list_to_binary(Body)};
|
||||
StatusCode =
|
||||
case AppStatus of
|
||||
running -> 200;
|
||||
not_running -> 503
|
||||
end,
|
||||
Headers = #{
|
||||
<<"content-type">> => <<"text/plain">>,
|
||||
<<"retry-after">> => <<"15">>
|
||||
},
|
||||
{StatusCode, Headers, list_to_binary(Body)};
|
||||
false ->
|
||||
{503, #{<<"retry-after">> => <<"15">>}, <<>>}
|
||||
end.
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_management_proto_v3).
|
||||
|
||||
-behaviour(emqx_bpapi).
|
||||
|
||||
-export([
|
||||
introduced_in/0,
|
||||
|
||||
node_info/1,
|
||||
broker_info/1,
|
||||
list_subscriptions/1,
|
||||
|
||||
list_listeners/1,
|
||||
subscribe/3,
|
||||
unsubscribe/3,
|
||||
unsubscribe_batch/3,
|
||||
|
||||
call_client/3,
|
||||
|
||||
get_full_config/1
|
||||
]).
|
||||
|
||||
-include_lib("emqx/include/bpapi.hrl").
|
||||
|
||||
introduced_in() ->
|
||||
"5.0.9".
|
||||
|
||||
-spec unsubscribe_batch(node(), emqx_types:clientid(), [emqx_types:topic()]) ->
|
||||
{unsubscribe, _} | {error, _} | {badrpc, _}.
|
||||
unsubscribe_batch(Node, ClientId, Topics) ->
|
||||
rpc:call(Node, emqx_mgmt, do_unsubscribe_batch, [ClientId, Topics]).
|
||||
|
||||
-spec node_info([node()]) -> emqx_rpc:erpc_multicall(map()).
|
||||
node_info(Nodes) ->
|
||||
erpc:multicall(Nodes, emqx_mgmt, node_info, [], 30000).
|
||||
|
||||
-spec broker_info([node()]) -> emqx_rpc:erpc_multicall(map()).
|
||||
broker_info(Nodes) ->
|
||||
erpc:multicall(Nodes, emqx_mgmt, broker_info, [], 30000).
|
||||
|
||||
-spec list_subscriptions(node()) -> [map()] | {badrpc, _}.
|
||||
list_subscriptions(Node) ->
|
||||
rpc:call(Node, emqx_mgmt, do_list_subscriptions, []).
|
||||
|
||||
-spec list_listeners(node()) -> map() | {badrpc, _}.
|
||||
list_listeners(Node) ->
|
||||
rpc:call(Node, emqx_mgmt_api_listeners, do_list_listeners, []).
|
||||
|
||||
-spec subscribe(node(), emqx_types:clientid(), emqx_types:topic_filters()) ->
|
||||
{subscribe, _} | {error, atom()} | {badrpc, _}.
|
||||
subscribe(Node, ClientId, TopicTables) ->
|
||||
rpc:call(Node, emqx_mgmt, do_subscribe, [ClientId, TopicTables]).
|
||||
|
||||
-spec unsubscribe(node(), emqx_types:clientid(), emqx_types:topic()) ->
|
||||
{unsubscribe, _} | {error, _} | {badrpc, _}.
|
||||
unsubscribe(Node, ClientId, Topic) ->
|
||||
rpc:call(Node, emqx_mgmt, do_unsubscribe, [ClientId, Topic]).
|
||||
|
||||
-spec call_client(node(), emqx_types:clientid(), term()) -> term().
|
||||
call_client(Node, ClientId, Req) ->
|
||||
rpc:call(Node, emqx_mgmt, do_call_client, [ClientId, Req]).
|
||||
|
||||
-spec get_full_config(node()) -> map() | list() | {badrpc, _}.
|
||||
get_full_config(Node) ->
|
||||
rpc:call(Node, emqx_mgmt_api_configs, get_full_config, []).
|
|
@ -113,3 +113,51 @@ t_node_metrics_api(_) ->
|
|||
{error, {_, 400, _}},
|
||||
emqx_mgmt_api_test_util:request_api(get, BadNodePath)
|
||||
).
|
||||
|
||||
t_multiple_nodes_api(_) ->
|
||||
net_kernel:start(['node_api@127.0.0.1', longnames]),
|
||||
ct:timetrap({seconds, 120}),
|
||||
snabbkaffe:fix_ct_logging(),
|
||||
Seq1 = list_to_atom(atom_to_list(?MODULE) ++ "1"),
|
||||
Seq2 = list_to_atom(atom_to_list(?MODULE) ++ "2"),
|
||||
Cluster = [{Name, Opts}, {Name1, Opts1}] = cluster([{core, Seq1}, {core, Seq2}]),
|
||||
ct:pal("Starting ~p", [Cluster]),
|
||||
Node1 = emqx_common_test_helpers:start_slave(Name, Opts),
|
||||
Node2 = emqx_common_test_helpers:start_slave(Name1, Opts1),
|
||||
try
|
||||
{200, NodesList} = rpc:call(Node1, emqx_mgmt_api_nodes, nodes, [get, #{}]),
|
||||
All = [Node1, Node2],
|
||||
lists:map(
|
||||
fun(N) ->
|
||||
N1 = maps:get(node, N),
|
||||
?assertEqual(true, lists:member(N1, All))
|
||||
end,
|
||||
NodesList
|
||||
),
|
||||
?assertEqual(2, length(NodesList)),
|
||||
|
||||
{200, Node11} = rpc:call(Node1, emqx_mgmt_api_nodes, node, [
|
||||
get, #{bindings => #{node => Node1}}
|
||||
]),
|
||||
?assertMatch(#{node := Node1}, Node11)
|
||||
after
|
||||
emqx_common_test_helpers:stop_slave(Node1),
|
||||
emqx_common_test_helpers:stop_slave(Node2)
|
||||
end,
|
||||
ok.
|
||||
|
||||
cluster(Specs) ->
|
||||
Env = [{emqx, boot_modules, []}],
|
||||
emqx_common_test_helpers:emqx_cluster(Specs, [
|
||||
{env, Env},
|
||||
{apps, [emqx_conf]},
|
||||
{load_schema, false},
|
||||
{join_to, true},
|
||||
{env_handler, fun
|
||||
(emqx) ->
|
||||
application:set_env(emqx, boot_modules, []),
|
||||
ok;
|
||||
(_) ->
|
||||
ok
|
||||
end}
|
||||
]).
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
-define(HOST, "http://127.0.0.1:18083/").
|
||||
|
||||
%%---------------------------------------------------------------------------------------
|
||||
%% CT boilerplate
|
||||
%%---------------------------------------------------------------------------------------
|
||||
|
||||
all() ->
|
||||
emqx_common_test_helpers:all(?MODULE).
|
||||
|
||||
|
@ -30,8 +36,102 @@ init_per_suite(Config) ->
|
|||
end_per_suite(_) ->
|
||||
emqx_mgmt_api_test_util:end_suite().
|
||||
|
||||
t_status(_Config) ->
|
||||
Path = emqx_mgmt_api_test_util:api_path_without_base_path(["/status"]),
|
||||
Status = io_lib:format("Node ~ts is ~ts~nemqx is ~ts", [node(), started, running]),
|
||||
{ok, Status} = emqx_mgmt_api_test_util:request_api(get, Path),
|
||||
init_per_testcase(t_status_not_ok, Config) ->
|
||||
ok = application:stop(emqx),
|
||||
Config;
|
||||
init_per_testcase(_TestCase, Config) ->
|
||||
Config.
|
||||
|
||||
end_per_testcase(t_status_not_ok, _Config) ->
|
||||
{ok, _} = application:ensure_all_started(emqx),
|
||||
ok;
|
||||
end_per_testcase(_TestCase, _Config) ->
|
||||
ok.
|
||||
|
||||
%%---------------------------------------------------------------------------------------
|
||||
%% Helper fns
|
||||
%%---------------------------------------------------------------------------------------
|
||||
|
||||
do_request(Opts) ->
|
||||
#{
|
||||
path := Path0,
|
||||
method := Method,
|
||||
headers := Headers,
|
||||
body := Body0
|
||||
} = Opts,
|
||||
URL = ?HOST ++ filename:join(Path0),
|
||||
{ok, #{host := Host, port := Port, path := Path}} = emqx_http_lib:uri_parse(URL),
|
||||
%% we must not use `httpc' here, because it keeps retrying when it
|
||||
%% receives a 503 with `retry-after' header, and there's no option
|
||||
%% to stop that behavior...
|
||||
{ok, Gun} = gun:open(Host, Port, #{retry => 0}),
|
||||
{ok, http} = gun:await_up(Gun),
|
||||
Request =
|
||||
fun() ->
|
||||
case Body0 of
|
||||
no_body -> gun:Method(Gun, Path, Headers);
|
||||
{_Encoding, Body} -> gun:Method(Gun, Path, Headers, Body)
|
||||
end
|
||||
end,
|
||||
Ref = Request(),
|
||||
receive
|
||||
{gun_response, Gun, Ref, nofin, StatusCode, Headers1} ->
|
||||
Data = data_loop(Gun, Ref, _Acc = <<>>),
|
||||
#{status_code => StatusCode, headers => maps:from_list(Headers1), body => Data}
|
||||
after 5_000 ->
|
||||
error({timeout, Opts, process_info(self(), messages)})
|
||||
end.
|
||||
|
||||
data_loop(Gun, Ref, Acc) ->
|
||||
receive
|
||||
{gun_data, Gun, Ref, nofin, Data} ->
|
||||
data_loop(Gun, Ref, <<Acc/binary, Data/binary>>);
|
||||
{gun_data, Gun, Ref, fin, Data} ->
|
||||
gun:shutdown(Gun),
|
||||
<<Acc/binary, Data/binary>>
|
||||
after 5000 ->
|
||||
error(timeout)
|
||||
end.
|
||||
|
||||
%%---------------------------------------------------------------------------------------
|
||||
%% Test cases
|
||||
%%---------------------------------------------------------------------------------------
|
||||
|
||||
t_status_ok(_Config) ->
|
||||
#{
|
||||
body := Resp,
|
||||
status_code := StatusCode
|
||||
} = do_request(#{
|
||||
method => get,
|
||||
path => ["status"],
|
||||
headers => [],
|
||||
body => no_body
|
||||
}),
|
||||
?assertEqual(200, StatusCode),
|
||||
?assertMatch(
|
||||
{match, _},
|
||||
re:run(Resp, <<"emqx is running$">>)
|
||||
),
|
||||
ok.
|
||||
|
||||
t_status_not_ok(_Config) ->
|
||||
#{
|
||||
body := Resp,
|
||||
headers := Headers,
|
||||
status_code := StatusCode
|
||||
} = do_request(#{
|
||||
method => get,
|
||||
path => ["status"],
|
||||
headers => [],
|
||||
body => no_body
|
||||
}),
|
||||
?assertEqual(503, StatusCode),
|
||||
?assertMatch(
|
||||
{match, _},
|
||||
re:run(Resp, <<"emqx is not_running$">>)
|
||||
),
|
||||
?assertMatch(
|
||||
#{<<"retry-after">> := <<"15">>},
|
||||
Headers
|
||||
),
|
||||
ok.
|
||||
|
|
|
@ -2,14 +2,14 @@ emqx_plugins_schema {
|
|||
plugins {
|
||||
desc {
|
||||
en: """
|
||||
Manage EMQX plugins.</br>
|
||||
Manage EMQX plugins.<br/>
|
||||
Plugins can be pre-built as a part of EMQX package,
|
||||
or installed as a standalone package in a location specified by
|
||||
<code>install_dir</code> config key</br>
|
||||
<code>install_dir</code> config key<br/>
|
||||
The standalone-installed plugins are referred to as 'external' plugins.
|
||||
"""
|
||||
zh: """管理EMQX插件。</br>
|
||||
插件可以是EMQX安装包中的一部分,也可以是一个独立的安装包。</br>
|
||||
zh: """管理EMQX插件。<br/>
|
||||
插件可以是EMQX安装包中的一部分,也可以是一个独立的安装包。<br/>
|
||||
独立安装的插件称为“外部插件”。
|
||||
"""
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ The standalone-installed plugins are referred to as 'external' plugins.
|
|||
}
|
||||
name_vsn {
|
||||
desc {
|
||||
en: """The {name}-{version} of the plugin.</br>
|
||||
It should match the plugin application name-version as the for the plugin release package name</br>
|
||||
en: """The {name}-{version} of the plugin.<br/>
|
||||
It should match the plugin application name-version as the for the plugin release package name<br/>
|
||||
For example: my_plugin-0.1.0.
|
||||
"""
|
||||
zh: """插件的名称{name}-{version}。</br>
|
||||
zh: """插件的名称{name}-{version}。<br/>
|
||||
它应该与插件的发布包名称一致,如my_plugin-0.1.0。"""
|
||||
}
|
||||
label {
|
||||
|
@ -54,7 +54,7 @@ For example: my_plugin-0.1.0.
|
|||
}
|
||||
states {
|
||||
desc {
|
||||
en: """An array of plugins in the desired states.</br>
|
||||
en: """An array of plugins in the desired states.<br/>
|
||||
The plugins are started in the defined order"""
|
||||
zh: """一组插件的状态。插件将按照定义的顺序启动"""
|
||||
}
|
||||
|
@ -69,11 +69,11 @@ The plugins are started in the defined order"""
|
|||
The installation directory for the external plugins.
|
||||
The plugin beam files and configuration files should reside in
|
||||
the subdirectory named as <code>emqx_foo_bar-0.1.0</code>.
|
||||
</br>
|
||||
<br/>
|
||||
NOTE: For security reasons, this directory should **NOT** be writable
|
||||
by anyone except <code>emqx</code> (or any user which runs EMQX).
|
||||
"""
|
||||
zh: "插件安装包的目录, 不要自己创建, 只能由emqx用户创建与修改"
|
||||
zh: "插件安装包的目录,出于安全考虑,该目录应该值允许 <code>emqx</code>,或用于运行 EMQX 服务的用户拥有写入权限。"
|
||||
}
|
||||
label {
|
||||
en: "Install Directory"
|
||||
|
@ -82,10 +82,10 @@ by anyone except <code>emqx</code> (or any user which runs EMQX).
|
|||
}
|
||||
check_interval {
|
||||
desc {
|
||||
en: """Check interval: check if the status of the plugins in the cluster is consistent, </br>
|
||||
en: """Check interval: check if the status of the plugins in the cluster is consistent, <br/>
|
||||
if the results of 3 consecutive checks are not consistent, then alarm.
|
||||
"""
|
||||
zh: """检查间隔:检查集群中插件的状态是否一致,</br>
|
||||
zh: """检查间隔:检查集群中插件的状态是否一致,<br/>
|
||||
如果连续3次检查结果不一致,则报警。
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
-define(APP, emqx_prometheus).
|
||||
-define(PROMETHEUS, [prometheus]).
|
||||
|
|
|
@ -37,18 +37,8 @@
|
|||
]
|
||||
).
|
||||
|
||||
-export([
|
||||
update/1,
|
||||
start/0,
|
||||
stop/0,
|
||||
restart/0,
|
||||
% for rpc
|
||||
do_start/0,
|
||||
do_stop/0
|
||||
]).
|
||||
|
||||
%% APIs
|
||||
-export([start_link/1]).
|
||||
-export([start_link/1, info/0]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([
|
||||
|
@ -69,88 +59,69 @@
|
|||
|
||||
-export([collect/1]).
|
||||
|
||||
-export([
|
||||
%% For bpapi, deprecated_since 5.0.10, remove this when 5.1.x
|
||||
do_start/0,
|
||||
do_stop/0
|
||||
]).
|
||||
|
||||
-define(C(K, L), proplists:get_value(K, L, 0)).
|
||||
|
||||
-define(TIMER_MSG, '#interval').
|
||||
|
||||
-record(state, {push_gateway, timer, interval}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% update new config
|
||||
update(Config) ->
|
||||
case
|
||||
emqx_conf:update(
|
||||
[prometheus],
|
||||
Config,
|
||||
#{rawconf_with_defaults => true, override_to => cluster}
|
||||
)
|
||||
of
|
||||
{ok, #{raw_config := NewConfigRows}} ->
|
||||
case maps:get(<<"enable">>, Config, true) of
|
||||
true ->
|
||||
ok = restart();
|
||||
false ->
|
||||
ok = stop()
|
||||
end,
|
||||
{ok, NewConfigRows};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
start() ->
|
||||
{_, []} = emqx_prometheus_proto_v1:start(mria_mnesia:running_nodes()),
|
||||
ok.
|
||||
|
||||
stop() ->
|
||||
{_, []} = emqx_prometheus_proto_v1:stop(mria_mnesia:running_nodes()),
|
||||
ok.
|
||||
|
||||
restart() ->
|
||||
ok = stop(),
|
||||
ok = start().
|
||||
|
||||
do_start() ->
|
||||
emqx_prometheus_sup:start_child(?APP, emqx_conf:get([prometheus])).
|
||||
|
||||
do_stop() ->
|
||||
case emqx_prometheus_sup:stop_child(?APP) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, not_found} ->
|
||||
ok
|
||||
end.
|
||||
-define(HTTP_OPTIONS, [{autoredirect, true}, {timeout, 60000}]).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% APIs
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
start_link(Opts) ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
|
||||
start_link([]) ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
|
||||
info() ->
|
||||
gen_server:call(?MODULE, info).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% gen_server callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init([Opts]) ->
|
||||
Interval = maps:get(interval, Opts),
|
||||
PushGateway = maps:get(push_gateway_server, Opts),
|
||||
{ok, ensure_timer(#state{push_gateway = PushGateway, interval = Interval})}.
|
||||
init([]) ->
|
||||
#{interval := Interval} = opts(),
|
||||
{ok, #{timer => ensure_timer(Interval), ok => 0, failed => 0}}.
|
||||
|
||||
handle_call(info, _From, State = #{timer := Timer}) ->
|
||||
{reply, State#{opts => opts(), next_push_ms => erlang:read_timer(Timer)}, State};
|
||||
handle_call(_Msg, _From, State) ->
|
||||
{noreply, State}.
|
||||
{reply, ok, State}.
|
||||
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_info({timeout, R, ?TIMER_MSG}, State = #state{timer = R, push_gateway = Uri}) ->
|
||||
handle_info({timeout, Timer, ?TIMER_MSG}, State = #{timer := Timer}) ->
|
||||
#{interval := Interval, push_gateway_server := Server} = opts(),
|
||||
PushRes = push_to_push_gateway(Server),
|
||||
NewTimer = ensure_timer(Interval),
|
||||
NewState = maps:update_with(PushRes, fun(C) -> C + 1 end, 1, State#{timer => NewTimer}),
|
||||
%% Data is too big, hibernate for saving memory and stop system monitor warning.
|
||||
{noreply, NewState, hibernate};
|
||||
handle_info(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
push_to_push_gateway(Uri) ->
|
||||
[Name, Ip] = string:tokens(atom_to_list(node()), "@"),
|
||||
Url = lists:concat([Uri, "/metrics/job/", Name, "/instance/", Name, "~", Ip]),
|
||||
Data = prometheus_text_format:format(),
|
||||
httpc:request(post, {Url, [], "text/plain", Data}, [{autoredirect, true}], []),
|
||||
%% Data is too big, hibernate for saving memory and stop system monitor warning.
|
||||
{noreply, ensure_timer(State), hibernate};
|
||||
handle_info(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
case httpc:request(post, {Url, [], "text/plain", Data}, ?HTTP_OPTIONS, []) of
|
||||
{ok, {{"HTTP/1.1", 200, "OK"}, _Headers, _Body}} ->
|
||||
ok;
|
||||
Error ->
|
||||
?SLOG(error, #{
|
||||
msg => "post_to_push_gateway_failed",
|
||||
error => Error,
|
||||
url => Url
|
||||
}),
|
||||
failed
|
||||
end.
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
@ -158,11 +129,14 @@ code_change(_OldVsn, State, _Extra) ->
|
|||
terminate(_Reason, _State) ->
|
||||
ok.
|
||||
|
||||
ensure_timer(State = #state{interval = Interval}) ->
|
||||
State#state{timer = emqx_misc:start_timer(Interval, ?TIMER_MSG)}.
|
||||
ensure_timer(Interval) ->
|
||||
emqx_misc:start_timer(Interval, ?TIMER_MSG).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% prometheus callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
opts() ->
|
||||
emqx_conf:get(?PROMETHEUS).
|
||||
|
||||
deregister_cleanup(_Registry) ->
|
||||
ok.
|
||||
|
@ -623,3 +597,11 @@ emqx_cluster_data() ->
|
|||
{nodes_running, length(Running)},
|
||||
{nodes_stopped, length(Stopped)}
|
||||
].
|
||||
|
||||
%% deprecated_since 5.0.10, remove this when 5.1.x
|
||||
do_start() ->
|
||||
emqx_prometheus_sup:start_child(?APP).
|
||||
|
||||
%% deprecated_since 5.0.10, remove this when 5.1.x
|
||||
do_stop() ->
|
||||
emqx_prometheus_sup:stop_child(?APP).
|
||||
|
|
|
@ -84,7 +84,7 @@ schema("/prometheus/stats") ->
|
|||
prometheus(get, _Params) ->
|
||||
{200, emqx:get_raw_config([<<"prometheus">>], #{})};
|
||||
prometheus(put, #{body := Body}) ->
|
||||
case emqx_prometheus:update(Body) of
|
||||
case emqx_prometheus_config:update(Body) of
|
||||
{ok, NewConfig} ->
|
||||
{200, NewConfig};
|
||||
{error, Reason} ->
|
||||
|
@ -120,7 +120,13 @@ prometheus_config_example() ->
|
|||
#{
|
||||
enable => true,
|
||||
interval => "15s",
|
||||
push_gateway_server => <<"http://127.0.0.1:9091">>
|
||||
push_gateway_server => <<"http://127.0.0.1:9091">>,
|
||||
vm_dist_collector => enabled,
|
||||
mnesia_collector => enabled,
|
||||
vm_statistics_collector => enabled,
|
||||
vm_system_info_collector => enabled,
|
||||
vm_memory_collector => enabled,
|
||||
vm_msacc_collector => enabled
|
||||
}.
|
||||
|
||||
prometheus_data_schema() ->
|
||||
|
|
|
@ -27,17 +27,10 @@
|
|||
]).
|
||||
|
||||
start(_StartType, _StartArgs) ->
|
||||
{ok, Sup} = emqx_prometheus_sup:start_link(),
|
||||
maybe_enable_prometheus(),
|
||||
{ok, Sup}.
|
||||
Res = emqx_prometheus_sup:start_link(),
|
||||
emqx_prometheus_config:add_handler(),
|
||||
Res.
|
||||
|
||||
stop(_State) ->
|
||||
emqx_prometheus_config:remove_handler(),
|
||||
ok.
|
||||
|
||||
maybe_enable_prometheus() ->
|
||||
case emqx_conf:get([prometheus, enable], false) of
|
||||
true ->
|
||||
emqx_prometheus_sup:start_child(?APP, emqx_conf:get([prometheus], #{}));
|
||||
false ->
|
||||
ok
|
||||
end.
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
-module(emqx_prometheus_config).
|
||||
|
||||
-behaviour(emqx_config_handler).
|
||||
|
||||
-include("emqx_prometheus.hrl").
|
||||
|
||||
-export([add_handler/0, remove_handler/0]).
|
||||
-export([post_config_update/5]).
|
||||
-export([update/1]).
|
||||
|
||||
update(Config) ->
|
||||
case
|
||||
emqx_conf:update(
|
||||
[prometheus],
|
||||
Config,
|
||||
#{rawconf_with_defaults => true, override_to => cluster}
|
||||
)
|
||||
of
|
||||
{ok, #{raw_config := NewConfigRows}} ->
|
||||
{ok, NewConfigRows};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
add_handler() ->
|
||||
ok = emqx_config_handler:add_handler(?PROMETHEUS, ?MODULE),
|
||||
ok.
|
||||
|
||||
remove_handler() ->
|
||||
ok = emqx_config_handler:remove_handler(?PROMETHEUS),
|
||||
ok.
|
||||
|
||||
post_config_update(?PROMETHEUS, _Req, New, _Old, AppEnvs) ->
|
||||
application:set_env(AppEnvs),
|
||||
update_prometheus(New);
|
||||
post_config_update(_ConfPath, _Req, _NewConf, _OldConf, _AppEnvs) ->
|
||||
ok.
|
||||
|
||||
update_prometheus(#{enable := true}) ->
|
||||
emqx_prometheus_sup:start_child(?APP);
|
||||
update_prometheus(#{enable := false}) ->
|
||||
emqx_prometheus_sup:stop_child(?APP).
|
|
@ -24,12 +24,13 @@
|
|||
namespace/0,
|
||||
roots/0,
|
||||
fields/1,
|
||||
desc/1
|
||||
desc/1,
|
||||
translation/1
|
||||
]).
|
||||
|
||||
namespace() -> "prometheus".
|
||||
|
||||
roots() -> ["prometheus"].
|
||||
roots() -> [{"prometheus", ?HOCON(?R_REF("prometheus"), #{translate_to => ["prometheus"]})}].
|
||||
|
||||
fields("prometheus") ->
|
||||
[
|
||||
|
@ -124,3 +125,7 @@ fields("prometheus") ->
|
|||
|
||||
desc("prometheus") -> ?DESC(prometheus);
|
||||
desc(_) -> undefined.
|
||||
|
||||
%% for CI test, CI don't load the whole emqx_conf_schema.
|
||||
translation(Name) ->
|
||||
emqx_conf_schema:translation(Name).
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
-export([
|
||||
start_link/0,
|
||||
start_child/1,
|
||||
start_child/2,
|
||||
stop_child/1
|
||||
]).
|
||||
|
||||
|
@ -40,23 +39,27 @@
|
|||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
-spec start_child(supervisor:child_spec()) -> ok.
|
||||
-spec start_child(supervisor:child_spec() | atom()) -> ok.
|
||||
start_child(ChildSpec) when is_map(ChildSpec) ->
|
||||
assert_started(supervisor:start_child(?MODULE, ChildSpec)).
|
||||
|
||||
-spec start_child(atom(), map()) -> ok.
|
||||
start_child(Mod, Opts) when is_atom(Mod) andalso is_map(Opts) ->
|
||||
assert_started(supervisor:start_child(?MODULE, ?CHILD(Mod, Opts))).
|
||||
assert_started(supervisor:start_child(?MODULE, ChildSpec));
|
||||
start_child(Mod) when is_atom(Mod) ->
|
||||
assert_started(supervisor:start_child(?MODULE, ?CHILD(Mod, []))).
|
||||
|
||||
-spec stop_child(any()) -> ok | {error, term()}.
|
||||
stop_child(ChildId) ->
|
||||
case supervisor:terminate_child(?MODULE, ChildId) of
|
||||
ok -> supervisor:delete_child(?MODULE, ChildId);
|
||||
{error, not_found} -> ok;
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
init([]) ->
|
||||
{ok, {{one_for_one, 10, 3600}, []}}.
|
||||
Children =
|
||||
case emqx_conf:get([prometheus, enable], false) of
|
||||
false -> [];
|
||||
true -> [?CHILD(emqx_prometheus, [])]
|
||||
end,
|
||||
{ok, {{one_for_one, 10, 3600}, Children}}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal functions
|
||||
|
@ -64,5 +67,5 @@ init([]) ->
|
|||
|
||||
assert_started({ok, _Pid}) -> ok;
|
||||
assert_started({ok, _Pid, _Info}) -> ok;
|
||||
assert_started({error, {already_tarted, _Pid}}) -> ok;
|
||||
assert_started({error, Reason}) -> erlang:error(Reason).
|
||||
assert_started({error, {already_started, _Pid}}) -> ok;
|
||||
assert_started({error, Reason}) -> {error, Reason}.
|
||||
|
|
|
@ -20,13 +20,15 @@
|
|||
|
||||
-export([
|
||||
introduced_in/0,
|
||||
|
||||
deprecated_since/0,
|
||||
start/1,
|
||||
stop/1
|
||||
]).
|
||||
|
||||
-include_lib("emqx/include/bpapi.hrl").
|
||||
|
||||
deprecated_since() -> "5.0.10".
|
||||
|
||||
introduced_in() ->
|
||||
"5.0.0".
|
||||
|
||||
|
|
|
@ -71,10 +71,14 @@ load_config() ->
|
|||
%%--------------------------------------------------------------------
|
||||
|
||||
t_start_stop(_) ->
|
||||
?assertMatch(ok, emqx_prometheus:start()),
|
||||
?assertMatch(ok, emqx_prometheus:stop()),
|
||||
?assertMatch(ok, emqx_prometheus:restart()),
|
||||
%% wait the interval timer tigger
|
||||
App = emqx_prometheus,
|
||||
?assertMatch(ok, emqx_prometheus_sup:start_child(App)),
|
||||
%% start twice return ok.
|
||||
?assertMatch(ok, emqx_prometheus_sup:start_child(App)),
|
||||
?assertMatch(ok, emqx_prometheus_sup:stop_child(App)),
|
||||
%% stop twice return ok.
|
||||
?assertMatch(ok, emqx_prometheus_sup:stop_child(App)),
|
||||
%% wait the interval timer trigger
|
||||
timer:sleep(2000).
|
||||
|
||||
t_collector_no_crash_test(_) ->
|
||||
|
|
|
@ -71,16 +71,27 @@ t_prometheus_api(_) ->
|
|||
#{
|
||||
<<"push_gateway_server">> := _,
|
||||
<<"interval">> := _,
|
||||
<<"enable">> := _
|
||||
<<"enable">> := _,
|
||||
<<"vm_statistics_collector">> := _,
|
||||
<<"vm_system_info_collector">> := _,
|
||||
<<"vm_memory_collector">> := _,
|
||||
<<"vm_msacc_collector">> := _
|
||||
},
|
||||
Conf
|
||||
),
|
||||
|
||||
NewConf = Conf#{<<"interval">> := <<"2s">>},
|
||||
#{<<"enable">> := Enable} = Conf,
|
||||
?assertEqual(Enable, undefined =/= erlang:whereis(emqx_prometheus)),
|
||||
NewConf = Conf#{<<"interval">> => <<"2s">>, <<"vm_statistics_collector">> => <<"disabled">>},
|
||||
{ok, Response2} = emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, NewConf),
|
||||
|
||||
Conf2 = emqx_json:decode(Response2, [return_maps]),
|
||||
?assertMatch(NewConf, Conf2),
|
||||
?assertEqual({ok, []}, application:get_env(prometheus, vm_statistics_collector_metrics)),
|
||||
?assertEqual({ok, all}, application:get_env(prometheus, vm_memory_collector_metrics)),
|
||||
|
||||
NewConf1 = Conf#{<<"enable">> => (not Enable)},
|
||||
{ok, _Response3} = emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, NewConf1),
|
||||
?assertEqual((not Enable), undefined =/= erlang:whereis(emqx_prometheus)),
|
||||
ok.
|
||||
|
||||
t_stats_api(_) ->
|
||||
|
|
|
@ -16,7 +16,7 @@ The IDs and secrets can be provided from a file which is configurable by the <co
|
|||
|
||||
PSK 是 “Pre-Shared-Keys” 的缩写。
|
||||
|
||||
注意: 确保 SSL 监听器仅启用了 'tlsv1.2', 并且配置了PSK 密码套件,例如 'RSA-PSK-AES256-GCM-SHA384'。
|
||||
注意: 确保 SSL 监听器仅启用了 'tlsv1.2',并且配置了PSK 密码套件,例如 'RSA-PSK-AES256-GCM-SHA384'。
|
||||
|
||||
可以通过查看监听器中的 SSL 选项,了解更多详细信息。
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ retainer_indices(type) ->
|
|||
retainer_indices(desc) ->
|
||||
"Retainer index specifications: list of arrays of positive ascending integers. "
|
||||
"Each array specifies an index. Numbers in an index specification are 1-based "
|
||||
"word positions in topics. Words from specified positions will be used for indexing.</br>"
|
||||
"word positions in topics. Words from specified positions will be used for indexing.<br/>"
|
||||
"For example, it is good to have <code>[2, 4]</code> index to optimize "
|
||||
"<code>+/X/+/Y/...</code> topic wildcard subscriptions.";
|
||||
retainer_indices(example) ->
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{application, emqx_rule_engine, [
|
||||
{description, "EMQX Rule Engine"},
|
||||
% strict semver, bump manually!
|
||||
{vsn, "5.0.2"},
|
||||
{vsn, "5.0.3"},
|
||||
{modules, []},
|
||||
{registered, [emqx_rule_engine_sup, emqx_rule_engine]},
|
||||
{applications, [kernel, stdlib, rulesql, getopt]},
|
||||
|
|
|
@ -671,8 +671,8 @@ event_info_client_connack() ->
|
|||
event_info_client_check_authz_complete() ->
|
||||
event_info_common(
|
||||
'client.check_authz_complete',
|
||||
{<<"client check authz complete">>, <<"鉴权结果"/utf8>>},
|
||||
{<<"client check authz complete">>, <<"鉴权结果"/utf8>>},
|
||||
{<<"client check authz complete">>, <<"授权结果"/utf8>>},
|
||||
{<<"client check authz complete">>, <<"授权结果"/utf8>>},
|
||||
<<"SELECT * FROM \"$events/client_check_authz_complete\"">>
|
||||
).
|
||||
event_info_session_subscribed() ->
|
||||
|
|
|
@ -2,14 +2,25 @@
|
|||
|
||||
## Enhancements
|
||||
|
||||
- Improve `/nodes` API responsiveness [#9221](https://github.com/emqx/emqx/pull/9221).
|
||||
|
||||
- Allow clear retained/delayed data when client is banned [#9139](https://github.com/emqx/emqx/pull/9139).
|
||||
|
||||
- Update `gen_rpc` library to version 3.0 [#9187](https://github.com/emqx/emqx/pull/9187).
|
||||
|
||||
- Improve memory usage on core nodes when bootstrapping a replicant [#9236](https://github.com/emqx/emqx/pull/9236).
|
||||
|
||||
- Improve stability of Prometheus Push Gateway and log errors when POST fails [#9235](http://github.com/emqx/emqx/pull/9235).
|
||||
|
||||
- Now it is possible to opt out VM internal metrics in prometheus stats [#9222](https://github.com/emqx/emqx/pull/9222).
|
||||
When system load is high, reporting too much metrics data may cause the prometheus stats API timeout.
|
||||
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fix error log message when `mechanism` is missing in authentication config [#8924](https://github.com/emqx/emqx/pull/8924).
|
||||
|
||||
- Fix HTTP 500 issue when unknown `status` parameter is used in `/gateway` API call [#7794](https://github.com/emqx/emqx/pull/9225).
|
||||
- Fix HTTP 500 issue when unknown `status` parameter is used in `/gateway` API call [#9225](https://github.com/emqx/emqx/pull/9225).
|
||||
|
||||
- Fixed the HTTP response status code for the `/status` endpoint [#9211](https://github.com/emqx/emqx/pull/9211).
|
||||
Before the fix, it always returned `200` even if the EMQX application was not running. Now it returns `503` in that case.
|
|
@ -2,14 +2,24 @@
|
|||
|
||||
## 增强
|
||||
|
||||
- 提升 `/nodes` API 响应速度 [#9221](https://github.com/emqx/emqx/pull/9221)。
|
||||
|
||||
- 支持拉黑客户端并从数据库中删除保留和延迟发布的消息 [#9139](https://github.com/emqx/emqx/pull/9139)。
|
||||
|
||||
- 升级 `gen_rpc` 库到 3.0 [#9187](https://github.com/emqx/emqx/pull/9187)。
|
||||
|
||||
- 在引导 `replicant` 节点时,改善 `core` 节点的内存使用量 [#9236](https://github.com/emqx/emqx/pull/9236)。
|
||||
|
||||
- 增加 Prometheus Push Gateway 的稳定性, 并在 POST 失败时打印错误日志 [#9235](http://github.com/emqx/emqx/pull/9235)。
|
||||
|
||||
- 可通过配置关闭 prometheus 中的部分内部指标,如果遇到机器负载过高 prometheus 接口返回超时可考虑关闭部分不关心指标,以提高响应速度 [#9222](https://github.com/emqx/emqx/pull/9222)。
|
||||
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- 优化认认证配置中 `mechanism` 字段缺失情况下的错误日志 [#8924](https://github.com/emqx/emqx/pull/8924)。
|
||||
|
||||
- 修复未知 `status` 参数导致 `/gateway` API 发生 HTTP 500 错误的问题 [#7794](https://github.com/emqx/emqx/pull/9225) [#7794](https://github.com/emqx/emqx/pull/9225).
|
||||
- 修复未知 `status` 参数导致 `/gateway` API 发生 HTTP 500 错误的问题 [#9225](https://github.com/emqx/emqx/pull/9225)。
|
||||
|
||||
- 修正了 `/status` 端点的响应状态代码 [#9211](https://github.com/emqx/emqx/pull/9211)。
|
||||
在此修复前,它总是返回 HTTP 状态码 `200`,即使 EMQX 没有完成启动或正在重启。 现在它在这些情况下会返回状态码 `503`。
|
2
mix.exs
2
mix.exs
|
@ -616,7 +616,7 @@ defmodule EMQXUmbrella.MixProject do
|
|||
|
||||
defp jq_dep() do
|
||||
if enable_jq?(),
|
||||
do: [{:jq, github: "emqx/jq", tag: "v0.3.6", override: true}],
|
||||
do: [{:jq, github: "emqx/jq", tag: "v0.3.8", override: true}],
|
||||
else: []
|
||||
end
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ quicer() ->
|
|||
{quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.16"}}}.
|
||||
|
||||
jq() ->
|
||||
{jq, {git, "https://github.com/emqx/jq", {tag, "v0.3.6"}}}.
|
||||
{jq, {git, "https://github.com/emqx/jq", {tag, "v0.3.8"}}}.
|
||||
|
||||
deps(Config) ->
|
||||
{deps, OldDeps} = lists:keyfind(deps, 1, Config),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
EMQX configuration file is in [HOCON](https://github.com/emqx/hocon) format.
|
||||
EMQX configuration files are in [HOCON](https://github.com/emqx/hocon) format.
|
||||
HOCON, or Human-Optimized Config Object Notation is a format for human-readable data,
|
||||
and a superset of JSON.
|
||||
|
||||
|
@ -7,7 +7,7 @@ and a superset of JSON.
|
|||
EMQX configuration consists of 3 layers.
|
||||
From bottom up:
|
||||
|
||||
1. Immutable base: `emqx.conf` + `EMQX_` prefixed environment variables.</br>
|
||||
1. Immutable base: `emqx.conf` + `EMQX_` prefixed environment variables.<br/>
|
||||
Changes in this layer require a full node restart to take effect.
|
||||
1. Cluster overrides: `$EMQX_NODE__DATA_DIR/configs/cluster-override.conf`
|
||||
1. Local node overrides: `$EMQX_NODE__DATA_DIR/configs/local-override.conf`
|
||||
|
@ -94,14 +94,14 @@ Complex types define data 'boxes' which may contain other complex data
|
|||
or primitive values.
|
||||
There are quite some different primitive types, to name a few:
|
||||
|
||||
* `atom()`
|
||||
* `boolean()`
|
||||
* `string()`
|
||||
* `integer()`
|
||||
* `float()`
|
||||
* `number()`
|
||||
* `binary()` # another format of string()
|
||||
* `emqx_schema:duration()` # time duration, another format of integer()
|
||||
* `atom()`.
|
||||
* `boolean()`.
|
||||
* `string()`.
|
||||
* `integer()`.
|
||||
* `float()`.
|
||||
* `number()`.
|
||||
* `binary()`, another format of string().
|
||||
* `emqx_schema:duration()`, time duration, another format of integer()
|
||||
* ...
|
||||
|
||||
::: tip Tip
|
||||
|
@ -146,7 +146,7 @@ For example, this environment variable sets an array value.
|
|||
export EMQX_LISTENERS__SSL__L1__AUTHENTICATION__SSL__CIPHERS='["TLS_AES_256_GCM_SHA384"]'
|
||||
```
|
||||
|
||||
However this also means a string value should be quoted if it happen to contain special
|
||||
However this also means a string value should be quoted if it happens to contain special
|
||||
characters such as `=` and `:`.
|
||||
|
||||
For example, a string value `"localhost:1883"` would be
|
||||
|
@ -248,9 +248,9 @@ authentication=[{enable=true}]
|
|||
|
||||
#### TLS/SSL ciphers
|
||||
|
||||
Starting from v5.0.6, EMQX no longer pre-populate the ciphers list with a default
|
||||
Starting from v5.0.6, EMQX no longer pre-populates the ciphers list with a default
|
||||
set of cipher suite names.
|
||||
Instead, the default ciphers are applyed at runtime when starting the listener
|
||||
Instead, the default ciphers are applied at runtime when starting the listener
|
||||
for servers, or when establishing a TLS connection as a client.
|
||||
|
||||
Below are the default ciphers selected by EMQX.
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
EMQX的配置文件格式是 [HOCON](https://github.com/emqx/hocon) .
|
||||
EMQX的配置文件格式是 [HOCON](https://github.com/emqx/hocon) 。
|
||||
HOCON(Human-Optimized Config Object Notation)是一个JSON的超集,非常适用于易于人类读写的配置数据存储。
|
||||
|
||||
## 分层结构
|
||||
|
||||
EMQX的配置文件可分为三层,自底向上依次是:
|
||||
|
||||
1. 不可变的基础层 `emqx.conf` 加上 `EMQX_` 前缀的环境变量.</br>
|
||||
1. 不可变的基础层 `emqx.conf` 加上 `EMQX_` 前缀的环境变量。<br/>
|
||||
修改这一层的配置之后,需要重启节点来使之生效。
|
||||
1. 集群范围重载层:`$EMQX_NODE__DATA_DIR/configs/cluster-override.conf`
|
||||
1. 节点本地重载层:`$EMQX_NODE__DATA_DIR/configs/local-override.conf`
|
||||
|
||||
如果环境变量 `$EMQX_NODE__DATA_DIR` 没有设置,那么该目录会从 emqx.conf 的 `node.data_dir`配置中读取。
|
||||
如果环境变量 `$EMQX_NODE__DATA_DIR` 没有设置,那么该目录会从 `emqx.conf` 的 `node.data_dir` 配置中读取。
|
||||
|
||||
配置文件 `cluster-override.conf` 的内容会在运行时被EMQX重写。
|
||||
这些重写发生在 dashboard UI,管理HTTP API,或者CLI对集群配置进行修改时。
|
||||
当EMQX运行在集群中时,一个EMQX节点重启之后,会从集群中其他节点复制该文件内容到本地。
|
||||
|
||||
:::tip Tip
|
||||
有些配置项是不能被重载的(例如 `node.name`).
|
||||
有些配置项是不能被重载的(例如 `node.name`)。
|
||||
配置项如果有 `mapping: path.to.boot.config.key` 这个属性,
|
||||
则不能被添加到重载文件中 `*-override.conf` 中。
|
||||
则不能被添加到重载文件 `*-override.conf` 中。
|
||||
:::
|
||||
|
||||
更多的重载规则,请参考下文 [配置重载规则](#配置重载规则).
|
||||
更多的重载规则,请参考下文 [配置重载规则](#配置重载规则)。
|
||||
|
||||
## 配置文件语法
|
||||
|
||||
|
@ -70,7 +70,7 @@ EMQX的配置文件中,有4中复杂数据结构类型,它们分别是:
|
|||
|
||||
1. Struct:结构体都是有类型名称的,结构体中可以有任意多个字段。
|
||||
结构体和字段的名称由不带特殊字符的全小些字母组成,名称中可以带数字,但不得以数字开头,多个单词可用下划线分隔。
|
||||
1. Map: Map与Struct(结构体)类似,但是内部的字段不是预先定义好的.
|
||||
1. Map: Map 与 Struct(结构体)类似,但是内部的字段不是预先定义好的。
|
||||
1. Union: 联合 `MemberType1 | MemberType2 | ...`,可以理解为:“不是这个,就是那个”
|
||||
1. Array: 数组 `[ElementType]`
|
||||
|
||||
|
@ -89,19 +89,19 @@ myarray.2 = 75
|
|||
复杂类型定义了数据 "盒子",其中可能包含其他复杂数据或原始值。
|
||||
有很多不同的原始类型,仅举几个例子。
|
||||
|
||||
* 原子 `atom()`
|
||||
* 布尔 `boolean()`.
|
||||
* 字符串 `string()'。
|
||||
* 整形 `integer()'。
|
||||
* 浮点数 `float()'.
|
||||
* 数值 `number()'。
|
||||
* 二进制编码的字符串 `binary()` # 是 `string()` 的另一种格式
|
||||
* 时间间隔 `emqx_schema:duration()` # 时间间隔,是 `integer()` 的另一种格式
|
||||
* 原子 `atom()`。
|
||||
* 布尔 `boolean()`。
|
||||
* 字符串 `string()`。
|
||||
* 整形 `integer()`。
|
||||
* 浮点数 `float()`。
|
||||
* 数值 `number()`。
|
||||
* 二进制编码的字符串 `binary()` 是 `string()` 的另一种格式。
|
||||
* 时间间隔 `emqx_schema:duration()` 是 `integer()` 的另一种格式。
|
||||
* ...
|
||||
|
||||
::: tip Tip
|
||||
原始类型的名称大多是自我描述的,所以不需要过多的注释。
|
||||
但是有一些不是那么直观的数据类型,则需要配合字段的描述文档进行理解
|
||||
但是有一些不是那么直观的数据类型,则需要配合字段的描述文档进行理解。
|
||||
:::
|
||||
|
||||
|
||||
|
@ -110,7 +110,7 @@ myarray.2 = 75
|
|||
如果我们把EMQX的配置值理解成一个类似目录树的结构,那么类似于文件系统中使用斜杠或反斜杠进行层级分割,
|
||||
EMQX使用的配置路径的层级分割符是 `'.'`
|
||||
|
||||
被`'.'`号分割的每一段,则是Struct(结构体)的字段,或Map的key.
|
||||
被 `'.'` 号分割的每一段,则是 Struct(结构体)的字段,或 Map 的 key。
|
||||
|
||||
下面有几个例子:
|
||||
|
||||
|
@ -122,7 +122,7 @@ authentication.1.enable = true
|
|||
|
||||
### 环境变量重载
|
||||
|
||||
因为`'.'` 分隔符不能使用于环境变量,所以我们需要使用另一个分割符。EMQX选用的是双下划线`__`。
|
||||
因为 `'.'` 分隔符不能使用于环境变量,所以我们需要使用另一个分割符。EMQX选用的是双下划线 `__`。
|
||||
为了与其他的环境变量有所区分,EMQX还增加了一个前缀 `EMQX_` 来用作环境变量命名空间。
|
||||
|
||||
例如 `node.name` 的重载变量名是 `EMQX_NODE__NAME`。
|
||||
|
@ -154,7 +154,7 @@ EMQX_BRIDGES__MQTT__MYBRIDGE__CONNECTOR_SERVER='"localhost:1883"'
|
|||
[warning] unknown_env_vars: ["EMQX_AUTHENTICATION__ENABLED"]
|
||||
```
|
||||
|
||||
这是因为正确的字段名称是 `enable`,而不是 `enabled`.
|
||||
这是因为正确的字段名称是 `enable`,而不是 `enabled`。
|
||||
:::
|
||||
|
||||
### 配置重载规则
|
||||
|
@ -168,8 +168,7 @@ HOCON的值是分层覆盖的,普遍规则如下:
|
|||
|
||||
#### 结构体
|
||||
|
||||
合并覆盖规则。在如下配置中,最后一行的 `debug` 值会覆盖覆盖原先`level`字段的 `error` 值
|
||||
但是`enable` 字段保持不变。
|
||||
合并覆盖规则。在如下配置中,最后一行的 `debug` 值会覆盖覆盖原先`level`字段的 `error` 值,但是 `enable` 字段保持不变。
|
||||
```
|
||||
log {
|
||||
console_handler{
|
||||
|
@ -178,7 +177,7 @@ log {
|
|||
}
|
||||
}
|
||||
|
||||
## 控制台日志打印先定义为`error`级,后被覆写成`debug`级
|
||||
## 控制台日志打印先定义为 `error` 级,后被覆写成 `debug` 级
|
||||
|
||||
log.console_handler.level=debug
|
||||
```
|
||||
|
@ -186,7 +185,7 @@ log.console_handler.level=debug
|
|||
#### Map
|
||||
|
||||
Map与结构体类似,也是合并覆盖规则。
|
||||
如下例子中,`zone1` 的 `max_packet_size` 可以在文件后面覆写.
|
||||
如下例子中,`zone1` 的 `max_packet_size` 可以在文件后面覆写。
|
||||
|
||||
```
|
||||
zone {
|
||||
|
|
Loading…
Reference in New Issue