skip to content

How does a Spring Boot service register itself with HashiCorp Consul for service discovery, and what dependency/config is required?

level: juniorimportance: must knowfreq 70%

answer

  1. starter-consul-discovery on classpath
  2. agent at localhost:8500
  3. spring.application.name = service ID
  4. auto-register + DiscoveryClient
  5. config.import replaces bootstrap

basics

~10 s

Add the spring-cloud-starter-consul-discovery dependency. On startup the app auto-registers with a local Consul agent using its service name and port, so other services can look it up by name.

solid answer

~30 s

You add `spring-cloud-starter-consul-discovery` to the classpath. Spring Cloud Consul's auto-configuration then registers the application with a Consul agent (default `localhost:8500`) at startup, using `spring.application.name` as the service ID and the app's host/port. Registration is enabled by default and driven by `spring.cloud.consul.discovery.*` properties. Consul stores this in its service catalog. Other services discover it through Spring Cloud's `DiscoveryClient` abstraction, or transparently via a load-balanced `RestTemplate`/`WebClient` using the service name as the host. On shutdown the app deregisters. You point it at Consul with `spring.cloud.consul.host` and `spring.cloud.consul.port`. Consul must be reachable (usually a local agent) for registration to succeed.

code

yaml · 17 lines
yaml
# build.gradle: implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery'
spring:
  application:
    name: order-service
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true
        instance-id: ${spring.application.name}:${random.value}
        tags:
          - version=1.0
---
# Consuming another service by name:
# @LoadBalanced @Bean RestTemplate rt;
# rt.getForObject("http://payment-service/charge", ...);

go deeper

for a junior

Know: add the discovery starter, app auto-registers with an agent using its service name, others find it by name.

for a middle

Know the key properties (instance-id uniqueness, prefer-ip-address, fail-fast) and the DiscoveryClient/LoadBalancer wiring.

for a senior

Explain agent vs server, the config.import vs bootstrap change, deregistration and startup failure modes.

for a principal

Reason about registration at scale: instance-id collisions, container networking, fail-fast policy, and Consul as one option among Eureka/K8s discovery.

**What Consul is.** HashiCorp Consul is a service mesh / service-discovery tool. It maintains a *catalog* of which service instances (name, IP, port, health) are currently available, so services can find each other by logical name instead of hardcoded addresses. It also provides a distributed **KV store** (a hierarchical key/value database) and a health-checking subsystem. **The Consul agent.** Every machine runs a Consul *agent*. Agents run in two modes: **client** agents (lightweight, forward requests to servers) and **server** agents (hold state, participate in Raft consensus). Your Spring app talks to a local agent, typically at `localhost:8500` (the HTTP API port). The agent relays registrations to the server cluster. **Spring Cloud Consul.** The `spring-cloud-starter-consul-discovery` starter pulls in auto-configuration (`ConsulAutoConfiguration`, `ConsulDiscoveryClientConfiguration`, `ConsulAutoServiceRegistrationAutoConfiguration`). Simply having it on the classpath enables: - **Auto-registration**: at startup a `ConsulServiceRegistry` / `ConsulAutoServiceRegistration` registers the instance with the agent. The service name defaults to `spring.application.name`; the instance ID defaults to `${spring.application.name}-${server.port}` (or a random suffix). Registration data includes host, port, tags, and a health check. - **Discovery**: a `ConsulDiscoveryClient` implements Spring Cloud's `DiscoveryClient`, letting you call `getInstances("service-name")`. Combined with Spring Cloud LoadBalancer, a `@LoadBalanced RestTemplate`/`WebClient` can use `http://service-name/...` and resolve+balance across healthy instances. **Key properties** (all under `spring.cloud.consul`): - `host` / `port` — the agent (default `localhost` / `8500`). - `discovery.enabled` — turn registration/discovery on/off (default true). - `discovery.service-name` — override the registered name. - `discovery.instance-id` — override the instance ID (make it unique per instance!). - `discovery.register` / `discovery.deregister` — whether to register / deregister on shutdown. - `discovery.prefer-ip-address` — register the IP instead of hostname (common in containers). - `discovery.tags` — arbitrary tags used for filtering. **Bootstrap ordering gotcha.** Historically Consul config was read during the *bootstrap* phase, requiring `spring-cloud-starter-bootstrap` or `spring.cloud.bootstrap.enabled=true`. Modern Spring Cloud uses the **`spring.config.import`** mechanism instead (e.g. `spring.config.import=consul:` for config), so bootstrap is no longer required for KV config. Discovery itself doesn't need bootstrap. **Gotchas / edge cases.** - If no Consul agent is reachable at startup, registration fails; `spring.cloud.consul.discovery.fail-fast` (default true) controls whether the app fails to start or logs and continues. - Duplicate instance IDs cause instances to overwrite each other in the catalog — always ensure uniqueness (default appends a random value in newer versions). - In containers, `prefer-ip-address=true` avoids registering an unroutable container hostname. **When to use.** Choose Consul discovery when you already run Consul (or want its KV/health/mesh features), need multi-datacenter awareness, or want language-agnostic discovery. Alternatives in the Spring Cloud ecosystem include Eureka and Kubernetes-native discovery.

  • What is the difference between a Consul client agent and a server agent?
    Client agents are stateless: they run on every node, register local services, run health checks, and forward RPCs to servers. Server agents hold the replicated catalog/KV state and participate in Raft consensus. Apps normally talk to a local client agent.
  • Do you still need spring-cloud-starter-bootstrap for Consul?
    Not for discovery, and no longer for KV config either — modern Spring Cloud uses `spring.config.import=consul:` instead of the bootstrap context. Bootstrap is only needed on older setups or when explicitly enabled.

context