diff --git a/etc/emqttd.conf b/etc/emqttd.conf index 71c6d0a96..f71829c79 100644 --- a/etc/emqttd.conf +++ b/etc/emqttd.conf @@ -8,11 +8,11 @@ ## Erlang VM ##-------------------------------------------------------------------- -## Erlang Node Name +## Erlang node name vm.nodename = emqttd@127.0.0.1 ## Cookie for distributed erlang -vm.setcookie = emqttdsecretcookie +vm.setcookie = emqsecretcookie ## SMP support: enable, auto, disable vm.smp = auto @@ -39,14 +39,14 @@ vm.max_ets_tables = 256000 ## Tweak GC to run more often vm.fullsweep_after = 1000 -vm.crash_dump = log/emqttd_crash.dump +## Crash dump +vm.crash_dump = log/crash.dump ##-------------------------------------------------------------------- ## Log ##-------------------------------------------------------------------- - ##-------------------------------------------------------------------- ## MQTT Protocol ##-------------------------------------------------------------------- @@ -65,39 +65,39 @@ mqtt.client_idle_timeout = 30 ##-------------------------------------------------------------------- ## TCP Listener: 1883, 127.0.0.1:1883, ::1:1883 -mqtt.listener.tcp = 1883 -mqtt.listener.tcp.acceptors = 16 -mqtt.listener.tcp.max_clients = 512 +## mqtt.listener.tcp = 1883 +## mqtt.listener.tcp.acceptors = 16 +## mqtt.listener.tcp.max_clients = 512 ## Rate Limit. Format is 'burst,rate', Unit is KB/Sec ## mqtt.listener.tcp.rate_limit = 100,10 ## Mount Point ## mqtt.listener.tcp.mount_point = prefix/ ## TCP Socket Options. Set buffer if hight thoughtput -mqtt.listener.tcp.opts.recbuf = 4096 -mqtt.listener.tcp.opts.sndbuf = 4096 -mqtt.listener.tcp.opts.buffer = 4096 -mqtt.listener.tcp.opts.nodelay = true -mqtt.listener.tcp.opts.backlog = 1024 +## mqtt.listener.tcp.opts.recbuf = 4096 +## mqtt.listener.tcp.opts.sndbuf = 4096 +## mqtt.listener.tcp.opts.buffer = 4096 +## mqtt.listener.tcp.opts.nodelay = true +## mqtt.listener.tcp.opts.backlog = 1024 ## SSL Listener -mqtt.listener.ssl = 883 -mqtt.listener.ssl.acceptors = 4 -mqtt.listener.ssl.max_clients = 512 +## mqtt.listener.ssl = 883 +## mqtt.listener.ssl.acceptors = 4 +## mqtt.listener.ssl.max_clients = 512 ## Rate Limit. Format is 'burst,rate', Unit is KB/Sec ## mqtt.listener.ssl.rate_limit = 100,10 ## Mount Point ## mqtt.listener.ssl.mount_point = prefix/ -mqtt.listener.ssl.opts.handshake_timeout = 10 ## Seconds -mqtt.listener.ssl.opts.certfile = etc/ssl/cert.pem -mqtt.listener.ssl.opts.keyfile = etc/ssl/key.pem -mqtt.listener.ssl.opts.cacertfile = etc/ssl/cacert.pem +## mqtt.listener.ssl.opts.handshake_timeout = 10 ## Seconds +## mqtt.listener.ssl.opts.certfile = etc/ssl/cert.pem +## mqtt.listener.ssl.opts.keyfile = etc/ssl/key.pem +## mqtt.listener.ssl.opts.cacertfile = etc/ssl/cacert.pem ## mqtt.listener.ssl.opts.verify = verify_peer ## mqtt.listener.ssl.opts.failed_if_no_peer_cert = true ## HTTP Listener -mqtt.listener.http = 8083 -mqtt.listener.http.acceptors = 4 -mqtt.listener.http.max_clients = 64 +## mqtt.listener.http = 8083 +## mqtt.listener.http.acceptors = 4 +## mqtt.listener.http.max_clients = 64 ##-------------------------------------------------------------------- ## MQTT Session @@ -119,8 +119,13 @@ mqtt.session.max_awaiting_rel = 0 ## Statistics Collection Interval(seconds) mqtt.session.collect_interval = 0 -## Expired after 2 day (unit: minute) -mqtt.session.expired_after = 2880 +## Expired after 2 day: +## w - week +## d - day +## h - hour +## m - minute +## s - second +mqtt.session.expired_after = 2d ##-------------------------------------------------------------------- ## MQTT Queue @@ -137,10 +142,10 @@ mqtt.queue.type = simple mqtt.queue.max_length = infinity ## Low-water mark of queued messages -mqtt.queue.low_watermark = 0.2 +mqtt.queue.low_watermark = 20% ## High-water mark of queued messages -mqtt.queue.high_watermark = 0.6 +mqtt.queue.high_watermark = 60% ## Queue Qos0 messages? mqtt.queue.qos0 = true @@ -175,40 +180,40 @@ mqtt.bridge.ping_down_interval = 1 ## Second ##------------------------------------------------------------------- ## Dir of plugins' config -mqtt.plugins.etc_dir = etc/plugins/ +## mqtt.plugins.etc_dir = etc/plugins/ ## File to store loaded plugin names. -mqtt.plugins.loaded_file = data/loaded_plugins +## mqtt.plugins.loaded_file = data/loaded_plugins ##------------------------------------------------------------------- ## MQTT Modules ##------------------------------------------------------------------- ## Enable retainer module -mqtt.module.retainer = on +## mqtt.module.retainer = on ## disc: disc_copies, ram: ram_copies -mqtt.module.retainer.storage_type = disc +## mqtt.module.retainer.storage_type = disc ## Max number of retained messages -mqtt.module.retainer.max_message_num = 100000 +## mqtt.module.retainer.max_message_num = 100000 ## Max Payload Size of retained message -mqtt.module.retainer.max_playload_size = 65536 +## mqtt.module.retainer.max_playload_size = 65536 ## Expired after seconds, never expired if 0 -mqtt.module.retainer.expired_after = 0 +## mqtt.module.retainer.expired_after = 0 ## Enable presence module ## Client presence management module. Publish presence messages when ## client connected or disconnected. -mqtt.module.presence = on -mqtt.module.presence.qos = 0 +## mqtt.module.presence = on +## mqtt.module.presence.qos = 0 ## Enable subscription module ## Subscribe topics automatically when client connected -mqtt.module.subscription = on -mqtt.module.subscription.topics = $client/%c,1;topic2,1 +## mqtt.module.subscription = on +## mqtt.module.subscription.topics = $client/%c,1;topic2,1 ## [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite) -mqtt.module.rewrite = off -mqtt.module.rewrite.config = etc/modules/rewrite.conf +## mqtt.module.rewrite = off +## mqtt.module.rewrite.config = etc/modules/rewrite.conf ##------------------------------------------------------------------- ## System Monitor @@ -216,15 +221,13 @@ mqtt.module.rewrite.config = etc/modules/rewrite.conf ## Long GC, don't monitor in production mode for: ## https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 - sysmon.long_gc = false ## Long Schedule(ms) sysmon.long_schedule = 240 ## 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM. -## 8 * 1024 * 1024 -sysmon.large_heap = 8388608 +sysmon.large_heap = 8MB ## Busy Port sysmon.busy_port = false diff --git a/priv/emqttd.schema b/priv/emqttd.schema index 2b5311462..2f56739a7 100644 --- a/priv/emqttd.schema +++ b/priv/emqttd.schema @@ -1,31 +1,35 @@ %%-*- mode: erlang -*- -%% EMQ 3.0 Config Mapping +%% EMQ 3.0 config mapping %%-------------------------------------------------------------------- %% Erlang VM Args %%-------------------------------------------------------------------- +%% @doc Erlang node name {mapping, "vm.nodename", "vm_args.-name", [ - {default, "{{node}}"} + {default, "emqttd@127.0.0.1"} ]}. +%% @doc Secret cookie for distributed erlang node {mapping, "vm.setcookie", "vm_args.-setcookie", [ - {default, "emqttd"} + {default, "emqsecretcookie"} ]}. +%% @doc SMP Support {mapping, "vm.smp", "vm_args.-smp", [ - {default, enable}, + {default, auto}, {datatype, {enum, [enable, auto, disable]}}, hidden ]}. +%% @doc Enable Kernel Poll {mapping, "vm.kernel_poll", "vm_args.+K", [ {default, on}, {datatype, flag}, hidden ]}. -%% More information at: http://erlang.org/doc/man/erl.html +%% @doc More information at: http://erlang.org/doc/man/erl.html {mapping, "vm.async_threads", "vm_args.+A", [ {default, 64}, {datatype, integer}, @@ -52,12 +56,7 @@ {validator, "range4ports", "must be 1024 to 134217727", fun(X) -> X >= 1024 andalso X =< 134217727 end}. -%% @doc For nodes with many busy_dist_port events, Basho recommends -%% raising the sender-side network distribution buffer size. -%% 32MB may not be sufficient for some workloads and is a suggested -%% starting point. Erlangers may know this as +zdbbl. -%% The Erlang/OTP default is 1024 (1 megabyte). -%% See: http://www.erlang.org/doc/man/erl.html#%2bzdbbl +%% @doc http://www.erlang.org/doc/man/erl.html#%2bzdbbl {mapping, "vm.dist_buffer_size", "vm_args.+zdbbl", [ {datatype, bytesize}, {commented, "32MB"}, @@ -83,14 +82,7 @@ end }. -%% @doc A non-negative integer which indicates how many times -%% generational garbage collections can be done without forcing a -%% fullsweep collection. In low-memory systems (especially without -%% virtual memory), setting the value to 0 can help to conserve -%% memory. -%% -%% More information at: -%% http://www.erlang.org/doc/man/erlang.html#system_flag-2 +%% @doc http://www.erlang.org/doc/man/erlang.html#system_flag-2 {mapping, "vm.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [ {default, 1000}, {datatype, integer}, @@ -103,7 +95,7 @@ %% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES, %% R16+ uses +e -%% @doc Raise the ETS table limit +%% @doc The ETS table limit {mapping, "vm.max_ets_tables", cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [ {default, 256000}, @@ -118,38 +110,232 @@ hidden ]}. -{mapping, "mqtt.max_clientid_len", "emqttd.mqtt_max_clientid_len", [ +%%-------------------------------------------------------------------- +%% MQTT Protocol +%%-------------------------------------------------------------------- + +%% @doc Set the Max ClientId Length Allowed. +{mapping, "mqtt.max_clientid_len", "emqttd.mqtt_protocol", [ {default, 1024}, {datatype, integer} ]}. -{mapping, "mqtt.max_packet_size", "emqttd.mqtt_max_packet_size", [ +%% @doc Max Packet Size Allowed, 64K by default. +{mapping, "mqtt.max_packet_size", "emqttd.mqtt_protocol", [ + {default, "64KB"}, {datatype, bytesize} ]}. -{mapping, "mqtt.client_idle_timeout", "emqttd.mqtt_client_idle_timeout", [ +%% @doc Client Idle Timeout. +{mapping, "mqtt.client_idle_timeout", "emqttd.mqtt_protocol", [ + {default, 30}, {datatype, integer} ]}. +{translation, "emqttd.mqtt_protocol", fun(Conf) -> + [{max_clientid_len, cuttlefish:conf_get("mqtt.max_clientid_len", Conf)}, + {max_packet_size, cuttlefish:conf_get("mqtt.max_packet_size", Conf)}, + {client_idle_timeout, cuttlefish:conf_get("mqtt.client_idle_timeout", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT Session +%%-------------------------------------------------------------------- + +%% @doc Max number of QoS 1 and 2 messages that can be “inflight” at one time. +%% 0 means no limit +{mapping, "mqtt.session.max_inflight", "emqttd.mqtt_session", [ + {default, 100}, + {datatype, integer} +]}. + + +%% @doc Retry interval for redelivering QoS1/2 messages. +{mapping, "mqtt.session.unack_retry_interval", "emqttd.mqtt_session", [ + {default, 60}, + {datatype, integer} +]}. + +%% @doc Awaiting PUBREL Timeout +{mapping, "mqtt.session.await_rel_timeout", "emqttd.mqtt_session", [ + {default, 30}, + {datatype, integer} +]}. + +%% @doc Max Packets that Awaiting PUBREL, 0 means no limit +{mapping, "mqtt.session.max_awaiting_rel", "emqttd.mqtt_session", [ + {default, 0}, + {datatype, integer} +]}. + +%% @doc Statistics Collection Interval(seconds) +{mapping, "mqtt.session.collect_interval", "emqttd.mqtt_session", [ + {default, 0}, + {datatype, integer} +]}. + +%% @doc Session expired after... +{mapping, "mqtt.session.expired_after", "emqttd.mqtt_session", [ + {default, "2d"}, + {datatype, {duration, s}} +]}. + +{translation, "emqttd.mqtt_session", fun(Conf) -> + [{max_inflight, cuttlefish:conf_get("mqtt.session.max_inflight", Conf)}, + {unack_retry_interval, cuttlefish:conf_get("mqtt.session.unack_retry_interval", Conf)}, + {await_rel_timeout, cuttlefish:conf_get("mqtt.session.await_rel_timeout", Conf)}, + {max_awaiting_rel, cuttlefish:conf_get("mqtt.session.max_awaiting_rel", Conf)}, + {collect_interval, cuttlefish:conf_get("mqtt.session.collect_interval", Conf)}, + {expired_after, cuttlefish:conf_get("mqtt.session.expired_after", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT Queue +%%-------------------------------------------------------------------- + +%% @doc Type: simple | priority +{mapping, "mqtt.queue.type", "emqttd.mqtt_queue", [ + {default, simple}, + {datatype, atom} +]}. + +%% @doc Topic Priority: 0~255, Default is 0 +{mapping, "mqtt.queue.priority", "emqttd.mqtt_queue", [ + {default, ""}, + {datatype, string}, + hidden +]}. + +%% @doc Max queue length. Enqueued messages when persistent client disconnected, or inflight window is full. +{mapping, "mqtt.queue.max_length", "emqttd.mqtt_queue", [ + {default, infinity}, + {datatype, [atom, integer]} +]}. + +%% @doc Low-water mark of queued messages +{mapping, "mqtt.queue.low_watermark", "emqttd.mqtt_queue", [ + {default, "20%"}, + {datatype, string}, + hidden +]}. + +%% @doc High-water mark of queued messages +{mapping, "mqtt.queue.high_watermark", "emqttd.mqtt_queue", [ + {default, "60%"}, + {datatype, string}, + hidden +]}. + +%% @doc Queue Qos0 messages? +{mapping, "mqtt.queue.qos0", "emqttd.mqtt_queue", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{translation, "emqttd.mqtt_queue", fun(Conf) -> + Parse = fun(S) -> + {match, [N]} = re:run(S, "^([0-9]+)%$", [{capture, all_but_first, list}]), + list_to_integer(N) / 100 + end, + Opts = [{type, cuttlefish:conf_get("mqtt.queue.type", Conf, simple)}, + {max_length, cuttlefish:conf_get("mqtt.queue.max_length", Conf)}, + {low_watermark, Parse(cuttlefish:conf_get("mqtt.queue.low_watermark", Conf))}, + {high_watermark, Parse(cuttlefish:conf_get("mqtt.queue.high_watermark", Conf))}, + {queue_qos0, cuttlefish:conf_get("mqtt.queue.qos0", Conf)}], + case cuttlefish:conf_get("mqtt.queue.priority", Conf) of + undefined -> Opts; + V -> [{priority, + [begin [T, P] = string:tokens(S, "="), + {T, list_to_integer(P)} + end || S <- string:tokens(V, ",")]}|Opts] + end +end}. + +%%-------------------------------------------------------------------- +%% MQTT Broker +%%-------------------------------------------------------------------- +{mapping, "mqtt.broker.sys_interval", "emqttd.mqtt_broker", [ + {default, 60}, + {datatype, integer} +]}. + +{translation, "emqttd.mqtt_broker", fun(Conf) -> + [{sys_interval, cuttlefish:conf_get("mqtt.broker.sys_interval", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT PubSub +%%-------------------------------------------------------------------- +{mapping, "mqtt.pubsub.pool_size", "emqttd.mqtt_pubsub", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "mqtt.pubsub.by_clientid", "emqttd.mqtt_pubsub", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "mqtt.pubsub.async", "emqttd.mqtt_pubsub", [ + {default, true}, + {datatype, {enum, [true, false]}}, + hidden +]}. + +{translation, "emqttd.mqtt_pubsub", fun(Conf) -> + [{pool_size, cuttlefish:conf_get("mqtt.pubsub.pool_size", Conf)}, + {by_clientid, cuttlefish:conf_get("mqtt.pubsub.by_clientid", Conf)}, + {async, cuttlefish:conf_get("mqtt.pubsub.async", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% MQTT Bridge +%%-------------------------------------------------------------------- +{mapping, "mqtt.bridge.max_queue_len", "emqttd.mqtt_bridge", [ + {default, 10000}, + {datatype, integer} +]}. + +{mapping, "mqtt.bridge.ping_down_interval", "emqttd.mqtt_bridge", [ + {default, 1}, + {datatype, integer} +]}. + +{translation, "emqttd.mqtt_bridge", fun(Conf) -> + [{max_queue_len, cuttlefish:conf_get("mqtt.bridge.max_queue_len", Conf)}, + {ping_down_interval, cuttlefish:conf_get("mqtt.bridge.ping_down_interval", Conf)}] +end}. + +%%-------------------------------------------------------------------- +%% System Monitor +%%-------------------------------------------------------------------- + +%% @doc Long GC, don't monitor in production mode for: +%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 {mapping, "sysmon.long_gc", "emqttd.sysmon", [ {default, false}, {datatype, {enum, [true, false]}} ]}. +%% @doc Long Schedule(ms) {mapping, "sysmon.long_schedule", "emqttd.sysmon", [ {default, 1000}, {datatype, integer} ]}. +%% @doc Large Heap {mapping, "sysmon.large_heap", "emqttd.sysmon", [ - {datatype, integer} + {default, "8MB"}, + {datatype, bytesize} ]}. +%% @doc Monitor Busy Port {mapping, "sysmon.busy_port", "emqttd.sysmon", [ {default, false}, {datatype, {enum, [true, false]}} ]}. +%% @doc Monitor Busy Dist Port {mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [ {default, true}, {datatype, {enum, [true, false]}}