prefork

package
v1.72.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2026 License: MIT Imports: 13 Imported by: 14

README

Prefork

Server prefork implementation.

Preforks master process between several child processes increases performance, because Go doesn't have to share and manage memory between cores.

WARNING: using prefork prevents the use of any global state!. Things like in-memory caches won't work.

  • How it works:
import (
    "github.com/valyala/fasthttp"
    "github.com/valyala/fasthttp/prefork"
)

server := &fasthttp.Server{
    // Your configuration
}

// Wraps the server with prefork
preforkServer := prefork.New(server)

if err := preforkServer.ListenAndServe(":8080"); err != nil {
    panic(err)
}

Benchmarks

Environment:

  • Machine: MacBook Pro 13-inch, 2017
  • OS: MacOS 10.15.3
  • Go: go1.13.6 darwin/amd64

Handler code:

func requestHandler(ctx *fasthttp.RequestCtx) {
    // Simulates some hard work
    time.Sleep(100 * time.Millisecond)
}

Test command:

$ wrk -H 'Host: localhost' -H 'Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7' -H 'Connection: keep-alive' --latency -d 15 -c 512 --timeout 8 -t 4 http://localhost:8080

Results:

  • prefork
Running 15s test @ http://localhost:8080
  4 threads and 512 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     4.75ms    4.27ms 126.24ms   97.45%
    Req/Sec    26.46k     4.16k   71.18k    88.72%
  Latency Distribution
     50%    4.55ms
     75%    4.82ms
     90%    5.46ms
     99%   15.49ms
  1581916 requests in 15.09s, 140.30MB read
  Socket errors: connect 0, read 318, write 0, timeout 0
Requests/sec: 104861.58
Transfer/sec:      9.30MB
  • non-prefork
Running 15s test @ http://localhost:8080
  4 threads and 512 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     6.42ms   11.83ms 177.19ms   96.42%
    Req/Sec    24.96k     5.83k   56.83k    82.93%
  Latency Distribution
     50%    4.53ms
     75%    4.93ms
     90%    6.94ms
     99%   74.54ms
  1472441 requests in 15.09s, 130.59MB read
  Socket errors: connect 0, read 265, write 0, timeout 0
Requests/sec:  97553.34
Transfer/sec:      8.65MB

Documentation

Overview

Package prefork provides a way to prefork a fasthttp server.

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrOverRecovery is returned when child prefork process restarts exceed
	// the value of RecoverThreshold.
	ErrOverRecovery = errors.New("exceeding the value of RecoverThreshold")

	// ErrOnlyReuseportOnWindows is returned when running on Windows without Reuseport.
	ErrOnlyReuseportOnWindows = errors.New("windows only supports Reuseport = true")

	// ErrCommandProducerNilCmd is returned when a CommandProducer returns
	// (nil, nil) instead of a started command.
	ErrCommandProducerNilCmd = errors.New("prefork: CommandProducer returned nil command")

	// ErrCommandProducerNotStarted is returned when a CommandProducer returns
	// an *exec.Cmd whose Process is nil (i.e. cmd.Start() was not called).
	ErrCommandProducerNotStarted = errors.New("prefork: CommandProducer must return a started command")
)

Functions

func IsChild

func IsChild() bool

IsChild reports whether the current process is a prefork child.

Types

type Logger

type Logger interface {
	// Printf must have the same semantics as log.Printf.
	Printf(format string, args ...any)
}

Logger is used for logging formatted messages. Its method set is intentionally identical to fasthttp.Logger so that *fasthttp.Server.Logger can be assigned directly.

type Prefork

type Prefork struct {
	// Logger receives diagnostic output. By default the standard log package
	// logger writing to stderr is used.
	Logger Logger

	// ServeFunc, ServeTLSFunc and ServeTLSEmbedFunc serve the inherited
	// listener inside each child process. New() wires them to the matching
	// *fasthttp.Server methods. When constructing a Prefork directly, set the
	// one matching the ListenAndServe* entry point you call; otherwise the
	// child panics on a nil call.
	ServeFunc         func(ln net.Listener) error
	ServeTLSFunc      func(ln net.Listener, certFile, keyFile string) error
	ServeTLSEmbedFunc func(ln net.Listener, certData, keyData []byte) error

	// Network must be "tcp", "tcp4" or "tcp6". Default is "tcp4".
	Network string

	// RecoverThreshold caps how often crashed children are respawned before
	// the master returns ErrOverRecovery. New() sets it to max(1, GOMAXPROCS/2).
	// When constructing a Prefork directly without New(), a zero value will
	// terminate the master after the very first child crash.
	RecoverThreshold int

	// RecoverInterval, when > 0, delays the respawn of a crashed child by the
	// given duration. The delay is applied per child in that child's own Wait
	// goroutine before its exit is reported, so simultaneous crashes are not
	// serialized: each child is respawned roughly RecoverInterval after it
	// exits, independently of the others. The wait is interruptible, so a
	// shutdown does not have to outlast a pending interval. Useful as
	// crash-loop backoff.
	RecoverInterval time.Duration

	// ShutdownGracePeriod is the time the master waits for children to exit
	// after sending SIGTERM before falling back to SIGKILL. Defaults to 5s
	// when zero. On Windows SIGTERM is not delivered, so this is unused there.
	ShutdownGracePeriod time.Duration

	// Reuseport selects a reuseport listener instead of fd-passing.
	// See: https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/
	// Disabled by default.
	Reuseport bool

	// OnMasterDeath, when non-nil, enables monitoring of the master process
	// in child processes. If the master process dies unexpectedly, this
	// callback is invoked. This allows custom cleanup before shutdown.
	//
	// It is recommended to set this to func() { os.Exit(1) } if no custom
	// cleanup is needed.
	//
	// Threading: invoked once from a watcher goroutine in the child. Must not
	// block the goroutine for long; must not call Prefork methods.
	OnMasterDeath func()

	// OnChildSpawn is called in the master after a new child process is
	// successfully started, both during initial spawn and during recovery.
	// It receives the PID of the newly spawned child process.
	//
	// If this callback returns an error, all already-running children are
	// killed and the prefork operation returns that error.
	//
	// Threading: invoked synchronously from the master goroutine. Must not
	// block; must not call Prefork methods.
	OnChildSpawn func(pid int) error

	// OnMasterReady is called in the master process exactly once, after all
	// initial children have been spawned and before the supervision loop runs.
	// It receives a slice of all initial child PIDs.
	//
	// If this callback returns an error, the prefork operation aborts and
	// returns that error after killing the children.
	//
	// Threading: invoked synchronously from the master goroutine. The slice
	// is only valid for the duration of the call; copy it if you need to
	// retain the PIDs after the callback returns.
	OnMasterReady func(childPIDs []int) error

	// OnChildRecover is called in the master after a crashed child has been
	// replaced. It receives the PID of the old (crashed) process and the PID
	// of its replacement. This is a notification only: unlike OnChildSpawn it
	// cannot abort recovery.
	//
	// Threading: invoked synchronously from the master goroutine, after
	// OnChildSpawn for the new child. Must not block; must not call Prefork
	// methods.
	OnChildRecover func(oldPID, newPID int)

	// CommandProducer creates and starts a child process command.
	// If nil, the default implementation re-executes the current binary
	// with FASTHTTP_PREFORK_CHILD=1 in the environment, stdout/stderr
	// inherited from the parent, and the given files as ExtraFiles.
	//
	// A custom producer must:
	//   - Set FASTHTTP_PREFORK_CHILD=1 in the child's environment
	//     (otherwise IsChild() returns false and the child won't serve)
	//   - Call cmd.Start() before returning (the returned command must be
	//     started so cmd.Process is non-nil)
	//   - Pass the provided files as cmd.ExtraFiles when Reuseport is false
	//
	// Primarily useful for testing (injecting dummy commands) or for
	// frameworks that need custom child process setup.
	CommandProducer func(files []*os.File) (*exec.Cmd, error)
	// contains filtered or unexported fields
}

Prefork implements fasthttp server prefork.

Preforks master process (with all cores) between several child processes increases performance significantly, because Go doesn't have to share and manage memory between cores.

WARNING: using prefork prevents the use of any global state! Things like in-memory caches won't work.

func New

func New(s *fasthttp.Server) *Prefork

New wraps the fasthttp server to run with preforked processes. It seeds Network and RecoverThreshold to sensible defaults; existing fields on s (Logger, Serve*) are captured.

func (*Prefork) ListenAndServe

func (p *Prefork) ListenAndServe(addr string) error

ListenAndServe serves HTTP requests from the given TCP addr.

func (*Prefork) ListenAndServeTLS

func (p *Prefork) ListenAndServeTLS(addr, certKey, certFile string) error

ListenAndServeTLS serves HTTPS requests from the given TCP addr.

Note: parameter order is (addr, certKey, certFile) — key path comes before cert path. This is preserved for backward compatibility with existing callers and differs from fasthttp.Server.ListenAndServeTLS. New code should prefer ListenAndServeTLSEmbed.

func (*Prefork) ListenAndServeTLSEmbed

func (p *Prefork) ListenAndServeTLSEmbed(addr string, certData, keyData []byte) error

ListenAndServeTLSEmbed serves HTTPS requests from the given TCP addr.

certData and keyData must contain valid TLS certificate and key data.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL