瀏覽代碼

perf(broker): Optimization for handling bursty traffic

intro. new lock type: 'spawn' of broker.perf.route_lock_type

mnesia get lock calls are not optimized for selective receive.

hence taking locks would be very expensive while there are tones of
messages in the brokers message queue.

This optimization run the transaction in a separate process to utilize
the selective receive optimization of the compiler.
William Yang 4 年之前
父節點
當前提交
e7fc75fdf2
共有 2 個文件被更改,包括 22 次插入2 次删除
  1. 3 1
      priv/emqx.schema
  2. 19 1
      src/emqx_router.erl

+ 3 - 1
priv/emqx.schema

@@ -2259,9 +2259,11 @@ end}.
 %% key:   mnesia translational updates with per-key locks. recommended for single node setup.
 %% key:   mnesia translational updates with per-key locks. recommended for single node setup.
 %% tab:   mnesia translational updates with table lock. recommended for multi-nodes setup.
 %% tab:   mnesia translational updates with table lock. recommended for multi-nodes setup.
 %% global: global lock protected updates. recommended for larger cluster.
 %% global: global lock protected updates. recommended for larger cluster.
+%% spawn: same as `key', but transaction is done in another proc, ideal for handling bursty traffic.
+%%
 {mapping, "broker.perf.route_lock_type", "emqx.route_lock_type", [
 {mapping, "broker.perf.route_lock_type", "emqx.route_lock_type", [
   {default, key},
   {default, key},
-  {datatype, {enum, [key, tab, global]}}
+  {datatype, {enum, [key, tab, global, spawn]}}
 ]}.
 ]}.
 
 
 %% @doc Enable trie path compaction.
 %% @doc Enable trie path compaction.

+ 19 - 1
src/emqx_router.erl

@@ -263,7 +263,25 @@ maybe_trans(Fun, Args) ->
             trans(fun() ->
             trans(fun() ->
                           emqx_trie:lock_tables(),
                           emqx_trie:lock_tables(),
                           apply(Fun, Args)
                           apply(Fun, Args)
-                  end, [])
+                  end, []);
+        spawn ->
+            %% trigger selective receive optimization of compiler,
+            %% ideal for handling busty traffic.
+            Ref = erlang:make_ref(),
+            Owner = self(),
+            {WPid, RefMon} = spawn_monitor(fun() ->
+                                                Res = trans(Fun, Args),
+                                                Owner ! {Ref, Res}
+                                        end),
+            receive
+                {Ref, TransRes} ->
+                    receive
+                        {'DOWN', RefMon, process, WPid, normal} -> ok
+                    end,
+                    TransRes;
+                {'DOWN', RefMon, process, WPid, _Info} ->
+                    {error, trans_crash}
+            end
     end.
     end.
 
 
 -spec(trans(function(), list(any())) -> ok | {error, term()}).
 -spec(trans(function(), list(any())) -> ok | {error, term()}).