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

  1. 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.
  2. Start the provider first, wait ~10-30s for registration plus the consumer's registry cache refresh, then retry the /echo call.
  3. Compare spring.application.name in the provider's application.yaml with the literal "demo-provider" used in getInstances — they must match exactly (case-sensitive).
  4. Verify the consumer's eureka.client.serviceUrl.defaultZone points at the same Eureka server the provider registered with.
  5. 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

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.