yudaocode/SpringBoot-Labs · error · IllegalStateException
获取不到实例
Error message
获取不到实例
What it means
Runtime guard in the Eureka consumer demo (labx-22 demo01): the code fetches all instances of service 'demo-provider' from the registry via DiscoveryClient.getInstances("demo-provider"), blindly takes the first entry, and throws IllegalStateException("获取不到实例") when the returned list is empty (instance == null). It means the consumer is asking Eureka for a service name that currently has zero registered, UP instances — the discovery lookup itself succeeded, it just found nothing. The `if (true)` branch shows the demo deliberately uses raw DiscoveryClient instead of LoadBalancerClient.choose.
Source
Thrown at labx-22/labx-22-scn-eureka-demo01-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx22/consumerdemo/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
- Ensure the demo-provider application for this lab is running and registered: open the Eureka server dashboard (default http://localhost:8761) and confirm an instance named exactly 'demo-provider' with status UP.
- Start the provider first, wait ~10-30s for registration plus the consumer's registry cache refresh, then retry the /echo call.
- Compare spring.application.name in the provider's application.yaml with the literal "demo-provider" used in getInstances — they must match exactly (case-sensitive).
- Verify the consumer's eureka.client.serviceUrl.defaultZone points at the same Eureka server the provider registered with.
- If the service may legitimately be absent, handle the empty list explicitly (friendly message / HTTP 503) instead of IllegalStateException, or switch to the loadBalancerClient.choose branch 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 with actionable message
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
if (instances == null || instances.isEmpty()) {
throw new IllegalStateException(
"获取不到实例: service 'demo-provider' has no registered instances; " +
"check provider is running and registered in Eureka");
}
ServiceInstance instance = instances.get(0); Defensive patterns
Strategy: validation
Validate before calling
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
if (instances == null || instances.isEmpty()) {
// do not proceed; surface a 503 with an actionable hint instead of IllegalStateException
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,
"demo-provider unavailable: no instances registered in Eureka");
}
ServiceInstance instance = instances.get(0); Type guard
boolean hasInstance(DiscoveryClient dc, String service) {
List<ServiceInstance> list = dc.getInstances(service);
return list != null && !list.isEmpty();
} Try / catch
try {
String response = restTemplate.getForObject(targetUrl, String.class);
} catch (IllegalStateException e) {
if ("获取不到实例".equals(e.getMessage())) {
// registry empty: 503 + retry hint rather than 500
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "demo-provider 暂无可用实例", e);
}
throw e;
} Prevention
- Start registry → provider → verify UP on the Eureka dashboard → then start the consumer.
- Keep provider spring.application.name and the getInstances literal in one shared constant/config to prevent drift.
- Prefer @LoadBalanced RestTemplate (http://demo-provider/echo?name=...) so empty-instance handling and instance choice are delegated to Spring Cloud LoadBalancer.
- For startup races, add a brief readiness check (actuator health plus a discovery probe) or retry with backoff on SERVICE_UNAVAILABLE.
When it happens
Trigger: Hitting the consumer's /echo?name=xxx endpoint (the controller calls this code at DemoConsumerApplication.java:59) while discoveryClient.getInstances("demo-provider") returns an empty list. That happens when: the provider application is not running, the provider registered under a different spring.application.name, the provider's Eureka registration has not completed or its lease expired, or the consumer itself never connected to the Eureka server so its DiscoveryClient has an empty local cache.
Common situations: Starting the consumer before the provider (registration takes a few seconds plus the client cache refresh interval, default 30s); provider's spring.application.name is not exactly 'demo-provider' (e.g. left as default or typo'd); Eureka server not started or wrong eureka.client.serviceUrl.defaultZone in the consumer, so the fetch returns nothing; provider registered but its instance was evicted (self-preservation/lease expiry); running demo02/demo03 variants whose provider registers a different name.
Related errors
AI-assisted analysis of yudaocode/SpringBoot-Labs@6c12efaed0 (2026-08-14).
Data as JSON: /api/errors/fba9111d48e295d6.
Report an issue: GitHub.