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

Much like Plack::Runner, but with far fewer options.

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 containing one or more address strings, e.g., listen => ['localhost:5000']. Formats: host:port for IPv4, [host]:port for IPv6 (e.g., ['[::1]:8080']).

Important: IPv6 addresses require reuseport AND pre_fork to be enabled, plus Perl 5.14+ with Socket IPv6 support. Without these, only IPv4 addresses are supported.

Alternatively, use host and port parameters.

pre_fork

Fork this many worker processes.

By default the app is loaded once in the parent and workers inherit it via fork (copy-on-write friendly). Set preload_app => 0 to load the app independently in each worker instead.

preload_app

Controls whether the app is loaded before or after forking workers (default: true / load before fork).

When true (default), the app and all its modules are loaded once in the parent process. Workers inherit the loaded code via fork, benefiting from OS copy-on-write memory sharing. Use after_fork to reconnect per-process resources (database handles, etc.).

When false, workers fork first and each loads the app independently. This is useful when the app has per-process initialization that cannot be deferred to after_fork, or when you want to test that module loading works in the worker environment. Requires app_file.

Feersum::Runner->new(
    pre_fork    => 4,
    preload_app => 0,
    app_file    => 'app.psgi',
    after_fork  => sub { ... },
)->run;
hot_restart

Enable generation-based hot restart. Requires app_file.

The entry process becomes a supervisor that manages "generations". Each generation is a forked child that loads the app and all modules from scratch. On SIGHUP, a new generation is forked; if it starts successfully, the old generation is gracefully shut down via SIGQUIT. Failed restarts are rolled back (old generation continues serving).

Works with pre_fork: each generation forks its own workers. All modules are reloaded cleanly (fresh %INC via fork, not in-process do).

plackup -s Feersum --app-file app.psgi -o hot_restart=1 -o pre_fork=4
kill -HUP <master-pid>   # zero-downtime restart with fresh modules
backlog

Listen socket backlog size (default: SOMAXCONN). Set to a higher value (e.g. 65535) if the kernel's somaxconn is tuned above the compile-time SOMAXCONN constant. The kernel silently clamps to its own maximum.

keepalive

Enable/disable http keepalive requests.

reverse_proxy

Enable reverse proxy mode. When enabled, Feersum trusts X-Forwarded-For and X-Forwarded-Proto headers from upstream proxies:

  • REMOTE_ADDR is set to the first IP in X-Forwarded-For (the original client)

  • psgi.url_scheme is set from X-Forwarded-Proto (http or https)

For the native interface, use $req->client_address and $req->url_scheme to get the forwarded values (these respect reverse_proxy mode automatically).

Only enable this when Feersum is behind a trusted proxy that sets these headers.

proxy_protocol

Enable PROXY protocol support (HAProxy protocol). When enabled, Feersum expects each new connection to begin with a PROXY protocol header before any HTTP data. Both v1 (text) and v2 (binary) formats are auto-detected and supported.

The PROXY protocol header provides the real client IP address when Feersum is behind a load balancer like HAProxy, AWS ELB/NLB, or nginx (with proxy_protocol).

When a valid PROXY header is received:

  • REMOTE_ADDR/REMOTE_PORT are updated to the source address from the header

  • For v1 UNKNOWN or v2 LOCAL commands, the original address is preserved

This option works independently of reverse_proxy. When both are enabled, the PROXY protocol sets the base address, which can then be overridden by X-Forwarded-For headers if reverse_proxy is also enabled.

Important: Only enable this when ALL connections come through a proxy that sends PROXY headers. Connections without valid PROXY headers will be rejected with HTTP 400.

Example HAProxy configuration:

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

Enable or disable the psgix.io PSGI extension (default: enabled). When disabled, Feersum skips creating psgix.io in the PSGI env hash, which avoids per-request overhead if your app never uses WebSocket upgrades or raw I/O.

read_timeout

Set read/keepalive timeout in seconds.

header_timeout

Set maximum time (in seconds) to receive complete HTTP headers (Slowloris protection). Default is 10 seconds. Pass 0 to disable. Connections that don't complete headers within the timeout are closed.

write_timeout

Set maximum time (in seconds) to complete writing a response. Default is 0 (disabled). When enabled, connections that stall during response writing are closed.

max_connection_reqs

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

max_accept_per_loop

Set max connections to accept per event loop cycle (default: 64). Lower values give more fair distribution across workers when using epoll_exclusive. Higher values improve throughput under heavy load by reducing syscall overhead.

max_connections

Set maximum concurrent connections (default: 10000). When the limit is reached, new connections are immediately closed. Provides protection against Slowloris-style DoS attacks.

max_read_buf

Set max read buffer size per connection (default: 64 MB). This limits how large the read buffer can grow during header parsing and chunked body reception.

max_body_len

Set max request body size (default: 64 MB). This limits Content-Length values and cumulative chunked body sizes.

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 to be compiled with TLS support (picotls submodule + Alien::OpenSSL). HTTP/2 is not enabled by default; pass h2 => 1 separately to enable it.

tls_cert_file
tls_key_file

Flat alternatives to the tls hash, useful with Plack's -o flag:

plackup -s Feersum -o tls_cert_file=server.crt -o 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

Enable HTTP/2 negotiation via ALPN on TLS listeners (default: off). Requires TLS to be enabled. When Alien::nghttp2 was available at build time and this option is set, HTTP/2 is negotiated alongside HTTP/1.1 during the TLS handshake.

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

If set without TLS enabled, a fatal error (croak) is raised.

reuseport

Enable SO_REUSEPORT for better prefork scaling (default: off). When enabled in combination with pre_fork, each worker process creates its own socket bound to the same address. The kernel then distributes incoming connections across workers, eliminating accept() contention and improving multi-core scaling. Requires Linux 3.9+ or similar kernel support.

Note: IPv6 support requires reuseport AND pre_fork to be enabled. Without these, only IPv4 addresses are supported.

epoll_exclusive

Enable EPOLLEXCLUSIVE for better prefork scaling on Linux 4.5+ (default: off). When enabled in combination with pre_fork, only one worker is woken per incoming connection, avoiding the "thundering herd" problem. Use with max_accept_per_loop to tune fairness vs throughput.

max_requests_per_worker

Maximum total requests a worker process will handle before gracefully recycling (default: 0 = unlimited). Requires pre_fork. The parent automatically forks a replacement worker. Useful for containing memory leaks in long-running applications.

access_log

Code reference called after each response completes (native handler only). Receives ($method, $uri, $elapsed_seconds). 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 wait for in-flight requests to complete during graceful shutdown before force-exiting (default: 5). Also honors the FEERSUM_GRACEFUL_TIMEOUT environment variable (option takes precedence).

startup_timeout

Seconds to wait for a hot_restart generation to signal readiness before declaring it failed and rolling back (default: 10).

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 to this user/group after creating listen sockets but before loading the application. Allows binding to privileged ports as root.

max_h2_concurrent_streams

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

quiet

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

app_file

Load this filename as a native feersum app.

$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.8.7 or, at your option, any later version of Perl 5 you may have available.