Skip to main content

Service

Services hold the upstream and plugins that several routes share.

In the console ServicesEngine resource service

What a service is​

A service holds what several routes have in common: the instances their requests go to, as nodes of its own or a shared upstream, and the plugins every one of them runs. A route that chooses Service under Target sends its requests to the service's instances and runs the service's plugins beside its own.

Where a route carries the same plugin as its service, the route's own copy is used on that route. How G8 handles a request shows where the service sits between the route and your backend.

When to use it​

  • Several routes reach the same backend instances, for example orders-api and orders-v1 for the orders backend, and you want to list the instances once.
  • Every route of one backend needs the same plugins, for example one request limit, and you want to add them in one place.
  • A client's requests should be counted over several routes together, not on each route apart.
  • Every route of one backend should answer only the host names the backend serves.

Not for plugins that run on every request of the environment, whatever the route — see Global rule (Global rules run their plugins on every request the engine handles) or plugins that routes share while each keeps instances of its own — see Plugin config (Plugin configs hold a set of plugins that several routes reference).

Guides​

Pages that walk through a job with a service, step by step.

Set it up​

Give the routes of the orders backend its two instances and one request limit​

orders-api and orders-v1 choose Service under Target and pick orders: their requests go to its two nodes, and its request limit counts each client address once over both routes.

Under General set Name to orders and set Description to The orders backend, for every route that reaches it. Under Target choose Nodes on this service and fill Upstream as in the JSON below. Once it is created, open its Plugins tab and add limit-count with its settings from the JSON below.

service · as the console saves it
{
"name": "orders",
"desc": "The orders backend, for every route that reaches it",
"upstream": {
"type": "roundrobin",
"nodes": {
"10.0.1.10:8080": 1,
"10.0.1.11:8080": 1
}
},
"plugins": {
"limit-count": {
"count": 100,
"time_window": 60,
"key": "remote_addr",
"rejected_code": 429
}
}
}

What you will see​

  • Repeated requests to orders-api are all answered 200, and the two backend nodes share them, as each node's own log shows, and each answer carries X-RateLimit-Limit: 100 from the service's limit-count, though the route carries no limit of its own.
  • The same client on orders-v1 is counted in the same 100: after four requests to orders-api, its first request to orders-v1 is answered with X-RateLimit-Remaining: 95.
  • Where orders-v1 carries a limit-count of its own, with a Count of 20, its answers carry X-RateLimit-Limit: 20: the route's copy is used instead of the service's.
  • Its requests are then counted apart from the service's: requests to orders-v1 do not lower the X-RateLimit-Remaining that orders-api answers with.

More scenarios​

Group the routes of a service whose instances DNS answers

DNS discovery must be enabled in the gateway's static configuration first; without it every request is refused with 503.

Under General set Name to orders-discovered. Under Target choose Nodes on this service and fill Upstream as in the JSON below.

service · as the console saves it
{
"name": "orders-discovered",
"upstream": {
"type": "roundrobin",
"discovery_type": "dns",
"service_name": "orders.internal.example.com:8080"
}
}
Group routes on a backend that expects its own host name

With verification on, the certificate of the node must be valid for orders.example.com, the name the request now carries.

Under General set Name to orders-public. Under Target choose Nodes on this service and fill Upstream as in the JSON below.

service · as the console saves it
{
"name": "orders-public",
"upstream": {
"type": "roundrobin",
"scheme": "https",
"nodes": {
"10.0.1.20:443": 1
},
"pass_host": "rewrite",
"upstream_host": "orders.example.com",
"tls": {
"verify": true
}
}
}
Group the checkout routes with session affinity

Requests that carry the same session_id cookie reach the same instance; one without the cookie is placed by its client address instead, so that client, and every client behind the same address, always reaches the same instance.

Under General set Name to checkout. Under Target choose Nodes on this service and fill Upstream as in the JSON below.

service · as the console saves it
{
"name": "checkout",
"upstream": {
"type": "chash",
"hash_on": "cookie",
"key": "session_id",
"nodes": {
"10.0.1.10:8080": 1,
"10.0.1.11:8080": 1
}
}
}
Group routes on an upstream that ramps added instances up

An instance added to the list later starts at 10 percent of its weight of 100 and reaches the whole of it over 60 seconds; the instances present when the upstream is created take their full share from the start.

Under General set Name to orders-warmed. Under Target choose Nodes on this service and fill Upstream as in the JSON below.

service · as the console saves it
{
"name": "orders-warmed",
"upstream": {
"type": "roundrobin",
"nodes": {
"10.0.1.10:8080": 100,
"10.0.1.11:8080": 100
},
"warm_up_conf": {
"slow_start_time_seconds": 60,
"min_weight_percent": 10,
"interval": 5
}
}
}
Serve only api.example.com on every route of the orders service

A route on the service that lists no Hosts of its own takes the service's.

Under General set Name to orders. Under Matching fill Hosts as in the JSON below. Under Target choose Nodes on this service and fill Upstream as in the JSON below.

service · as the console saves it
{
"name": "orders",
"hosts": [
"api.example.com"
],
"upstream": {
"type": "roundrobin",
"nodes": {
"10.0.1.10:8080": 1,
"10.0.1.11:8080": 1
}
}
}

What you will see​

  • Requests for api.example.com are all answered 200, some by the first instance and some by the second.
  • A route on the service that lists no Hosts of its own answers no other host: a request for shop.example.com is answered 404 Route Not Found.

Things to know​

  • The engine assigns the id when the object is created; it is not the name, and it is what other objects refer to.
  • Plugins — A limit-count on the service keeps one count for each client address over every route on it: requests to orders-api and to orders-v1 draw on the same 100.
  • Plugins — Where a route carries the same plugin as its service, the route's copy is used on that route, with its own settings and its own count. A route with a limit of 20 of its own is counted by it, and its requests are not counted in the service's 100.
  • Plugins — The service's other plugins still run on such a route: a route with cors settings of its own also carries the limit the service adds.
  • Hosts — A route on the service that lists no Hosts of its own takes the service's: a request for any other host is then answered 404 Route Not Found.
  • Each gateway node keeps the count of a limit-count on its own unless its Policy points at Redis, so with two nodes a client can get up to 100 on each.
  • A service that routes still use cannot be deleted: g8 refuses the delete while they still use it. Move each route to another target first.
  • AdvicePut every route of one backend on its service rather than leaving some with nodes of their own, so that the instances and the shared plugins are changed in one place.

Settings​

The fields as the console shows them, section by section. A field under “When … is …” is there only while that value is set. A field that holds the settings of another kind links to that kind’s page.

General​

NamenamestringRequired
1 to 256 characters
Descriptiondescstring
up to 256 characters
Labelslabelsobject

Key and value pairs of your own, for grouping and filtering. They change nothing about traffic. An object whose keys are any name, each with a string as its value.

Matching​

Routes that use this service inherit these rules.

Hostshostsarray of strings

Leave empty to match any host. A leading * matches subdomains, for example *.example.com.

at least 1 item

Target​

Where requests to routes of this service are sent.

Choose one:

  • UpstreamSend matching requests to a shared upstream.
  • Nodes on this serviceDefine the backend here; nothing is shared.
  • NoneNo backend is chosen; the service serves its plugins alone.

Upstream​

Upstreamupstream_idstring or integer
string 1 to 64 characters or integer at least 1 · letters, digits, dots, hyphens and underscores
pattern^[a-zA-Z0-9-_.]+$

Nodes on this service​

Upstreamupstreamobject

Has the settings of an upstream, kept here and shared with nothing; each field is described on that page.

Websocketenable_websocketboolean

Lets a matching request upgrade the connection to WebSocket.

Plugins​

Plugins on this service are managed in the Plugins tab once the service exists.

Pluginspluginsobject

The plugins of this service, keyed by plugin name. The engine runs them by their priority, not by the order they are written in.

G8 dev · Apache APISIX® 3.19.0
Apache, Apache APISIX and APISIX are trademarks of The Apache Software Foundation.