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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/Dockerfile +10 -2
- data/README.md +183 -61
- data/docs/assets/profile_picture.png +0 -0
- data/docs/assets/startup_output.svg +37 -0
- data/docs/raptor-vs-puma.md +104 -424
- data/docs/talk.md +1388 -0
- data/ext/raptor_bpf/reuseport_select.bpf.c +18 -9
- data/ext/raptor_http/extconf.rb +2 -0
- data/ext/raptor_http/raptor_http.c +165 -234
- data/ext/raptor_http2/raptor_http2.c +272 -223
- data/ext/raptor_native/raptor_native.c +38 -20
- data/lib/rackup/handler/raptor.rb +14 -12
- data/lib/raptor/binder.rb +12 -12
- data/lib/raptor/cli.rb +19 -18
- data/lib/raptor/cluster.rb +120 -74
- data/lib/raptor/control_server.rb +5 -2
- data/lib/raptor/detached_body.rb +6 -2
- data/lib/raptor/http.rb +7 -6
- data/lib/raptor/http1.rb +281 -234
- data/lib/raptor/http2.rb +356 -276
- data/lib/raptor/plugin.rb +98 -0
- data/lib/raptor/reactor.rb +138 -148
- data/lib/raptor/reuseport_bpf.rb +62 -38
- data/lib/raptor/server.rb +45 -34
- data/lib/raptor/stats.rb +15 -3
- data/lib/raptor/thread_locals.rb +4 -3
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/rackup/handler/raptor.rbs +2 -1
- data/sig/generated/raptor/binder.rbs +9 -9
- data/sig/generated/raptor/cli.rbs +6 -6
- data/sig/generated/raptor/cluster.rbs +18 -5
- data/sig/generated/raptor/control_server.rbs +2 -1
- data/sig/generated/raptor/detached_body.rbs +5 -1
- data/sig/generated/raptor/http.rbs +3 -5
- data/sig/generated/raptor/http1.rbs +119 -102
- data/sig/generated/raptor/http2.rbs +204 -190
- data/sig/generated/raptor/plugin.rbs +52 -0
- data/sig/generated/raptor/reactor.rbs +107 -118
- data/sig/generated/raptor/reuseport_bpf.rbs +54 -17
- data/sig/generated/raptor/server.rbs +26 -26
- data/sig/generated/raptor/stats.rbs +3 -2
- data/sig/generated/raptor/thread_locals.rbs +4 -3
- metadata +6 -2
- 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
|
|
10
|
-
# the BPF
|
|
11
|
-
#
|
|
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
|
|
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
|
-
#
|
|
38
|
-
#
|
|
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 (
|
|
46
|
-
def self.create_worker_listeners: (
|
|
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
|
|
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
|
|
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
|
-
#
|
|
76
|
-
#
|
|
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
|
|
5
|
-
# dispatches them into the request pipeline.
|
|
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
|
-
@
|
|
35
|
+
@worker_index: Integer?
|
|
40
36
|
|
|
41
37
|
@running: AtomicBoolean
|
|
42
38
|
|
|
43
|
-
|
|
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
|
|
48
|
+
# @param http2 [Http2] the HTTP/2 handler
|
|
50
49
|
# @param connection_options [Hash] per-connection timeout configuration, used to bound TLS handshakes
|
|
51
|
-
# @
|
|
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]
|
|
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 (
|
|
57
|
-
def initialize: (
|
|
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
|
|
86
|
-
#
|
|
85
|
+
# Starts a background thread that publishes this worker's load to the
|
|
86
|
+
# BPF map for load-aware dispatch.
|
|
87
87
|
#
|
|
88
|
-
# @return [
|
|
88
|
+
# @return [Thread] the load reporter
|
|
89
89
|
#
|
|
90
|
-
# @rbs () ->
|
|
91
|
-
def spawn_load_reporter: () ->
|
|
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/
|
|
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
|
|
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
|
-
#
|
|
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
|
|
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
|
-
# @
|
|
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
|
|
19
|
-
#
|
|
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.
|
|
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/
|
|
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
|