ff13518961
## Background When making a blocking query on a missing service (was never registered, or is not registered anymore) the query returns as soon as any service is updated. On clusters with frequent updates (5~10 updates/s in our DCs) these queries virtually do not block, and clients with no protections againt this waste ressources on the agent and server side. Clients that do protect against this get updates later than they should because of the backoff time they implement between requests. ## Implementation While reducing the number of unnecessary updates we still want : * Clients to be notified as soon as when the last instance of a service disapears. * Clients to be notified whenever there's there is an update for the service. * Clients to be notified as soon as the first instance of the requested service is added. To reduce the number of unnecessary updates we need to block when a request to a missing service is made. However in the following case : 1. Client `client1` makes a query for service `foo`, gets back a node and X-Consul-Index 42 2. `foo` is unregistered 3. `client1` makes a query for `foo` with `index=42` -> `foo` does not exist, the query blocks and `client1` is not notified of the change on `foo` We could store the last raft index when each service was last alive to know wether we should block on the incoming query or not, but that list could grow indefinetly. We instead store the last raft index when a service was unregistered and use it when a query targets a service that does not exist. When a service `srv` is unregistered this "missing service index" is always greater than any X-Consul-Index held by the clients while `srv` was up, allowing us to immediatly notify them. 1. Client `client1` makes a query for service `foo`, gets back a node and `X-Consul-Index: 42` 2. `foo` is unregistered, we set the "missing service index" to 43 3. `client1` makes a blocking query for `foo` with `index=42` -> `foo` does not exist, we check against the "missing service index" and return immediatly with `X-Consul-Index: 43` 4. `client1` makes a blocking query for `foo` with `index=43` -> we block 5. Other changes happen in the cluster, but foo still doesn't exist and "missing service index" hasn't changed, the query is still blocked 6. `foo` is registered again on index 62 -> `foo` exists and its index is greater than 43, we unblock the query |
||
---|---|---|
.. | ||
ae | ||
cache | ||
cache-types | ||
checks | ||
config | ||
connect | ||
consul | ||
debug | ||
exec | ||
local | ||
metadata | ||
mock | ||
pool | ||
proxycfg | ||
proxyprocess | ||
router | ||
structs | ||
systemd | ||
token | ||
xds | ||
acl.go | ||
acl_endpoint.go | ||
acl_endpoint_legacy.go | ||
acl_endpoint_legacy_test.go | ||
acl_endpoint_test.go | ||
acl_test.go | ||
agent.go | ||
agent_endpoint.go | ||
agent_endpoint_test.go | ||
agent_test.go | ||
bindata_assetfs.go | ||
blacklist.go | ||
blacklist_test.go | ||
catalog_endpoint.go | ||
catalog_endpoint_test.go | ||
check.go | ||
config.go | ||
connect_auth.go | ||
connect_ca_endpoint.go | ||
connect_ca_endpoint_test.go | ||
coordinate_endpoint.go | ||
coordinate_endpoint_test.go | ||
dns.go | ||
dns_test.go | ||
enterprise_delegate_oss.go | ||
event_endpoint.go | ||
event_endpoint_test.go | ||
health_endpoint.go | ||
health_endpoint_test.go | ||
http.go | ||
http_oss.go | ||
http_oss_test.go | ||
http_test.go | ||
intentions_endpoint.go | ||
intentions_endpoint_test.go | ||
keyring.go | ||
keyring_test.go | ||
kvs_endpoint.go | ||
kvs_endpoint_test.go | ||
notify.go | ||
notify_test.go | ||
operator_endpoint.go | ||
operator_endpoint_test.go | ||
prepared_query_endpoint.go | ||
prepared_query_endpoint_test.go | ||
remote_exec.go | ||
remote_exec_test.go | ||
retry_join.go | ||
retry_join_test.go | ||
session_endpoint.go | ||
session_endpoint_test.go | ||
sidecar_service.go | ||
sidecar_service_test.go | ||
signal_unix.go | ||
signal_windows.go | ||
snapshot_endpoint.go | ||
snapshot_endpoint_test.go | ||
status_endpoint.go | ||
status_endpoint_test.go | ||
testagent.go | ||
testagent_test.go | ||
translate_addr.go | ||
txn_endpoint.go | ||
txn_endpoint_test.go | ||
ui_endpoint.go | ||
ui_endpoint_test.go | ||
user_event.go | ||
user_event_test.go | ||
util.go | ||
util_test.go | ||
watch_handler.go | ||
watch_handler_test.go |