Gateway Routing¶
The Gateway reaches its Centers through routes defined in a routes file, which it monitors and reloads without a restart. This page covers the file format, its validation, the reload behavior, and the console commands that manage routes on a running Gateway.
Overview¶
Each route names a target Center and its address. The Gateway reads the routes file at startup and whenever it changes on disk, and it connects to every route it holds. A subscription is sent to every route, and a query to every route whose Center holds all the tables the query names. The results are merged, so the routes collectively define the data the Gateway exposes. Route targets are Centers.
File location¶
Set by ami.gateway.routes.file, which defaults to data/gateway.routes.
If the file does not exist when the Gateway starts, it is created containing a header comment and one example route to the local Center:
Format¶
One route per line. Blank lines are ignored, as are lines beginning with #. Each route is 3 fields
separated by semicolons:
| Field | Required | Description |
|---|---|---|
id |
Yes | Identifier for the route. Must not be empty, and must be unique within the file |
host:port |
Yes | Address of the target Center. The port must be between 1 and 65535 |
certificateFile |
Yes, may be empty | Certificate for connecting to the target. The path must be inside the installation root. Keeping it in the Gateway component's own directory is a convention, not a requirement |
All 3 fields must be present. A line with a number of fields other than 3 is rejected with
Expecting 3 parts (id;host:port;certificateFile) not <n>.
A certificate path outside the installation root is refused:
Copy the target Center's public key somewhere under the installation root, for example the
Gateway's own keys/, and reference it from there.
A failed addRoute leaves the routes file unusable
addRoute is not atomic. A call that returns an error still writes its line to the routes
file, and a later call may report the earlier call's error text rather than describing its own
input. The file is then refused on every reload, the existing routes stop serving, and queries
return GATEWAY: Route no longer available.
After any failed addRoute, open the routes file and remove the bad line by hand, then
confirm the routes reconnect. Do not assume a rejected call changed nothing.
This does not apply to editing the file directly: a malformed hand-edit is refused on re-read and the previously loaded routes keep running.
The certificate field may be left empty when no certificate is supplied, but the trailing semicolon is still required. An empty certificate field falls back to the instance's configured Center public key:
2 routes sharing an id are rejected with Duplicate gateway route id: <id>, so an accidental
duplicate is caught rather than silently overriding.
Inspect the routes from a client¶
A client connected to the JDBC listener can list the routes with SHOW GATEWAY. The Gateway
answers this itself rather than forwarding it to a route:
Connected reports whether the Gateway currently holds a connection to that route's Center, so
this is the quickest way to tell a misconfigured route from an unreachable one without admin
console access.
Route ids are visible to clients¶
A route id is not only an internal label. On a metadata statement the Gateway adds a first column
named GatewayCenterId, holding the id of the route each row came from, so a client sees the ids
chosen in the routes file:
The column is added to SHOW and DESCRIBE TABLE results, for example DESCRIBE TABLE Trades. DESCRIBE alone is a syntax error. A plain SELECT does not carry it, because
rows from the routes that answer are combined into one result set. Choose route ids that mean something to the
people querying through the Gateway, rather than treating them as internal names.
Reload behavior¶
The Gateway checks the file on the interval set by ami.gateway.check.config.file.changes.period.ms, 2 seconds by default, and
re-reads it when it has changed. Reloading is selective: each route is compared against the version
already running, and only the differences are acted on. Unchanged routes keep serving, changed and
removed routes are shut down, and new routes are started.
A malformed edit does not take the Gateway down. The parse error is logged, e.g:
Ignoring changes to <file> due to parsing error: Error at line 3 ... Expecting 3 parts, and the
previously loaded routes keep running, so the running configuration is never replaced by a broken one.
Check the log after editing to confirm the change was accepted, because a rejected edit leaves the
Gateway serving the old configuration with no other outward sign.
Removing a route on a running Gateway
On the build tested, removing a route with removeRoute left the remaining routes failing with
GATEWAY: Route no longer available until the Gateway was reloaded, even though the routes file
and showRoutes looked correct. Until this is confirmed fixed, reload the Gateway component
after removing a route with ami.reloadComponent("<name>").
Use reloadComponent, not shutdownComponent, startupComponent or restartComponent. Those
3 do not work on a Gateway, see Stopping and starting a Gateway.
Managing routes from the console¶
The Gateway exposes console commands to inspect and change routes on a running instance.
Connect to the instance's admin console over SSH. The console port is printed in the startup log and
defaults to 3285; sign in as an administrator:
At the prompt, invoke a command as a method on the Gateway component, named ami_<component-name>
after the name in data/ami.components (a Gateway named gateway is ami_gateway):
| Command | Parameters | Effect |
|---|---|---|
showRoutes |
None | Show all configured routes with their id, host, port, certificate file, and connection status |
showRouteSubscriptions |
None | Show each route's upstream subscriptions with type, row count, filters, and columns |
showClientSubscriptions |
None | Show each Gateway client subscription with type, in-focus row count, filters, and columns |
showClients |
None | Show all connected Gateway clients with their id, host, and subscription types |
addRoute |
name, hostport, pubkeyfile |
Add a route to the routes file and connect it immediately |
removeRoute |
name |
Remove a route from the routes file and disconnect it immediately |
addRoute and removeRoute change live connections
addRoute and removeRoute write the routes file and change live connections immediately. Adding
a route connects it at once. Removing a route disconnects it at once, but on the build tested it
also leaves the surviving routes unusable until the Gateway is reloaded (see Removing a route on
a running Gateway above): reload the component after a removeRoute.
Stopping and starting a Gateway¶
Use ami.reloadComponent("<name>") to apply configuration changes to a running Gateway. It
re-reads the component's property files and restores its listeners.
Do not shut down or restart a Gateway component
ami.shutdownComponent(), ami.startupComponent() and ami.restartComponent() do not work on
a Gateway, although they work on every other component type.
shutdownComponent reports Component shutdown: <name> and does stop the listeners, so the
Gateway genuinely stops serving. It continues to report RUNNING in ami.showComponents(), and
because of that startupComponent then refuses with Component is already running: <name>.
restartComponent performs a shutdown followed by a start, so it fails the same way and leaves
the Gateway stopped.
The state is recoverable without restarting AmiCore. ami.reloadComponent("<name>") brings the
listeners back, and removing and re-adding the component also works.
The risk is that ami.showComponents() reports a stopped Gateway as RUNNING, so an operator
watching component status does not see that clients have lost the Gateway.
Distribution model¶
A query is sent to every route whose Center holds all the tables in its FROM clause, and the
responses are merged: plain results are combined, and aggregate (GROUP BY) results are
re-aggregated across those routes. A route without one of the tables is skipped. If no route holds
them all, the query fails with GATEWAY: Table not found: <table>, or
GATEWAY: Set of tables not found: <table> + <table> for several.
See the distribution model on the overview page.
What this does not support¶
- Route targets are Centers only, not other component types.
- A query cannot name the route it runs on. The routes are chosen from the tables it names.