diff options
| author | Michael Klishin <michael@novemberain.com> | 2015-12-03 15:09:54 +0300 |
|---|---|---|
| committer | Michael Klishin <michael@novemberain.com> | 2015-12-03 15:09:54 +0300 |
| commit | 6e486a1e713f5a227ec7bfca2389cc81c63eddb9 (patch) | |
| tree | 88ba02f0ad9b4cdaa8d21d772e069445db5c1bd8 | |
| parent | 92a3cd890fd4f5b506e496f429d90b2048bb5c7a (diff) | |
| parent | a9f7fef06380e7c29bb8d5d64c706be16732b553 (diff) | |
| download | rabbitmq-server-git-6e486a1e713f5a227ec7bfca2389cc81c63eddb9.tar.gz | |
Merge pull request #462 from rabbitmq/rabbitmq-server-448
Support setting vm_memory_high_watermark and disk_free_limit in units
| -rw-r--r-- | docs/rabbitmq.config.example | 18 | ||||
| -rw-r--r-- | docs/rabbitmqctl.1.xml | 13 | ||||
| -rw-r--r-- | src/rabbit_alarm.erl | 3 | ||||
| -rw-r--r-- | src/rabbit_control_main.erl | 12 | ||||
| -rw-r--r-- | src/rabbit_disk_monitor.erl | 18 | ||||
| -rw-r--r-- | src/rabbit_resource_monitor_misc.erl | 49 | ||||
| -rw-r--r-- | src/vm_memory_monitor.erl | 19 |
7 files changed, 118 insertions, 14 deletions
diff --git a/docs/rabbitmq.config.example b/docs/rabbitmq.config.example index 13cac251e6..55c5736994 100644 --- a/docs/rabbitmq.config.example +++ b/docs/rabbitmq.config.example @@ -193,6 +193,19 @@ %% Alternatively, we can set a limit (in bytes) of RAM used by the node. %% %% {vm_memory_high_watermark, {absolute, 1073741824}}, + %% + %% Or you can set absolute value using memory units. + %% + %% {vm_memory_high_watermark, {absolute, "1024M"}}, + %% + %% Supported units suffixes: + %% + %% k, kiB: kibibytes (2^10 bytes) + %% M, MiB: mebibytes (2^20) + %% G, GiB: gibibytes (2^30) + %% kB: kilobytes (10^3) + %% MB: megabytes (10^6) + %% GB: gigabytes (10^9) %% Fraction of the high watermark limit at which queues start to %% page message out to disc in order to free up memory. @@ -211,6 +224,11 @@ %% listed above for more details. %% %% {disk_free_limit, 50000000}, + %% + %% Or you can set it using memory units (same as in vm_memory_high_watermark) + %% {disk_free_limit, "50MB"}, + %% {disk_free_limit, "50000kB"}, + %% {disk_free_limit, "2GB"}, %% Alternatively, we can set a limit relative to total available RAM. %% diff --git a/docs/rabbitmqctl.1.xml b/docs/rabbitmqctl.1.xml index 885e3c4dd2..b9e478cb53 100644 --- a/docs/rabbitmqctl.1.xml +++ b/docs/rabbitmqctl.1.xml @@ -1958,15 +1958,22 @@ </listitem> </varlistentry> <varlistentry> - <term><cmdsynopsis><command>set_vm_memory_high_watermark absolute</command> <arg choice="req"><replaceable>memory_limit_in_bytes</replaceable></arg></cmdsynopsis></term> + <term><cmdsynopsis><command>set_vm_memory_high_watermark absolute</command> <arg choice="req"><replaceable>memory_limit</replaceable></arg></cmdsynopsis></term> <listitem> <variablelist> <varlistentry> - <term>memory_limit_in_bytes</term> + <term>memory_limit</term> <listitem><para> The new memory limit at which flow control is triggered, expressed in bytes as an integer number - greater than or equal to 0. + greater than or equal to 0 or as string with memory unit + (e.g. 1024MB). Available units are: + k, kiB: kibibytes (2^10 bytes) + M, MiB: mebibytes (2^20) + G, GiB: gibibytes (2^30) + kB: kilobytes (10^3) + MB: megabytes (10^6) + GB: gigabytes (10^9) </para></listitem> </varlistentry> </variablelist> diff --git a/src/rabbit_alarm.erl b/src/rabbit_alarm.erl index 111f780076..fdb673a61b 100644 --- a/src/rabbit_alarm.erl +++ b/src/rabbit_alarm.erl @@ -39,6 +39,8 @@ -define(SERVER, ?MODULE). + + %%---------------------------------------------------------------------------- -ifdef(use_specs). @@ -77,6 +79,7 @@ start() -> ok = rabbit_sup:start_restartable_child(?MODULE), ok = gen_event:add_handler(?SERVER, ?MODULE, []), {ok, MemoryWatermark} = application:get_env(vm_memory_high_watermark), + rabbit_sup:start_restartable_child( vm_memory_monitor, [MemoryWatermark, fun (Alarm) -> diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl index d21f60a440..91a079da93 100644 --- a/src/rabbit_control_main.erl +++ b/src/rabbit_control_main.erl @@ -417,10 +417,14 @@ action(set_vm_memory_high_watermark, Node, [Arg], _Opts, Inform) -> rpc_call(Node, vm_memory_monitor, set_vm_memory_high_watermark, [Frac]); action(set_vm_memory_high_watermark, Node, ["absolute", Arg], _Opts, Inform) -> - Limit = list_to_integer(Arg), - Inform("Setting memory threshold on ~p to ~p bytes", [Node, Limit]), - rpc_call(Node, vm_memory_monitor, set_vm_memory_high_watermark, - [{absolute, Limit}]); + case rabbit_resource_monitor_misc:parse_information_unit(Arg) of + {ok, Limit} -> + Inform("Setting memory threshold on ~p to ~p bytes", [Node, Limit]), + rpc_call(Node, vm_memory_monitor, set_vm_memory_high_watermark, + [{absolute, Limit}]); + {error, parse_error} -> + {error_string, "Unable to parse absolute memory limit value ~p", [Arg]} + end; action(set_permissions, Node, [Username, CPerm, WPerm, RPerm], Opts, Inform) -> VHost = proplists:get_value(?VHOST_OPT, Opts), diff --git a/src/rabbit_disk_monitor.erl b/src/rabbit_disk_monitor.erl index 3e9171b79a..30b11c0c11 100644 --- a/src/rabbit_disk_monitor.erl +++ b/src/rabbit_disk_monitor.erl @@ -44,6 +44,7 @@ -define(SERVER, ?MODULE). -define(DEFAULT_MIN_DISK_CHECK_INTERVAL, 100). -define(DEFAULT_MAX_DISK_CHECK_INTERVAL, 10000). +-define(DEFAULT_DISK_FREE_LIMIT, 50000000). %% 250MB/s i.e. 250kB/ms -define(FAST_RATE, (250 * 1000)). @@ -71,7 +72,7 @@ -ifdef(use_specs). --type(disk_free_limit() :: (integer() | {'mem_relative', float()})). +-type(disk_free_limit() :: (integer() | string() | {'mem_relative', float()})). -spec(start_link/1 :: (disk_free_limit()) -> rabbit_types:ok_pid_or_error()). -spec(get_disk_free_limit/0 :: () -> integer()). -spec(set_disk_free_limit/1 :: (disk_free_limit()) -> 'ok'). @@ -233,10 +234,17 @@ parse_free_win32(CommandResult) -> [{capture, all_but_first, list}]), list_to_integer(lists:reverse(Free)). -interpret_limit({mem_relative, R}) -> - round(R * vm_memory_monitor:get_total_memory()); -interpret_limit(L) -> - L. +interpret_limit({mem_relative, Relative}) + when is_float(Relative), Relative < 1 -> + round(Relative * vm_memory_monitor:get_total_memory()); +interpret_limit(Absolute) -> + case rabbit_resource_monitor_misc:parse_information_unit(Absolute) of + {ok, ParsedAbsolute} -> ParsedAbsolute; + {error, parse_error} -> + rabbit_log:error("Unable to parse disk_free_limit value ~p", + [Absolute]), + ?DEFAULT_DISK_FREE_LIMIT + end. emit_update_info(StateStr, CurrentFree, Limit) -> rabbit_log:info( diff --git a/src/rabbit_resource_monitor_misc.erl b/src/rabbit_resource_monitor_misc.erl new file mode 100644 index 0000000000..88f3bd1121 --- /dev/null +++ b/src/rabbit_resource_monitor_misc.erl @@ -0,0 +1,49 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (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.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2007-2015 Pivotal Software, Inc. All rights reserved. +%% + + +-module(rabbit_resource_monitor_misc). + +-export([parse_information_unit/1]). + +-ifdef(use_spec). + +-spec(parse_information_unit/1 :: (integer() | string()) -> + {ok, integer()} | {error, parse_error}). + +-endif. + +parse_information_unit(Value) when is_integer(Value) -> {ok, Value}; +parse_information_unit(Value) when is_list(Value) -> + case re:run(Value, + "^(?<VAL>[0-9]+)(?<UNIT>kB|KB|MB|GB|kb|mb|gb|Kb|Mb|Gb|kiB|KiB|MiB|GiB|kib|mib|gib|KIB|MIB|GIB|k|K|m|M|g|G)?$", + [{capture, all_names, list}]) of + {match, [[], _]} -> + {ok, list_to_integer(Value)}; + {match, [Unit, Num]} -> + Multiplier = case Unit of + KiB when KiB =:= "k"; KiB =:= "kiB"; KiB =:= "K"; KiB =:= "KIB"; KiB =:= "kib" -> 1024; + MiB when MiB =:= "m"; MiB =:= "MiB"; MiB =:= "M"; MiB =:= "MIB"; MiB =:= "mib" -> 1024*1024; + GiB when GiB =:= "g"; GiB =:= "GiB"; GiB =:= "G"; GiB =:= "GIB"; GiB =:= "gib" -> 1024*1024*1024; + KB when KB =:= "KB"; KB =:= "kB"; KB =:= "kb"; KB =:= "Kb" -> 1000; + MB when MB =:= "MB"; MB =:= "mB"; MB =:= "mb"; MB =:= "Mb" -> 1000000; + GB when GB =:= "GB"; GB =:= "gB"; GB =:= "gb"; GB =:= "Gb" -> 1000000000 + end, + {ok, list_to_integer(Num) * Multiplier}; + nomatch -> + % log error + {error, parse_error} + end. diff --git a/src/vm_memory_monitor.erl b/src/vm_memory_monitor.erl index 1d98843365..e599f50103 100644 --- a/src/vm_memory_monitor.erl +++ b/src/vm_memory_monitor.erl @@ -49,6 +49,7 @@ %% wrong. Scale by vm_memory_high_watermark in configuration to get a %% sensible value. -define(MEMORY_SIZE_FOR_UNKNOWN_OS, 1073741824). +-define(DEFAULT_VM_MEMORY_HIGH_WATERMARK, 0.4). -record(state, {total_memory, memory_limit, @@ -63,7 +64,7 @@ -ifdef(use_specs). --type(vm_memory_high_watermark() :: (float() | {'absolute', integer()})). +-type(vm_memory_high_watermark() :: (float() | {'absolute', integer() | string()})). -spec(start_link/1 :: (float()) -> rabbit_types:ok_pid_or_error()). -spec(start_link/3 :: (float(), fun ((any()) -> 'ok'), fun ((any()) -> 'ok')) -> rabbit_types:ok_pid_or_error()). @@ -208,7 +209,7 @@ set_mem_limits(State, MemLimit) -> _ -> TotalMemory end, - MemLim = interpret_limit(MemLimit, UsableMemory), + MemLim = interpret_limit(parse_mem_limit(MemLimit), UsableMemory), error_logger:info_msg("Memory limit set to ~pMB of ~pMB total.~n", [trunc(MemLim/?ONE_MB), trunc(TotalMemory/?ONE_MB)]), internal_update(State #state { total_memory = TotalMemory, @@ -220,6 +221,20 @@ interpret_limit({'absolute', MemLim}, UsableMemory) -> interpret_limit(MemFraction, UsableMemory) -> trunc(MemFraction * UsableMemory). + +parse_mem_limit({absolute, Limit}) -> + case rabbit_resource_monitor_misc:parse_information_unit(Limit) of + {ok, ParsedLimit} -> {absolute, ParsedLimit}; + {error, parse_error} -> + rabbit_log:error("Unable to parse vm_memory_high_watermark value ~p", [Limit]), + ?DEFAULT_VM_MEMORY_HIGH_WATERMARK + end; +parse_mem_limit(Relative) when is_float(Relative), Relative < 1 -> + Relative; +parse_mem_limit(_) -> + ?DEFAULT_VM_MEMORY_HIGH_WATERMARK. + + internal_update(State = #state { memory_limit = MemLimit, alarmed = Alarmed, alarm_funs = {AlarmSet, AlarmClear} }) -> |
