Class: Raptor::Cluster
- Inherits:
-
Object
- Object
- Raptor::Cluster
- Defined in:
- lib/raptor/cluster.rb
Overview
Multi-process web server cluster with advanced concurrency architecture.
Cluster manages multiple worker processes, each running a complete server stack including a ractor pool for HTTP parsing, a thread pool for application processing, plus dedicated reactor and server threads. It handles process forking, signal management, graceful shutdown, and automatic worker restart when a worker process unexpectedly exits.
The architecture provides horizontal scaling through processes while maintaining efficient I/O and CPU utilization within each process through the combination of ractor-based parsing and thread pools on top of NIO reactors.
Flow per worker process:
-
Server continuously accepts connections but skips acceptance when backlog is high
-
Reactor manages I/O multiplexing and provides backlog metrics for load control
-
Ractor pool handles CPU-intensive HTTP parsing in parallel
-
Thread pool processes Rack applications and handles response writing
-
Natural load balancing occurs through backpressure-based acceptance control
Class Method Summary collapse
-
.run(options) ⇒ void
Convenience method to create and run a cluster with the given options.
Instance Method Summary collapse
-
#initialize(options) ⇒ void
constructor
Creates a new Cluster with the specified configuration.
-
#run ⇒ void
Starts the multi-process cluster and manages worker processes.
-
#stats ⇒ Array<Hash>
Returns stats for all worker processes.
Constructor Details
#initialize(options) ⇒ void
Creates a new Cluster with the specified configuration.
Initializes the cluster with worker, ractor, and thread counts, sets up network binding, loads the Rack application, and prepares for multi-process operation.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/raptor/cluster.rb', line 103 def initialize() @worker_count = [:workers] @ractor_count = [:ractors] @thread_count = [:threads] @client_options = [:client] @worker_timeout = [:worker_timeout] @worker_boot_timeout = [:worker_boot_timeout] @worker_shutdown_timeout = [:worker_shutdown_timeout] @stats_file = [:stats_file] @pid_file = [:pid_file] @on_error = [:on_error] @binder = Binder.new([:binds]) @server_port = @binder.server_port @app = [:app] || Rack::Builder.parse_file([:rackup]) log_initialization @shutdown = false @workers = {} @timed_out = Set.new @stats = Stats.new(@worker_count) @phase = 0 @phased_restart_requested = false @phased_restarting = false end |
Class Method Details
.run(options) ⇒ void
This method returns an undefined value.
Convenience method to create and run a cluster with the given options.
55 56 57 |
# File 'lib/raptor/cluster.rb', line 55 def self.run() new().run end |
Instance Method Details
#run ⇒ void
This method returns an undefined value.
Starts the multi-process cluster and manages worker processes.
Forks the configured number of worker processes and monitors them, restarting any that exit unexpectedly or stop checking in. Handles graceful shutdown via INT or TERM signals, stats logging via USR1, and phased restart via USR2.
Each worker process includes:
-
1 server thread (continuously accepts connections with backpressure control)
-
1 reactor thread (I/O multiplexing, timeout handling, backlog monitoring)
-
N pipeline ractors (parallel HTTP parsing)
-
1 pipeline collector thread (coordinates parsing results)
-
M worker threads (Rack application processing and response writing)
-
1 stats thread (writes per-worker metrics to shared memory every second)
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/raptor/cluster.rb', line 147 def run trap("INT") { shutdown } trap("TERM") { shutdown } trap("USR1") { log_stats } trap("USR2") { @phased_restart_requested = true } File.open(@pid_file, File::CREAT | File::EXCL | File::WRONLY) { |file| file.write(Process.pid.to_s) } if @pid_file @worker_count.times { |index| spawn_worker(index) } stats_file_thread = if @stats_file Thread.new do Thread.current.name = "Raptor Stats File" write_stats_file_loop end end until @shutdown break if reap_workers == :no_children perform_phased_restart if @phased_restart_requested && !@phased_restarting timeout_hung_workers sleep 0.1 end stop_workers stats_file_thread&.join File.delete(@stats_file) rescue nil if @stats_file File.delete(@pid_file) rescue nil if @pid_file @stats.unmap end |
#stats ⇒ Array<Hash>
Returns stats for all worker processes.
187 188 189 |
# File 'lib/raptor/cluster.rb', line 187 def stats @stats.all end |