Class: Async::Service::Supervisor::Envoy::Monitor

Inherits:
Monitor
  • Object
show all
Defined in:
lib/async/service/supervisor/envoy/monitor.rb

Overview

Represents a supervisor monitor that publishes worker endpoints to Envoy using xDS.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bind: nil, delegate: Delegate.new, control_plane: Async::GRPC::XDS::ControlPlane.new, health_checks: [], orca: false, processor: nil, utilization_monitor: nil, interval: 1, **options) ⇒ Monitor

Initialize the monitor.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 36

def initialize(
	bind: nil,
	delegate: Delegate.new,
	control_plane: Async::GRPC::XDS::ControlPlane.new,
	health_checks: [],
	orca: false,
	processor: nil,
	utilization_monitor: nil,
	interval: 1,
	**options
)
	super(interval: interval, **options)
	
	@bind = bind
	@delegate = delegate
	@control_plane = control_plane
	@health_checks = health_checks
	@interval = interval
	@orca = orca
	@controllers = {}
	@published_clusters = {}
	@server_task = nil
	@mutex = Mutex.new
	
	if @orca
		raise ArgumentError, "ORCA reporting requires a TCP bind address!" unless @bind
		raise ArgumentError, "ORCA reporting requires a utilization monitor!" unless utilization_monitor
		
		@orca_port = server_endpoint.url.port
		raise ArgumentError, "ORCA reporting requires a fixed TCP port!" unless @orca_port&.positive?
		
		@processor = processor || Process::Metrics::Processor.new
		@utilization_monitor = utilization_monitor
		@request_totals = {}
		@load_reports = {}
		@authorities = {}
	end
end

Instance Attribute Details

#control_planeObject (readonly)

Returns the value of attribute control_plane.



76
77
78
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 76

def control_plane
  @control_plane
end

#delegateObject (readonly)

Returns the value of attribute delegate.



79
80
81
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 79

def delegate
  @delegate
end

#The xDS control plane receiving cluster and endpoint updates.(xDScontrolplanereceivingcluster) ⇒ Object (readonly)



76
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 76

attr :control_plane

Instance Method Details

#as_jsonObject

Convert the currently published endpoints to JSON-compatible data.



127
128
129
130
131
132
133
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 127

def as_json
	@mutex.synchronize do
		{
			clusters: build_clusters
		}
	end
end

#load_report(authority) ⇒ Object

Get the latest ORCA report for a worker authority.



147
148
149
150
151
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 147

def load_report(authority)
	return unless @orca
	
	@mutex.synchronize{@load_reports[authority]}
end

#register(supervisor_controller) ⇒ Object

Register a supervisor worker with Envoy.



84
85
86
87
88
89
90
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 84

def register(supervisor_controller)
	@mutex.synchronize do
		@controllers[supervisor_controller.id] = supervisor_controller
		@authorities[worker_hostname(supervisor_controller)] = supervisor_controller.id if @orca
		reconcile
	end
end

#remove(supervisor_controller) ⇒ Object

Remove a supervisor worker from Envoy.



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 95

def remove(supervisor_controller)
	@mutex.synchronize do
		@controllers.delete(supervisor_controller.id)
		if @orca
			hostname = worker_hostname(supervisor_controller)
			@authorities.delete(hostname)
			@load_reports.delete(hostname)
			@request_totals.delete(supervisor_controller.id)
		end
		reconcile
	end
end

#run(parent: Async::Task.current) ⇒ Object

Run the monitor and optional xDS server task.



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 111

def run(parent: Async::Task.current)
	task = super(parent: parent)
	
	if @bind
		@server_task = parent.async do
			server = Async::GRPC::XDS::Server.new(@control_plane)
			server.dispatcher.register(ORCAService.new(self, minimum_interval: @interval)) if @orca
			server.run(server_endpoint)
		end
	end
	
	task
end

#run_onceObject

Refresh endpoint health and publish updated EDS state.



155
156
157
158
159
160
161
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 155

def run_once
	sample_load_reports if @orca
	
	@mutex.synchronize do
		reconcile
	end
end

#The delegate used to map supervisor state into Envoy endpoints.=(delegateusedtomapsupervisorstateintoEnvoyendpoints. = (value)) ⇒ Object



79
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 79

attr :delegate

#worker?(authority) ⇒ Boolean

Determine whether an ORCA worker authority is currently registered.

Returns:

  • (Boolean)


138
139
140
141
142
# File 'lib/async/service/supervisor/envoy/monitor.rb', line 138

def worker?(authority)
	return false unless @orca
	
	@mutex.synchronize{@authorities.key?(authority)}
end