diff --git a/apps/emqx/src/emqx_channel.erl b/apps/emqx/src/emqx_channel.erl index e7500164e..d5b55a0d5 100644 --- a/apps/emqx/src/emqx_channel.erl +++ b/apps/emqx/src/emqx_channel.erl @@ -1144,8 +1144,7 @@ run_terminate_hook(Reason, #channel{clientinfo = ClientInfo, session = Session}) %% Internal functions %%-------------------------------------------------------------------- overload_protection(_, #channel{clientinfo = #{zone := Zone}}) -> - T = get_mqtt_conf(Zone, overload_drawback_delay, 1), - emqx_olp:backoff(T), + emqx_olp:backoff(Zone), ok. %%-------------------------------------------------------------------- diff --git a/apps/emqx/src/emqx_connection.erl b/apps/emqx/src/emqx_connection.erl index 139f8f6aa..180747208 100644 --- a/apps/emqx/src/emqx_connection.erl +++ b/apps/emqx/src/emqx_connection.erl @@ -821,8 +821,10 @@ ensure_rate_limit(Stats, State = #state{limiter = Limiter}) -> %%-------------------------------------------------------------------- %% Run GC and Check OOM -run_gc(Stats, State = #state{gc_state = GcSt}) -> - case ?ENABLED(GcSt) andalso emqx_gc:run(Stats, GcSt) of +run_gc(Stats, State = #state{gc_state = GcSt, zone = Zone}) -> + case ?ENABLED(GcSt) andalso not emqx_olp:backoff_gc(Zone) + andalso emqx_gc:run(Stats, GcSt) + of false -> State; {_IsGC, GcSt1} -> State#state{gc_state = GcSt1} diff --git a/apps/emqx/src/emqx_olp.erl b/apps/emqx/src/emqx_olp.erl index 9a57ea9ff..f38218765 100644 --- a/apps/emqx/src/emqx_olp.erl +++ b/apps/emqx/src/emqx_olp.erl @@ -16,16 +16,35 @@ -module(emqx_olp). -export([ is_overloaded/0 , backoff/1 + , backoff_gc/1 + , backoff_hibernation/1 ]). -spec is_overloaded() -> boolean(). is_overloaded() -> load_ctl:is_overloaded(). --spec backoff(timer:timeout()) -> ok | timeout. -backoff(Delay) -> - load_ctl:maydelay(Delay). +-spec backoff(Zone :: atom()) -> ok | timeout. +backoff(Zone) -> + case emqx_config:get_zone_conf(Zone, [overload_protection, enable], false) of + true -> + Delay = emqx_config:get_zone_conf(Zone, [overload_protection, backoff_delay], 1), + load_ctl:maydelay(Delay); + false -> + ok + end. +-spec backoff_gc(Zone :: atom()) -> ok | timeout. +backoff_gc(Zone) -> + load_ctl:is_overloaded() + andalso emqx_config:get_zone_conf(Zone, [overload_protection, enable], false) + andalso emqx_config:get_zone_conf(Zone, [overload_protection, backoff_gc], false). + +-spec backoff_hibernation(Zone :: atom()) -> ok | timeout. +backoff_hibernation(Zone) -> + load_ctl:is_overloaded() + andalso emqx_config:get_zone_conf(Zone, [overload_protection, enable], false) + andalso emqx_config:get_zone_conf(Zone, [overload_protection, backoff_hibernation], false). %%%_* Emacs ==================================================================== %%% Local Variables: %%% allout-layout: t diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 31f973421..cd9c5e265 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -122,6 +122,9 @@ roots(medium) -> , {"force_shutdown", sc(ref("force_shutdown"), #{})} + , {"overload_protection", + sc(ref("overload_protection"), + #{})} ]; roots(low) -> [ {"force_gc", @@ -323,7 +326,9 @@ fields("mqtt") -> fields("zone") -> Fields = ["mqtt", "stats", "flapping_detect", "force_shutdown", - "conn_congestion", "rate_limit", "quota", "force_gc"], + "conn_congestion", "rate_limit", "quota", "force_gc", + "overload_protection" + ], [{F, ref(emqx_zone_schema, F)} || F <- Fields]; fields("rate_limit") -> @@ -391,6 +396,24 @@ fields("force_shutdown") -> })} ]; +fields("overload_protection") -> + [ {"enable", + sc(boolean(), + #{ default => false})} + , {"backoff_delay", + sc(range(0, inf), + #{ default => 1 + })} + , {"backoff_gc", + sc(boolean(), + #{ default => true + })} + , {"backoff_hibernation", + sc(boolean(), + #{ default => true + })} + ]; + fields("conn_congestion") -> [ {"enable_alarm", sc(boolean(),