Class: Karafka::Pro::Swarm::LivenessListener
- Inherits:
-
Swarm::LivenessListener
- Object
- Swarm::LivenessListener
- Karafka::Pro::Swarm::LivenessListener
- Defined in:
- lib/karafka/pro/swarm/liveness_listener.rb
Overview
This listener should not break anything if subscribed in the supervisor prior to forking as it relies on server events for operations.
Pro listener that monitors RSS usage and other heartbeat metrics (if configured) to ensure that everything operates.
It can:
- monitor poll frequency to make sure things are not polled not often enough
- monitor consumption to make sure we do not process data for too long
- monitor RSS to make sure that we do not use too much memory
By default it does not monitor memory and consuming and polling is configured in such
a way to align with max.poll.interval.ms and other defaults.
Failure statuses reported are as follows:
- 1 - polling ttl exceeded
- 2 - consuming ttl exceeded
- 3 - memory limit exceeded
- 4 - stability ttl exceeded (stuck in non-steady librdkafka join state)
Instance Method Summary collapse
-
#initialize(memory_limit: Float::INFINITY, consuming_ttl: DEFAULT_CONSUMING_TTL, polling_ttl: DEFAULT_POLLING_TTL, stability_ttl: nil) ⇒ LivenessListener
constructor
A new instance of LivenessListener.
-
#on_client_events_poll(_event) ⇒ Object
Report liveness during events poll so it works during long processing without statistics.
- #on_connection_listener_after_fetch_loop(event) ⇒ Object
-
#on_connection_listener_before_fetch_loop(_event) ⇒ Object
Report status before the first fetch loop iteration so the supervisor gets an initial healthy report even if the first consumption takes longer than the report timeout.
-
#on_connection_listener_fetch_loop(_event) ⇒ Object
Tick on each fetch and report liveness so it works even when statistics are disabled.
-
#on_connection_listener_stopped(_event) ⇒ Object
Deregister the polling tracker for given listener.
-
#on_connection_listener_stopping(_event) ⇒ Object
Deregister the polling tracker for given listener.
- #on_error_occurred(_event) ⇒ Object
- #on_statistics_emitted(event) ⇒ Object
Constructor Details
#initialize(memory_limit: Float::INFINITY, consuming_ttl: DEFAULT_CONSUMING_TTL, polling_ttl: DEFAULT_POLLING_TTL, stability_ttl: nil) ⇒ LivenessListener
Returns a new instance of LivenessListener.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 76 def initialize( memory_limit: Float::INFINITY, consuming_ttl: DEFAULT_CONSUMING_TTL, polling_ttl: DEFAULT_POLLING_TTL, stability_ttl: nil ) @polling_ttl = polling_ttl @consuming_ttl = consuming_ttl # When nil, resolved lazily via #stability_ttl on first health evaluation because # the default derives from the routing subscription groups, which may not be drawn # yet when the listener is constructed in karafka.rb @stability_ttl = stability_ttl # We cast it just in case someone would provide '10MB' or something similar @memory_limit = memory_limit.is_a?(String) ? memory_limit.to_i : memory_limit @pollings = {} @consumptions = {} @join_states = {} @instabilities = {} super() end |
Instance Method Details
#on_client_events_poll(_event) ⇒ Object
Report liveness during events poll so it works during long processing without statistics. This event fires periodically during wait even when the listener is blocked on consumer jobs, preventing the supervisor from killing the node.
117 118 119 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 117 def on_client_events_poll(_event) report_status end |
#on_connection_listener_after_fetch_loop(event) ⇒ Object
192 193 194 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 192 def on_connection_listener_after_fetch_loop(event) clear_instability_tracking(event[:subscription_group]) end |
#on_connection_listener_before_fetch_loop(_event) ⇒ Object
Report status before the first fetch loop iteration so the supervisor gets an initial healthy report even if the first consumption takes longer than the report timeout.
101 102 103 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 101 def on_connection_listener_before_fetch_loop(_event) report_status end |
#on_connection_listener_fetch_loop(_event) ⇒ Object
Tick on each fetch and report liveness so it works even when statistics are disabled
108 109 110 111 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 108 def on_connection_listener_fetch_loop(_event) mark_polling_tick report_status end |
#on_connection_listener_stopped(_event) ⇒ Object
Deregister the polling tracker for given listener
183 184 185 186 187 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 183 def on_connection_listener_stopped(_event) return if Karafka::App.done? clear_polling_tick end |
#on_connection_listener_stopping(_event) ⇒ Object
Deregister the polling tracker for given listener
171 172 173 174 175 176 177 178 179 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 171 def on_connection_listener_stopping(_event) # We are interested in disabling tracking for given listener only if it was requested # when karafka was running. If we would always clear, it would not catch the shutdown # polling requirements. The "running" listener shutdown operations happen only when # the manager requests it for downscaling. return if Karafka::App.done? clear_polling_tick end |
#on_error_occurred(_event) ⇒ Object
164 165 166 167 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 164 def on_error_occurred(_event) clear_consumption_tick clear_polling_tick end |
#on_statistics_emitted(event) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/karafka/pro/swarm/liveness_listener.rb', line 144 def on_statistics_emitted(event) cgrp = event[:statistics]&.dig("cgrp") return unless cgrp sg_id = event[:subscription_group_id] join_state = cgrp["join_state"] return unless join_state synchronize do if join_state == "steady" || join_state == "init" || join_state == "wait-metadata" @instabilities.delete(sg_id) @join_states.delete(sg_id) elsif @join_states[sg_id] != join_state @join_states[sg_id] = join_state @instabilities[sg_id] = monotonic_now end end end |