Class: Raptor::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/raptor/server.rb

Overview

Accepts client connections and dispatches them into the request pipeline. Skips acceptance when the reactor backlog is high so an overloaded process leaves connections for peers that can absorb them (via shared ‘SO_REUSEPORT` listeners).

Supports TCP, Unix, and SSL listeners. SSL handshakes are offloaded to the thread pool so a slow client can’t pin the server thread. For HTTP/1.1 the first request is parsed inline and dispatched straight to the thread pool; HTTP/2 (negotiated via ALPN) is registered with the reactor for frame processing.

Examples:

binder = Binder.new(["tcp://0.0.0.0:3000"])
reactor = Reactor.new(ractor_pool, thread_pool, client_options: {})
request = Request.new(app, 3000)
server = Server.new(binder, reactor, thread_pool, request, client_options: { first_data_timeout: 30 })
server.run
# ... later
server.shutdown

Constant Summary collapse

HTTP_SCHEME =
"http"
HTTPS_SCHEME =
"https"
H2_PROTOCOL =
"h2"
DEFAULT_REMOTE_ADDR =
"127.0.0.1"
DEFAULT_SERVER_NAME =
"localhost"
MIN_BACKPRESSURE_THRESHOLD =
64

Instance Method Summary collapse

Constructor Details

#initialize(binder, reactor, thread_pool, request, client_options:) ⇒ void

Creates a new Server instance.

Parameters:

  • binder (Binder)

    the binder managing listening sockets

  • reactor (Reactor)

    the reactor for handling client connections

  • thread_pool (AtomicThreadPool)

    thread pool for application processing

  • request (Request)

    the HTTP/1.1 request handler

  • client_options (Hash)

    client timeout configuration, used to bound TLS handshakes



57
58
59
60
61
62
63
64
# File 'lib/raptor/server.rb', line 57

def initialize(binder, reactor, thread_pool, request, client_options:)
  @binder = binder
  @reactor = reactor
  @thread_pool = thread_pool
  @request = request
  @client_options = client_options
  @running = AtomicBoolean.new(true)
end

Instance Method Details

#runThread

Starts the server’s main accept loop in a new thread.

The accept loop polls listening sockets for ready connections and accepts them when system capacity allows. It checks reactor backlog before accepting to prevent overload. This provides natural load balancing across multiple worker processes through backpressure control.

Returns:

  • (Thread)

    the thread running the accept loop



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/raptor/server.rb', line 76

def run
  Thread.new(@binder.listeners, @reactor, @running) do |server_sockets, reactor, running|
    Thread.current.name = "Server"

    while running.true?
      begin
        ready_servers, _, _ = IO.select(server_sockets, nil, nil, 1)
      rescue IOError, Errno::EBADF
        break
      end

      next unless ready_servers
      next if @reactor.backlog >= [(@thread_pool.size * 1.2).ceil, MIN_BACKPRESSURE_THRESHOLD].max

      ready_servers.each do |listener|
        accept_connection(listener, reactor)
      end
    end
  end
end

#shutdownvoid

This method returns an undefined value.

Gracefully shuts down the server.

Stops accepting new connections and closes all listening sockets. The server thread will exit after handling any in-flight accept operations.



105
106
107
108
# File 'lib/raptor/server.rb', line 105

def shutdown
  @running.make_false
  @binder.close
end