Skip to content

Commit 9de5a60

Browse files
mkuratczykmergify[bot]
authored andcommitted
If a queue process is hibernated, consider it up (#7825)
`rabbit_core_metrics_gc` checks the status of all queues (and other things) every two minutes. With many queues, this can get pretty expensive. Systems with lots of queues will often have many of them idle and hibernated. Before this change `rabbit_core_metrics_gc` would wake up all of them, causing a memory spike, just to check if their state isn't `down`. With this change, a hibernated queue will be considered up. (cherry picked from commit 1c2c38d) # Conflicts: # deps/rabbit/src/rabbit_process.erl
1 parent 349c484 commit 9de5a60

File tree

2 files changed

+99
-6
lines changed

2 files changed

+99
-6
lines changed

deps/rabbit/src/rabbit_amqqueue.erl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,14 +1077,17 @@ list_local_names_down() ->
10771077
is_down(Q)].
10781078

10791079
is_down(Q) ->
1080-
try
1081-
info(Q, [state]) == [{state, down}]
1082-
catch
1083-
_:_ ->
1084-
true
1080+
case rabbit_process:is_process_hibernated(amqqueue:get_pid(Q)) of
1081+
true -> false;
1082+
false ->
1083+
try
1084+
info(Q, [state]) == [{state, down}]
1085+
catch
1086+
_:_ ->
1087+
true
1088+
end
10851089
end.
10861090

1087-
10881091
-spec sample_local_queues() -> [amqqueue:amqqueue()].
10891092
sample_local_queues() -> sample_n_by_name(list_local_names(), 300).
10901093

deps/rabbit/src/rabbit_process.erl

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
6+
%%
7+
8+
-module(rabbit_process).
9+
10+
-export([on_running_node/1,
11+
is_process_alive/1,
12+
is_process_hibernated/1,
13+
is_registered_process_alive/1]).
14+
15+
-spec on_running_node(Pid) -> OnRunningNode when
16+
Pid :: pid(),
17+
OnRunningNode :: boolean().
18+
%% @doc Indicates if the specified process runs on a member of the cluster.
19+
%%
20+
%% @param Pid the PID of the process to check
21+
%% @returns true if the process runs on one of the cluster members, false
22+
%% otherwise.
23+
24+
on_running_node(Pid) ->
25+
Node = node(Pid),
26+
rabbit_nodes:is_running(Node).
27+
28+
%% This requires the process be in the same running cluster as us
29+
%% (i.e. not partitioned or some random node).
30+
%%
31+
%% See also rabbit_misc:is_process_alive/1 which does not.
32+
33+
-spec is_process_alive(Pid) -> IsAlive when
34+
Pid :: pid() | {RegisteredName, Node},
35+
RegisteredName :: atom(),
36+
Node :: node(),
37+
IsAlive :: boolean().
38+
%% @doc Indicates if the specified process is alive.
39+
%%
40+
%% Unlike {@link erlang:is_process_alive/1}, this function works with remote
41+
%% processes and registered processes. However, the process must run on one of
42+
%% the cluster members.
43+
%%
44+
%% @param Pid the PID or name of the process to check
45+
%% @returns true if the process is alive runs on one of the cluster members,
46+
%% false otherwise.
47+
48+
is_process_alive(Pid) when is_pid(Pid) ->
49+
on_running_node(Pid)
50+
andalso
51+
rpc:call(node(Pid), erlang, is_process_alive, [Pid]) =:= true;
52+
is_process_alive({Name, Node}) when is_atom(Name) andalso is_atom(Node) ->
53+
case rabbit_nodes:is_running(Node) of
54+
true ->
55+
try
56+
erpc:call(Node, ?MODULE, is_registered_process_alive, [Name])
57+
catch
58+
error:{exception, undef, [{?MODULE, _, _, _} | _]} ->
59+
rpc:call(
60+
Node,
61+
rabbit_mnesia, is_registered_process_alive, [Name])
62+
end;
63+
false ->
64+
false
65+
end.
66+
67+
-spec is_registered_process_alive(RegisteredName) -> IsAlive when
68+
RegisteredName :: atom(),
69+
IsAlive :: boolean().
70+
%% @doc Indicates if the specified registered process is alive.
71+
%%
72+
%% The process must be local to this node.
73+
%%
74+
%% @param RegisteredName the name of the registered process
75+
%% @returns true if the process is alive, false otherwise.
76+
77+
is_registered_process_alive(Name) ->
78+
is_pid(whereis(Name)).
79+
80+
-spec is_process_hibernated(Pid) -> IsHibernated when
81+
Pid :: pid(),
82+
IsHibernated :: boolean().
83+
%% @doc Indicates if the specified process is hibernated.
84+
%%
85+
%% @param Pid the PID or name of the process to check
86+
%% @returns true if the process is hibernated on one of the cluster members,
87+
%% false otherwise.
88+
89+
is_process_hibernated(Pid) when is_pid(Pid) ->
90+
{current_function,{erlang,hibernate,3}} == erlang:process_info(Pid, current_function).

0 commit comments

Comments
 (0)