yudaocode/SpringBoot-Labs · error · IllegalStateException
获取不到实例
Error message
获取不到实例
What it means
The labx-27 Spring Cloud Consul discovery consumer throws IllegalStateException("获取不到实例") when DiscoveryClient.getInstances("demo-provider") returns an empty list — Consul's catalog has no healthy instances registered under that name. Consul registers services with health checks (default TTL/HTTP per config); an instance that fails its health check is reported with a critical status, and Spring Cloud's Consul catalog query filters to passing instances by default. So this error arises both when the provider never registered and when it registered but its health check went critical — a distinction from plain Eureka lease semantics.
Source
Thrown at labx-27/labx-27-sc-consul-discovery-demo01-consumer/src/main/java/cn/iocoder/springcloud/labx27/consuldemo/consumer/DemoConsumerApplication.java:59
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/hello")
public String hello(String name) {
// 获得服务 `demo-provider` 的一个实例
ServiceInstance instance;
if (true) {
// 获取服务 `demo-provider` 对应的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
// 选择第一个
instance = instances.size() > 0 ? instances.get(0) : null;
} else {
instance = loadBalancerClient.choose("demo-provider");
}
// 发起调用
if (instance == null) {
throw new IllegalStateException("获取不到实例");
}
String targetUrl = instance.getUri() + "/echo?name=" + name;
String response = restTemplate.getForObject(targetUrl, String.class);
// 返回结果
return "consumer:" + response;
}
}
}
View on GitHub (pinned to 6c12efaed0)
Solutions
- Open the Consul UI (http://localhost:8500) and check the 'demo-provider' service: no service listed → start the demo provider; listed but red/critical → fix its health check (dependency/endpoint) so it turns green.
- Confirm the provider's spring.application.name equals demo-provider exactly and both apps use the same spring.cloud.consul.host/port.
- Start Consul in dev mode first (consul agent -dev), then the provider, wait for its check to pass, then the consumer call.
- If health-check strictness is unwanted in a demo, set spring.cloud.consul.discovery.register-health-check=false or configure queryOptions to skip checks, then retry.
- Handle the empty list explicitly (503 + message) or fall back to LoadBalancerClient.choose with a null check.
Example fix
// before
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
instance = instances.size() > 0 ? instances.get(0) : null;
if (instance == null) {
throw new IllegalStateException("获取不到实例");
}
// after — explicit empty handling referencing Consul health
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
if (instances.isEmpty()) {
throw new IllegalStateException(
"获取不到实例: no passing Consul instances for 'demo-provider'; " +
"check http://localhost:8500 for registration and health status");
}
ServiceInstance instance = instances.get(0); Defensive patterns
Strategy: validation
Validate before calling
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
if (instances.isEmpty()) {
// includes 'registered but health check critical' cases, since queries filter to passing
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,
"demo-provider 无健康实例, 请检查 Consul UI (http://localhost:8500)");
}
ServiceInstance instance = instances.get(0); Type guard
boolean consulHasPassingInstance(DiscoveryClient dc, String service) {
List<ServiceInstance> list = dc.getInstances(service);
return list != null && !list.isEmpty();
} Try / catch
catch (IllegalStateException e) {
if ("获取不到实例".equals(e.getMessage())) {
// likely health-check critical or not yet registered: 503 + hint
return ResponseEntity.status(503)
.body("demo-provider not passing Consul health checks; check consul UI");
}
throw e;
} Prevention
- Run `consul agent -dev` before the apps and keep spring.cloud.consul.host/port aligned on both sides.
- Ensure the provider's health-check endpoint works (actuator + correct spring.cloud.consul.discovery.health-check-path) so instances show green.
- Watch the Consul UI catalog during development: red checks explain empty getInstances results instantly.
- For demos, spring.cloud.consul.discovery.register-health-check=false removes health-gating while you test connectivity.
When it happens
Trigger: Calling /echo when: the Consul provider app is not running or never registered (missing spring-cloud-starter-consul-discovery); spring.application.name ≠ 'demo-provider'; Consul agent not started (default localhost:8500) or consumer's spring.cloud.consul.host/port point to the wrong agent; the provider registered but its health check is critical so the passing-only query yields nothing; provider is mid-startup and registration/health-check propagation has not completed.
Common situations: Consul agent (dev mode: consul agent -dev) not running before the apps; health-check failures (e.g. the default /actuator/health endpoint unavailable because management deps missing, or a misconfigured spring.cloud.consul.discovery.health-check-path); name mismatches between the getInstances literal and provider's spring.application.name; Docker/remote Consul where host/port config is stale; querying a catalog in a different Consul datacenter.
Related errors
AI-assisted analysis of yudaocode/SpringBoot-Labs@6c12efaed0 (2026-08-14).
Data as JSON: /api/errors/59946fd72476007a.
Report an issue: GitHub.