ngx_api_gateway
is a dynamically configurable solution for routing requests.
- Dynamically add and remove upstreams.
- Dynamically modify routes between URLs and backends.
- Synchronization with external registry.
- Templating.
- Environment may be used in configuration inventory.
- Internal configuration persistent storage.
- ngx_template_module.
- ngx_dynamic_upstream.
- ngx_dynamic_healthcheck 2.X.X branch.
- ngx_http_upsync_upstream.
SQLite for persistance.
Development.
You may dynamically add and remove upstreams to nginx in runtime without reloads.
This feature is very important because reloads of nginx needs to close all active connections and create another ones. Websockets and tcp streams may prevent fast reloads.
As you know, locations in nginx is a configuration time feature and routing can't be changed in runtime dynamically.
With dynamic routes you may add and remove routes based on prefix tree and regular expression patterns.
You may associate URLs to upstream in runtime without chaning nginx cnfiguration with REST without reloads.
Configurations is stored to internal sqlite database and on reload is loaded to nginx configuration.
Routes and upstreams configuration may be fetched from external http server and applied. Some of changes may needs to reload nginx.
For detailed templating possibilities you may look ngx_template_module.
env.template:
env {{name}};
env.yml:
---
env:
- name: LISTEN_PORT
dynamic.template:
server {
listen {{listen}} reuseport;
default_type text/plain;
location / {
auth_request {{auth.request}};
api_gateway_router_dynamic {{dynamic_var}}:5m;
proxy_connect_timeout {{proxy.connect_timeout}};
proxy_read_timeout {{proxy.read_timeout}};
if ({{dynamic_var}} = '') {
return 404 'No route';
}
proxy_pass {{proxy.protocol}}://{{dynamic_var}};
}
location = /auth_stub {
internal;
return 200;
}
}
dynamic.yml:
---
dynamic:
- name: dynamic_entrypoint1
listen: "{{env(LISTEN_PORT1)|default(9000)}}"
dynamic_var: $dynamic1
auth:
request: /auth_stub
proxy:
connect_timeout: 10s
read_timeout: 60s
protocol: http
- name: dynamic_entrypoint2
listen: "{{env(LISTEN_PORT2)|default(9001)}}"
dynamic_var: $dynamic2
auth:
request: /auth_stub
proxy:
connect_timeout: 10s
read_timeout: 60s
protocol: http
check.temlate:
healthcheck passive type=http rise={{rise}} fall={{fall}} timeout={{timeout}} interval={{interval}};
healthcheck_request_uri {{request.method}} {{request.uri}};
healthcheck_response_codes {{response.codes}};
healthcheck_response_body {{response.match}};
check.yml:
---
check:
- name: http
rise: 1
fall: 2
timeout: 10000
interval: 10
request:
method: GET
uri: /healthz
response:
codes: 200 204
match: .*
nginx.conf:
template keyfile=env.yml template=env.template;
http {
upstream_conf_zone 8m;
template keyfile=check.yml template=check.template;
api_gateway_template keyfile=dynamic.yml template=dynamic.template;
server {
listen 8888;
location = /healthcheck/get {
healthcheck_get;
}
location = /healthcheck/status {
healthcheck_status;
}
location = /route {
api_gateway_route;
}
location = /dynamic {
dynamic_upstream;
}
location = /upstream {
upstream_conf;
}
}
}
For more examples look into example
folder.
Syntax | upstream_conf_zone |
---|---|
Default | 8m |
Context | http |
Syntax | upstream_conf |
---|---|
Default | - |
Context | location |
Method: POST
Arguments:
- method - roundrobin, leastconn, ip_hash.
- stream - add stream upstream.
- keepalive - number of keepalived connections.
- keepalive_requests - number of keepalived requests.
- keepalive_timeout - timeout for keepalived connection.
- dns_update - background synchronization hosts addresses by DNS in seconds. Looking for details in ngx_dynamic_upstream.
Example: curl -X POST 'localhost:6000/upstream?name=test&keepalive=600&keepalive_requests=10'
.
Method: DELETE
Example: curl -X DELETE 'localhost:6000/upstream?name=test'
.
Method: GET
Example: curl localhost:6000/upstream
.
Output:
[
{
"keepalive": 600,
"keepalive_requests": 10,
"method": "roundrobin",
"name": "test1",
"type": "http"
},
{
"keepalive": 600,
"keepalive_requests": 10,
"method": "roundrobin",
"name": "test2",
"type": "http"
}
]
Dynamic routes is implemented via api_gateway_router_dynamic
directive.
Syntax | api_gateway_router_dynamic <variable>:<mem> |
---|---|
Default | - |
Context | http,location |
Example:
location / {
api_gateway_router_dynamic $backend:5m;
proxy_pass http://$backend;
Routes associated with nginx variable, declared with api_gateway_router_dynamic
directive.
Syntax | route_conf |
---|---|
Default | - |
Context | location |
Register location handler for setup new route, delete existing.
Method: POST
Arguments:
- backend - upstream name.
- api - route. May be uri mask (/a/b/*/c/d) or regular expression.
- var - variable name.
Example: curl -X POST localhost:8888/route?backend=app1&api=/a/b/*/c&var=$backend
.
Method: DELETE
Arguments:
- api - route. May be uri mask (/a/b/*/c/d) or regular expression.
- var - variable name.
Example: curl -X DELETE localhost:8888/route?api=/a/b/*/c&var=$backend
.
Static routes is implemented via api_gateway_router
directive.
It injects backend's configuration into server or location.
Syntax | api_gateway_router <variable>:<mem> <backends> |
---|---|
Default | - |
Context | server,location |
Example:
check.yml:
---
check:
- name: http
rise: 1
fall: 2
timeout: 10000
interval: 10
request:
method: GET
uri: /healthz
response:
codes: 200 204
match: .*
backend.template:
upstream {{__group}}@{{name}} {
zone shm_{{name}} 256k;
dns_update {{dns.update}};
dns_add_down on;
{{servers}}
check passive type=http rise={{[email protected]}} fall={{[email protected]}} timeout={{[email protected]}} interval={{[email protected]}};
check_request_uri {{[email protected]}} {{[email protected]}};
check_response_codes {{[email protected]}};
check_response_body {{check.response.match}};
}
backends.yml:
---
backends:
- name: backend1
api:
- /app1/fun1
- ~ ^/app3/fun2
- /app1/fun3
- /app1/*/hello/*
- /app1/0000000
dns:
update: 60s
server:
max_conns: 10
max_fails: 2
fail_timeout: 30s
upsync:
interval: 60s
timeout: 10s
check:
response:
match: pong
servers:
- server 127.0.0.1:3333 max_conns={{server.max_conns}} max_fails={{server.max_fails}} fail_timeout={{server.fail_timeout}};
- server 127.0.0.1:4444 max_conns={{server.max_conns}} max_fails={{server.max_fails}} fail_timeout={{server.fail_timeout}};
- name: backend2
api:
- /app2/fun1
- ~ ^/app2/fun2
- /app2/fun3
- /app2/*/hello/*
- /app2/0000000
dns:
update: 60s
server:
max_conns: 10
max_fails: 2
fail_timeout: 30s
upsync:
interval: 60s
timeout: 10s
check:
response:
match: pong
servers:
- server 127.0.0.1:5555 max_conns={{server.max_conns}} max_fails={{server.max_fails}} fail_timeout={{server.fail_timeout}};
- server 127.0.0.1:6666 max_conns={{server.max_conns}} max_fails={{server.max_fails}} fail_timeout={{server.fail_timeout}};
entrypoint.template:
server {
listen {{listen}} reuseport;
default_type text/plain;
{{server.directives|default()}}
{{server.locations|default()}}
location / {
auth_request {{auth.request}};
{{location.directives|default()}}
api_gateway_router $backend:1m {{backends}};
proxy_connect_timeout {{proxy.connect_timeout}};
proxy_read_timeout {{proxy.read_timeout}};
proxy_pass {{proxy.protocol}}://$backend;
}
location = /auth_stub {
internal;
return 200;
}
}
entrypoints.yml:
---
entrypoints:
- name: app
listen: 11111
server:
directives:
- set $variable1 1;
- set $variable2 2;
locations:
- location ~* ^/app1/.+\.(jpg|gif|png)$ { proxy_pass http://backends@backend1; }
- location ~* ^/app2/.+\.(jpg|gif|png)$ { proxy_pass http://backends@backend2; }
location:
directives:
- set $variable3 3;
- set $variable4 4;
auth:
request: /auth_stub
proxy:
connect_timeout: 100s
read_timeout: 600s
protocol: http
backends:
- backends@backend1
- backends@backend2
nginx:
http {
template keyfile=check.yml;
api_gateway_template keyfile=backends.yml template=backend.template;
api_gateway_template keyfile=entrypoints.yml template=entrypoint.template;
}
Syntax | api_gateway_template keyfile=keys.yml template=template_file url=host:port/url |
---|---|
Context | http |
Synchronization inventory with external registry.
Example: api_gateway_template keyfile=backends.yml template=backend.template url=127.0.0.1:7777/registry/backends;
See example for details.
Syntax | api_gateway_timeout <timeout> |
---|---|
Context | http |
Syntax | api_gateway_interval <interval> |
---|---|
Context | http |