raptor 0.22.3 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/Dockerfile +10 -2
  4. data/README.md +183 -61
  5. data/docs/assets/profile_picture.png +0 -0
  6. data/docs/assets/startup_output.svg +37 -0
  7. data/docs/raptor-vs-puma.md +104 -424
  8. data/docs/talk.md +1388 -0
  9. data/ext/raptor_bpf/reuseport_select.bpf.c +18 -9
  10. data/ext/raptor_http/extconf.rb +2 -0
  11. data/ext/raptor_http/raptor_http.c +165 -234
  12. data/ext/raptor_http2/raptor_http2.c +272 -223
  13. data/ext/raptor_native/raptor_native.c +38 -20
  14. data/lib/rackup/handler/raptor.rb +14 -12
  15. data/lib/raptor/binder.rb +12 -12
  16. data/lib/raptor/cli.rb +19 -18
  17. data/lib/raptor/cluster.rb +120 -74
  18. data/lib/raptor/control_server.rb +5 -2
  19. data/lib/raptor/detached_body.rb +6 -2
  20. data/lib/raptor/http.rb +7 -6
  21. data/lib/raptor/http1.rb +281 -234
  22. data/lib/raptor/http2.rb +356 -276
  23. data/lib/raptor/plugin.rb +98 -0
  24. data/lib/raptor/reactor.rb +138 -148
  25. data/lib/raptor/reuseport_bpf.rb +62 -38
  26. data/lib/raptor/server.rb +45 -34
  27. data/lib/raptor/stats.rb +15 -3
  28. data/lib/raptor/thread_locals.rb +4 -3
  29. data/lib/raptor/version.rb +1 -1
  30. data/sig/generated/rackup/handler/raptor.rbs +2 -1
  31. data/sig/generated/raptor/binder.rbs +9 -9
  32. data/sig/generated/raptor/cli.rbs +6 -6
  33. data/sig/generated/raptor/cluster.rbs +18 -5
  34. data/sig/generated/raptor/control_server.rbs +2 -1
  35. data/sig/generated/raptor/detached_body.rbs +5 -1
  36. data/sig/generated/raptor/http.rbs +3 -5
  37. data/sig/generated/raptor/http1.rbs +119 -102
  38. data/sig/generated/raptor/http2.rbs +204 -190
  39. data/sig/generated/raptor/plugin.rbs +52 -0
  40. data/sig/generated/raptor/reactor.rbs +107 -118
  41. data/sig/generated/raptor/reuseport_bpf.rbs +54 -17
  42. data/sig/generated/raptor/server.rbs +26 -26
  43. data/sig/generated/raptor/stats.rbs +3 -2
  44. data/sig/generated/raptor/thread_locals.rbs +4 -3
  45. metadata +6 -2
  46. data/docs/brisrails-talk.md +0 -2398
@@ -6,14 +6,41 @@ module Raptor
6
6
  #
7
7
  # Auto-enabled on Linux when the `libbpf-ruby` gem is installed and the
8
8
  # BPF object file has been compiled. Falls back silently to standard
9
- # `SO_REUSEPORT` when either is missing. Raises when the kernel refuses
10
- # the BPF program. Wraps `tcp://` bindings only; non-tcp bindings are
11
- # left to the binder's shared listeners.
9
+ # `SO_REUSEPORT` when either is missing, or when there are more workers
10
+ # or listeners than the BPF maps have slots for. Raises when the kernel
11
+ # refuses the BPF program. Wraps `tcp://` bindings only; non-tcp bindings
12
+ # are left to the binder's shared listeners.
12
13
  module ReuseportBPF
13
14
  LIBBPF_LOADED: untyped
14
15
 
15
16
  BPF_OBJECT_PATH: untyped
16
17
 
18
+ TCP_INFO_UNACKED_OFFSET: ::Integer
19
+
20
+ UNAVAILABLE_LOAD: ::Integer
21
+
22
+ MAX_WORKERS: ::Integer
23
+
24
+ MAX_LISTENERS: ::Integer
25
+
26
+ self.@accepted_load_value: String
27
+
28
+ self.@load_value: String
29
+
30
+ self.@load_key: String
31
+
32
+ self.@worker_listeners: Array[TCPServer]
33
+
34
+ self.@shared_listeners: Array[TCPServer]
35
+
36
+ self.@loads_fd: Integer?
37
+
38
+ self.@socks_fd: Integer
39
+
40
+ self.@program_fd: Integer
41
+
42
+ self.@object: untyped
43
+
17
44
  # Returns true when the preconditions for BPF-directed reuseport are
18
45
  # met on this platform.
19
46
  #
@@ -22,28 +49,30 @@ module Raptor
22
49
  # @rbs () -> bool
23
50
  def self.supported?: () -> bool
24
51
 
25
- # Prepares BPF-directed routing for `worker_count` workers.
52
+ # Prepares BPF-directed routing for `worker_count` workers across the
53
+ # addresses `shared_listeners` are bound to.
26
54
  #
27
55
  # Returns true when BPF-directed dispatch is active. Returns false
28
- # when the platform is unsupported. Raises when the kernel refuses
29
- # the program.
56
+ # when the platform is unsupported or the counts exceed the map slots.
57
+ # Raises when the kernel refuses the program.
30
58
  #
31
59
  # @param worker_count [Integer] number of worker processes that will bind sockets
60
+ # @param shared_listeners [Array<TCPServer>] the binder's tcp listeners
32
61
  # @return [Boolean]
33
62
  #
34
- # @rbs (Integer worker_count) -> bool
35
- def self.setup: (Integer worker_count) -> bool
63
+ # @rbs (Integer worker_count, Array[TCPServer] shared_listeners) -> bool
64
+ def self.setup: (Integer worker_count, Array[TCPServer] shared_listeners) -> bool
36
65
 
37
- # Returns tcp listening sockets bound and registered for `worker_index`.
38
- # Skips non-tcp bind URIs.
66
+ # Creates this worker's BPF-routed listeners at the shared listeners'
67
+ # bound addresses, including resolved `localhost` addresses and ports
68
+ # assigned by the kernel for port 0.
39
69
  #
40
- # @param bind_uris [Array<String>] the configured bind URIs
41
70
  # @param worker_index [Integer] slot index for this worker in the socks map
42
71
  # @param socket_backlog [Integer] kernel listen() queue depth
43
72
  # @return [Array<TCPServer>] the tcp listening sockets created for this worker
44
73
  #
45
- # @rbs (Array[String] bind_uris, Integer worker_index, Integer socket_backlog) -> Array[TCPServer]
46
- def self.create_worker_listeners: (Array[String] bind_uris, Integer worker_index, Integer socket_backlog) -> Array[TCPServer]
74
+ # @rbs (Integer worker_index, Integer socket_backlog) -> Array[TCPServer]
75
+ def self.create_worker_listeners: (Integer worker_index, Integer socket_backlog) -> Array[TCPServer]
47
76
 
48
77
  # Prepares this worker's load-reporting slot so subsequent
49
78
  # {update_load} calls can publish its backlog.
@@ -54,7 +83,7 @@ module Raptor
54
83
  # @rbs (Integer worker_index) -> void
55
84
  def self.enable_load_reporting: (Integer worker_index) -> void
56
85
 
57
- # Publishes this worker's current backlog to the BPF map.
86
+ # Publishes this worker's load to the BPF map.
58
87
  #
59
88
  # @param backlog [Integer] the worker's current reactor backlog
60
89
  # @return [void]
@@ -62,7 +91,7 @@ module Raptor
62
91
  # @rbs (Integer backlog) -> void
63
92
  def self.update_load: (Integer backlog) -> void
64
93
 
65
- # Publishes an accept-side backlog estimate. This uses a separate value
94
+ # Publishes an accept-side load estimate. This uses a separate value
66
95
  # buffer because the server and load reporter call into the map from
67
96
  # different threads.
68
97
  #
@@ -72,13 +101,21 @@ module Raptor
72
101
  # @rbs (Integer backlog) -> void
73
102
  def self.update_accepted_load: (Integer backlog) -> void
74
103
 
75
- # Marks a worker's slot as unavailable by parking its load at the
76
- # sentinel maximum so the BPF program's least-loaded pick skips it.
104
+ # Parks a worker's load at the maximum so BPF favors other workers.
105
+ # Stop publishing its load first to avoid overwriting the sentinel.
77
106
  #
78
107
  # @param worker_index [Integer] slot index for the worker to mark
79
108
  # @return [void]
80
109
  #
81
110
  # @rbs (Integer worker_index) -> void
82
111
  def self.mark_unavailable: (Integer worker_index) -> void
112
+
113
+ # Returns the number of connections waiting in this worker's accept
114
+ # queues, which the reactor backlog cannot see.
115
+ #
116
+ # @return [Integer]
117
+ #
118
+ # @rbs () -> Integer
119
+ def self.accept_queue_length: () -> Integer
83
120
  end
84
121
  end
@@ -1,10 +1,8 @@
1
1
  # Generated from lib/raptor/server.rb with RBS::Inline
2
2
 
3
3
  module Raptor
4
- # Accepts client connections on TCP, Unix, and SSL listeners and
5
- # dispatches them into the request pipeline. Yields between accepts
6
- # when the thread pool queue exceeds the pool size so overloaded
7
- # workers stay responsive to in-flight requests.
4
+ # Accepts client connections on TCP, Unix, SSL, and cleartext HTTP/2
5
+ # listeners and dispatches them into the request pipeline.
8
6
  class Server
9
7
  HTTP_SCHEME: ::String
10
8
 
@@ -20,10 +18,6 @@ module Raptor
20
18
 
21
19
  MIN_BACKPRESSURE_THRESHOLD: ::Integer
22
20
 
23
- @binder: Binder
24
-
25
- @listeners: Array[TCPServer | UNIXServer | Binder::SslListener]
26
-
27
21
  @reactor: Reactor
28
22
 
29
23
  @thread_pool: AtomicThreadPool
@@ -34,27 +28,33 @@ module Raptor
34
28
 
35
29
  @first_data_timeout: Integer
36
30
 
31
+ @listeners: Array[TCPServer | UNIXServer | Binder::SslListener | Binder::H2cListener]
32
+
37
33
  @drain_accept_queue: bool
38
34
 
39
- @bpf_active: bool
35
+ @worker_index: Integer?
40
36
 
41
37
  @running: AtomicBoolean
42
38
 
43
- # Creates a new Server instance.
39
+ @thread: Thread?
40
+
41
+ @load_reporter: Thread?
42
+
43
+ # Creates a new Server.
44
44
  #
45
- # @param binder [Binder] the binder managing listening sockets
46
45
  # @param reactor [Reactor] the reactor for handling client connections
47
46
  # @param thread_pool [AtomicThreadPool] thread pool for application processing
48
47
  # @param http1 [Http1] the HTTP/1.1 handler
49
- # @param http2 [Http2] the HTTP/2 handler (provides the initial SETTINGS frame)
48
+ # @param http2 [Http2] the HTTP/2 handler
50
49
  # @param connection_options [Hash] per-connection timeout configuration, used to bound TLS handshakes
51
- # @param listeners [Array] the per-worker listeners this server accepts on
50
+ # @option connection_options [Integer] :first_data_timeout timeout for completing the TLS handshake
51
+ # @param listeners [Array<TCPServer, UNIXServer, Binder::SslListener, Binder::H2cListener>] the per-worker listeners this server accepts on
52
52
  # @param drain_accept_queue [Boolean] whether to drain the kernel accept queue on shutdown
53
- # @param worker_index [Integer, nil] the slot index for BPF load reporting
53
+ # @param worker_index [Integer, nil] this worker's BPF slot index, or nil when BPF dispatch is inactive
54
54
  # @return [void]
55
55
  #
56
- # @rbs (Binder binder, Reactor reactor, AtomicThreadPool thread_pool, Http1 http1, Http2 http2, connection_options: Hash[Symbol, untyped], listeners: Array[untyped], ?drain_accept_queue: bool, ?worker_index: Integer?) -> void
57
- def initialize: (Binder binder, Reactor reactor, AtomicThreadPool thread_pool, Http1 http1, Http2 http2, connection_options: Hash[Symbol, untyped], listeners: Array[untyped], ?drain_accept_queue: bool, ?worker_index: Integer?) -> void
56
+ # @rbs (Reactor reactor, AtomicThreadPool thread_pool, Http1 http1, Http2 http2, connection_options: Hash[Symbol, untyped], listeners: Array[TCPServer | UNIXServer | Binder::SslListener | Binder::H2cListener], ?drain_accept_queue: bool, ?worker_index: Integer?) -> void
57
+ def initialize: (Reactor reactor, AtomicThreadPool thread_pool, Http1 http1, Http2 http2, connection_options: Hash[Symbol, untyped], listeners: Array[TCPServer | UNIXServer | Binder::SslListener | Binder::H2cListener], ?drain_accept_queue: bool, ?worker_index: Integer?) -> void
58
58
 
59
59
  # Starts the server's main accept loop in a new thread.
60
60
  #
@@ -82,13 +82,13 @@ module Raptor
82
82
 
83
83
  private
84
84
 
85
- # Starts a background thread that publishes this worker's reactor
86
- # backlog to the BPF map for load-aware dispatch.
85
+ # Starts a background thread that publishes this worker's load to the
86
+ # BPF map for load-aware dispatch.
87
87
  #
88
- # @return [void]
88
+ # @return [Thread] the load reporter
89
89
  #
90
- # @rbs () -> void
91
- def spawn_load_reporter: () -> void
90
+ # @rbs () -> Thread
91
+ def spawn_load_reporter: () -> Thread
92
92
 
93
93
  # Dispatches every connection already in the kernel accept queue for each
94
94
  # listener until all are drained.
@@ -100,13 +100,13 @@ module Raptor
100
100
 
101
101
  # Accepts a connection from the given listener, immediately publishes
102
102
  # the pending work to the BPF map, and dispatches the socket into the
103
- # HTTP/1.1 or SSL/HTTP-2 pipeline.
103
+ # SSL, cleartext HTTP/2, or HTTP/1.1 pipeline.
104
104
  #
105
- # @param listener [TCPServer, UNIXServer, Binder::SslListener] the ready listener
105
+ # @param listener [TCPServer, UNIXServer, Binder::SslListener, Binder::H2cListener] the ready listener
106
106
  # @return [Boolean] true if a connection was accepted, false if the listener had nothing to dispatch
107
107
  #
108
- # @rbs (TCPServer | UNIXServer | Binder::SslListener listener) -> bool
109
- def accept_connection: (TCPServer | UNIXServer | Binder::SslListener listener) -> bool
108
+ # @rbs (TCPServer | UNIXServer | Binder::SslListener | Binder::H2cListener listener) -> bool
109
+ def accept_connection: (TCPServer | UNIXServer | Binder::SslListener | Binder::H2cListener listener) -> bool
110
110
 
111
111
  # Performs the TLS handshake for an accepted SSL connection, bounded
112
112
  # by `:first_data_timeout`, and dispatches it through the HTTP/2 or
@@ -114,7 +114,7 @@ module Raptor
114
114
  #
115
115
  # @param listener [Binder::SslListener] the SSL listener that accepted the connection
116
116
  # @param tcp_client [TCPSocket] the accepted TCP socket
117
- # @param remote_addr [String] the client's IP address
117
+ # @param remote_addr [String] the client IP address
118
118
  # @return [void]
119
119
  #
120
120
  # @rbs (Binder::SslListener listener, TCPSocket tcp_client, String remote_addr) -> void
@@ -25,7 +25,8 @@ module Raptor
25
25
 
26
26
  @mmap: untyped
27
27
 
28
- # Allocates the shared mmap region for `num_workers` slots.
28
+ # Creates a new Stats and allocates the shared mmap region for
29
+ # `num_workers` slots.
29
30
  #
30
31
  # @param num_workers [Integer] number of worker slots to allocate
31
32
  # @return [void]
@@ -68,7 +69,7 @@ module Raptor
68
69
 
69
70
  # Reads stats for a worker slot from shared memory.
70
71
  #
71
- # @param slot [Integer] slot offset to read from
72
+ # @param slot [Integer] slot index to read from
72
73
  # @return [Hash] stat hash with :pid, :index, :phase, :requests, :backlog, :busy_threads, :thread_capacity, :started_at, :last_checkin, and :booted
73
74
  #
74
75
  # @rbs (Integer slot) -> Hash[Symbol, untyped]
@@ -9,14 +9,15 @@ module Raptor
9
9
  # Returns a reusable value stored on the current thread.
10
10
  #
11
11
  # @param key [Symbol] thread-variable key used to cache the value
12
- # @yieldreturn [Object] value to store when the key is unset
12
+ # @yield when the key is unset
13
+ # @yieldreturn [Object] the value to store
13
14
  # @return [Object] the existing or newly stored value
14
15
  #
15
16
  # @rbs (Symbol key) { () -> untyped } -> untyped
16
17
  def self.fetch: (Symbol key) { () -> untyped } -> untyped
17
18
 
18
- # Clears application-owned true thread locals while retaining Raptor's
19
- # reusable per-thread values.
19
+ # Clears application thread locals while retaining Raptor's reusable
20
+ # per-thread values.
20
21
  #
21
22
  # @return [void]
22
23
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raptor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.3
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Young
@@ -141,8 +141,10 @@ files:
141
141
  - LICENSE.txt
142
142
  - README.md
143
143
  - Rakefile
144
- - docs/brisrails-talk.md
144
+ - docs/assets/profile_picture.png
145
+ - docs/assets/startup_output.svg
145
146
  - docs/raptor-vs-puma.md
147
+ - docs/talk.md
146
148
  - exe/raptor
147
149
  - ext/raptor_bpf/reuseport_select.bpf.c
148
150
  - ext/raptor_http/extconf.rb
@@ -163,6 +165,7 @@ files:
163
165
  - lib/raptor/http1.rb
164
166
  - lib/raptor/http2.rb
165
167
  - lib/raptor/log.rb
168
+ - lib/raptor/plugin.rb
166
169
  - lib/raptor/reactor.rb
167
170
  - lib/raptor/reuseport_bpf.rb
168
171
  - lib/raptor/server.rb
@@ -181,6 +184,7 @@ files:
181
184
  - sig/generated/raptor/http1.rbs
182
185
  - sig/generated/raptor/http2.rbs
183
186
  - sig/generated/raptor/log.rbs
187
+ - sig/generated/raptor/plugin.rbs
184
188
  - sig/generated/raptor/reactor.rbs
185
189
  - sig/generated/raptor/reuseport_bpf.rbs
186
190
  - sig/generated/raptor/server.rbs