NAME

Feersum::Runner - feersum script core

SYNOPSIS

use Feersum::Runner;
my $runner = Feersum::Runner->new(
    listen => 'localhost:5000',
    pre_fork => 0,
    quiet => 1,
    app_file => 'app.feersum',
);
$runner->run($feersum_app);

DESCRIPTION

Process manager for Feersum. Handles listen sockets, pre-forking, hot restart, TLS, daemonization, and graceful shutdown.

METHODS

Feersum::Runner->new(%params)

Returns a Feersum::Runner singleton. If called again while not running, the previous instance is replaced with a new one using the provided params.

listen

Listen address as an arrayref of one or more address strings, e.g. listen => ['localhost:5000'], or a plain string for a single address. Formats: host:port for IPv4, [host]:port for IPv6 (needs Perl 5.14+ with Socket IPv6 support). A bare (unbracketed) IPv6 address whose tail looks like a port is rejected as ambiguous.

An entry beginning with / or . is bound as a UNIX-domain socket, created world-accessible (mode 0777); restrict access through the directory's permissions.

Alternatively, use host and port.

pre_fork

Fork this many worker processes. The app is loaded once in the parent and inherited copy-on-write unless preload_app => 0.

preload_app

Whether the app is loaded before forking workers (default: true). When true, workers inherit the loaded app copy-on-write; use after_fork to reconnect per-process resources. When false, each worker loads app_file itself after the fork (requires app_file). Ignored under hot_restart, where each generation loads the app once and forks copy-on-write.

hot_restart

Generation-based hot restart. Requires app_file. The entry process becomes a supervisor; on SIGHUP it forks a new generation that re-runs the app file from scratch and, once that generation is ready, retires the old one via SIGQUIT. A generation that fails to start is discarded and the old one keeps serving.

Works with pre_fork (each generation forks its own workers) and with tls/h2. Modules already loaded before run() are inherited via fork and not reloaded; restart the supervisor to refresh those.

Under plackup the .psgi path must also be given to plackup itself; app_file only names what each generation re-runs:

plackup -s Feersum --app-file=app.psgi --hot-restart=1 --pre-fork=4 app.psgi
kill -HUP <master-pid>
backlog

Listen socket backlog (default: SOMAXCONN). Raise it if the kernel's somaxconn is tuned above the compile-time constant; the kernel clamps to its own maximum.

keepalive

Enable/disable http keepalive requests.

reverse_proxy

Trust X-Forwarded-For and X-Forwarded-Proto from an upstream proxy: REMOTE_ADDR becomes the first forwarded IP and psgi.url_scheme follows X-Forwarded-Proto. The native $req->client_address and $req->url_scheme honour this too. Only enable behind a trusted proxy.

proxy_protocol

Expect a PROXY protocol header (v1 or v2, auto-detected) at the start of every connection and take REMOTE_ADDR/REMOTE_PORT from it; v1 UNKNOWN, v2 LOCAL and non-INET families keep the socket address. Independent of reverse_proxy, which is applied on top. Only enable when every connection comes through such a proxy: a connection without a valid header is rejected with HTTP 400. HAProxy example:

backend feersum_backend
    mode http
    server feersum 127.0.0.1:5000 send-proxy-v2
psgix_io

Enable the psgix.io PSGI extension (default: enabled). Disable it to skip the per-request overhead if the app never needs the raw socket.

read_timeout

Read/keepalive timeout in seconds (default: 5). Must be positive.

header_timeout

Seconds allowed to receive complete request headers (default: 10; 0 disables).

write_timeout

Seconds allowed for a stalled response write before the connection is closed (default: 0, disabled).

max_connection_reqs

Set max requests per connection in case of keepalive - 0(default) for unlimited.

max_accept_per_loop

Connections accepted per event loop cycle (default: 64). Lower values spread load more evenly across prefork workers sharing a listen socket.

max_connections

Maximum concurrent connections (default: 10000; 0 disables). At the limit the oldest idle keep-alive connection is closed to make room; if none is idle, the new connection is closed and accepting pauses on that listener until a slot frees.

max_read_buf

Maximum read buffer per connection (default: 64 MiB), bounding header parsing and chunked body reception.

max_body_len

Maximum request body size (default: 64 MiB), applied to Content-Length and to the cumulative chunked body.

max_uri_len

Set max request URI length (default: 8192).

wbuf_low_water

Set write buffer low-water mark in bytes (default: 0). Used with poll_cb() on streaming responses: the callback fires when the buffer drains to or below this threshold.

read_priority
write_priority
accept_priority

Set libev I/O watcher priorities for read, write, and accept operations. Valid range is -2 (lowest) to +2 (highest), default is 0.

tls

Enable TLS 1.3 on all listeners. Pass a hash reference with cert_file and key_file paths:

Feersum::Runner->new(
    listen => ['0.0.0.0:8443'],
    tls    => { cert_file => 'server.crt', key_file => 'server.key' },
    app    => $app,
)->run;

Requires Feersum built with TLS support. HTTP/2 needs h2 => 1 as well.

tls_cert_file
tls_key_file

Flat alternatives to the tls hash, useful with plackup's pass-through options:

plackup -s Feersum --tls-cert-file=server.crt --tls-key-file=server.key

Both must be specified together. If a tls hash is also provided, it takes precedence and these are ignored.

h2

Negotiate HTTP/2 via ALPN on TLS listeners (default: off). Needs TLS configured (croaks otherwise) and Alien::nghttp2 at build time.

sni

SNI virtual hosting: an arrayref of { sni => $hostname, cert_file => $path, key_file => $path } hashes, each adding a certificate for that hostname. Requires tls (the default certificate); croaks without it.

reuseport

Use SO_REUSEPORT with pre_fork (default: off): each worker binds its own socket to the same address and the kernel spreads connections across them, removing accept() contention. Needs Linux 3.9+ or equivalent.

Each worker binds for itself, which user/group on a port below 1024 makes impossible; Feersum probes the bind while dropping privileges and falls back to the shared inherited socket, with a warning.

A reuseport socket owns its accept queue, so a retiring or restarting worker would reset whatever the kernel had queued on it. Reuseport workers therefore run with set_drain_accept_queue (see Feersum) and serve that queue as part of the graceful drain. What remains is a small window of refused connects between a worker closing its listener and its replacement binding; Linux 5.14+ removes it with net.ipv4.tcp_migrate_req=1.

Not required for IPv6; see listen.

max_requests_per_worker

Requests a worker serves before retiring and being replaced (default: 0, unlimited). Effective with pre_fork or hot_restart. The limit is exact (enforced in XS; see "max_requests_per_worker()" in Feersum), retirement is not counted as a crash for respawn backoff, and graceful_timeout bounds the retiring worker's drain since the replacement is forked only once it exits.

access_log

Code reference called after each response completes (native handler only). Receives ($method, $uri, $elapsed_seconds). Requests the server rejects before dispatch (malformed, over a limit, timed out) produce no line; see access_log in Feersum. For PSGI apps, use Plack::Middleware::AccessLog instead.

access_log => sub {
    my ($method, $uri, $elapsed) = @_;
    warn sprintf "%s %s %.3fms\n", $method, $uri, $elapsed * 1000;
},
graceful_timeout

Seconds to let in-flight requests finish on shutdown or worker retirement before force-exiting (default: 5; 0 force-exits at once). The FEERSUM_GRACEFUL_TIMEOUT environment variable is used when the option is unset. A prefork parent allows 2 extra seconds so its workers exit first. Force-exit truncates whatever is still in flight, so raise it if you serve large or long-streaming responses.

startup_timeout

Seconds to wait for a hot_restart generation to report ready before rolling back (default: 10). Also caps how long a daemonize parent waits for the daemon's readiness report; there a timeout counts as success.

after_fork

Code reference called in each worker child immediately after fork, before entering the event loop. Use this to reconnect database handles, reseed PRNGs, or close inherited file descriptors:

after_fork => sub { $dbh = DBI->connect(...) },
pid_file

Write the server PID to this file. Removed on clean shutdown.

daemonize

Fork into background, redirect STDIN/STDOUT/STDERR to /dev/null, and call setsid(). The PID file (if specified) is written with the daemon's PID.

user
group

Drop privileges after the listen sockets are bound and before the app loads, so a root start can bind privileged ports. Supplementary groups are always cleared; with group omitted the user's primary group is used. The drop is verified and croaks if it did not take effect.

The TLS certificate and key must be readable by user: a worker respawn re-reads them after the drop, so a root-only key works at startup and then empties the pool at the first respawn (silently under daemonize).

max_h2_concurrent_streams

Maximum concurrent HTTP/2 streams per connection (default: 100). Requires H2 support compiled in.

max_h2_conn_body

Aggregate cap on request-body bytes buffered across a connection's HTTP/2 streams (default: 0, off). Bounds the memory a peer can tie up with many concurrent uploads; see "max_h2_conn_body" in Feersum. Requires H2 support.

quiet

Don't be so noisy. (default: on)

app

An already-compiled native Feersum app code reference, as an alternative to passing it to run(). Mutually exclusive with a per-worker load: when app is set, app_file is not re-read in the workers.

app_file

Load this filename as a native feersum app. Required for hot_restart, which re-reads the file in each new generation. With preload_app off and no app, each worker loads it independently after the fork.

$runner->run($feersum_app)

Run Feersum with the specified app code reference. Note that this is not a PSGI app, but a native Feersum app.

$runner->assign_request_handler($subref)

For sub-classes to override, assigns an app handler. (e.g. Plack::Handler::Feersum). By default, this assigns a Feersum-native (and not PSGI) handler.

$runner->quit()

Initiate a graceful shutdown. A signal handler for SIGQUIT will call this method.

AUTHOR

Jeremy Stashewsky, stash@cpan.org

COPYRIGHT AND LICENSE

Copyright (C) 2010 by Jeremy Stashewsky & Socialtext Inc.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.14 or, at your option, any later version of Perl 5 you may have available.