Edge
The fleet layer for a Multisite: several servers (edges) share one set of instances, any edge accepts any request, and a request for an instance another edge runs is forwarded there over the private network. Works with either runtime provider, pocker or docker.
Install · Configure · Use · Integrations · Example
Install
Edge is built into pocketone. It turns on in host mode (a provider in pocketone.yaml) when the file has an
edges section, or a mothership section (Mothership), which lists the edges too.
In your own Go build, give the host a router as its forward hook:
edges, err := edge.FromSection(log) // the `edges` section; nil when there is none
if edges != nil {
opts.Forward = edge.NewRouter(edge.RouterConfig{Edges: edges, Logger: log}).Forward
}
h, err := multisite.FromConfig(opts)
The module is github.com/pockethost/pocketone/ext/multisite-edge.
Configure
The edges section names this edge and lists the others (keys below):
edges:
self: lax-1
list:
- { id: sgp-1, internal_url: "http://10.88.0.4:8080", region: sgp }
server:
plain: [":8080"] # where the other edges reach this one (their internal_url for it)
Each entry needs id and internal_url. An instance another edge runs names its owner in remote:
instances:
- id: shop
hosts: [shop.example.com]
remote: edge:@sgp-1 # also accepted: edge:sgp-1, or sgp-1
Without a mothership, instances come from the instances file. With one, instances and edges both come from it; a
fixed edges.list entry wins over the mothership's for the same edge.
pocketone.yaml reference
edges:
The fleet: this edge's id and a fixed list of the other edges (id, internal_url, region).
| Key | Type | Default | Description |
|---|---|---|---|
self |
string | This edge's id, such as lax-1. | |
list |
list of object | The other edges: id, internal_url (where this edge reaches it) and optional region. |
Use
There's nothing to run by hand. A load balancer sends visitors to any edge, and each request ends up on the edge that runs its instance:
- Owner healthy: the request is forwarded to its
internal_url, with the original hostname. An edge is healthy when its source heard from it in the last 30 seconds, or else when it answers/_pocker/health(an edge the source marks offline never is). - Owner briefly unreachable but healthy: requests are held and retried every 250 ms until it answers. Only requests without a body (GET, HEAD, OPTIONS) are replayed after a failed connection.
- Owner down or unknown: a 503 with
Retry-After: 10, at once. - Never bounced: a request another edge already forwarded is never forwarded again; it gets a 421.
- CORS: for an instance with
access.cors_origins, the entry edge answers preflights and sets the onlyAccess-Control-Allow-Originthe browser sees. - Headers: where both edges set the same header (such as the firewall's rate-limit headers), the owner's wins.
Integrations
Works with
| Extension | How they fit |
|---|---|
| Multisite | Edge fills the host's forward hook for instances with remote set. |
| Pocker, Docker | Either runs the instances this edge owns; an app already running here stops when its instance moves to another edge. |
| Firewall | The entry edge checks the peer and the instance's rate limits before forwarding. |
| Mothership | Its mirror is an edge source: it follows the mothership's list of edges and their heartbeats. |
Building on Edge
- Edge sources. Implement
edge.EdgeSource(Self,Resolve,Edges) to say where the other edges are; addRun(edge.Runner) for background work.YAMLProvideris theedges.listone;MultiProvidercombines several, the first to resolve an instance'sremotewinning. - Router.
edge.NewRouter(edge.RouterConfig{...})takes the health path, healthy window, retry interval and the 503 and 421 messages. PlugRouter.Forwardintomultisite.Host.Forward. - Timing.
edge.WithMark(ctx)records which edge a request was forwarded to and when, e.g. for Server-Timing.
Example
Edge has no example program of its own. The stock binary wires it up in
examples/pocketone/multi.go, together with the mothership's edge list.
License
MIT
Questions and comments
Comments are a GitHub Discussions thread; sign in with GitHub to post.