{"record":{"id":"05f250cbfda3e837","repo":"yudaocode/SpringBoot-Labs","slug":"error-05f250","errorCode":null,"errorMessage":"获取不到实例","messagePattern":"获取不到实例","errorType":"exception","errorClass":"IllegalStateException","httpStatus":500,"severity":"error","filePath":"labx-25/labx-25-sc-zookeeper-discovery-demo01-consumer/src/main/java/cn/iocoder/springcloud/labx25/zookeeperdemo/consumer/DemoConsumerApplication.java","lineNumber":59,"sourceCode":"        private RestTemplate restTemplate;\n        @Autowired\n        private LoadBalancerClient loadBalancerClient;\n\n        @GetMapping(\"/hello\")\n        public String hello(String name) {\n            // 获得服务 `demo-provider` 的一个实例\n            ServiceInstance instance;\n            if (true) {\n                // 获取服务 `demo-provider` 对应的实例列表\n                List<ServiceInstance> instances = discoveryClient.getInstances(\"demo-provider\");\n                // 选择第一个\n                instance = instances.size() > 0 ? instances.get(0) : null;\n            } else {\n                instance = loadBalancerClient.choose(\"demo-provider\");\n            }\n            // 发起调用\n            if (instance == null) {\n                throw new IllegalStateException(\"获取不到实例\");\n            }\n            String targetUrl = instance.getUri() + \"/echo?name=\" + name;\n            String response = restTemplate.getForObject(targetUrl, String.class);\n            // 返回结果\n            return \"consumer:\" + response;\n        }\n\n    }\n\n}\n","sourceCodeStart":41,"sourceCodeEnd":70,"githubUrl":"https://github.com/yudaocode/SpringBoot-Labs/blob/6c12efaed06d12907a0f40dd2ad1f7020aec8798/labx-25/labx-25-sc-zookeeper-discovery-demo01-consumer/src/main/java/cn/iocoder/springcloud/labx25/zookeeperdemo/consumer/DemoConsumerApplication.java#L41-L70","documentation":"The labx-25 Spring Cloud Zookeeper discovery consumer throws IllegalStateException(\"获取不到实例\") when DiscoveryClient.getInstances(\"demo-provider\") returns an empty list — the consumer asked Zookeeper for the service path and found no live instances. With Zookeeper, instances are ephemeral znodes under /services/demo-provider; they vanish when the provider session ends, so a crashed/killed provider is removed immediately (unlike Eureka's lease grace period), making this error appear the instant the provider dies or never registers. The consumer must also have spring-cloud-starter-zookeeper-discovery and a reachable Zookeeper server (spring.cloud.zookeeper.connect-string).","triggerScenarios":"Calling the consumer's /echo endpoint when: the Zookeeper provider app is not running (its ephemeral node under /services/demo-provider does not exist); the provider registered under a different name (spring.application.name mismatch with 'demo-provider'); Zookeeper is down or the consumer's connect-string points elsewhere, so CuratorDiscoveryClient queries the wrong ensemble; the provider is still starting and its registration has not completed; or the provider's Zookeeper session expired (network blip) deleting its ephemeral node.","commonSituations":"Zookeeper not installed/started locally (default localhost:2181) before running the demo; provider registered but with a JSON/metadata or name mismatch so the lookup path differs; starting consumer before provider registration finishes; Docker-mapped Zookeeper ports vs connect-string mismatch; session timeouts after laptop sleep/network change removing ephemeral nodes while Eureka habits suggest the instance would linger.","solutions":["Check Zookeeper directly: run `zkCli.sh` then `ls /services/demo-provider` (path may be /services or /spring-cloud per spring.cloud.zookeeper.discovery.root) — if empty, the provider is not registered; start the demo provider.","Confirm the provider's spring.application.name is exactly demo-provider and both apps share the same spring.cloud.zookeeper.connect-string and discovery root.","Ensure the Zookeeper server is up (echo ruok | nc localhost 2181 → imok) and the provider log shows successful Curator connection + registration before calling.","Wait a moment after provider startup and retry — ephemeral registration is fast but not instantaneous; then guard the empty case explicitly or use LoadBalancerClient.choose with a null check."],"exampleFix":"// before\nList<ServiceInstance> instances = discoveryClient.getInstances(\"demo-provider\");\ninstance = instances.size() > 0 ? instances.get(0) : null;\nif (instance == null) {\n    throw new IllegalStateException(\"获取不到实例\");\n}\n\n// after — explicit empty handling referencing Zookeeper semantics\nList<ServiceInstance> instances = discoveryClient.getInstances(\"demo-provider\");\nif (instances.isEmpty()) {\n    throw new IllegalStateException(\n        \"获取不到实例: no ephemeral nodes for 'demo-provider' in Zookeeper; \" +\n        \"verify provider registration at /services/demo-provider\");\n}\nServiceInstance instance = instances.get(0);","handlingStrategy":"validation","validationCode":"List<ServiceInstance> instances = discoveryClient.getInstances(\"demo-provider\");\nif (instances.isEmpty()) {\n    // Zookeeper ephemeral node absent: provider down or never registered\n    throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,\n        \"demo-provider 无可用实例 (Zookeeper /services/demo-provider 为空)\");\n}\nServiceInstance instance = instances.get(0);","typeGuard":"boolean zkServiceRegistered(DiscoveryClient dc, String service) {\n    List<ServiceInstance> list = dc.getInstances(service);\n    return list != null && !list.isEmpty();\n}","tryCatchPattern":"catch (IllegalStateException e) {\n    if (\"获取不到实例\".equals(e.getMessage())) {\n        // ephemeral nodes vanish on provider session loss; retry after short backoff\n        return ResponseEntity.status(503).body(\"demo-provider unavailable in Zookeeper, retry shortly\");\n    }\n    throw e;\n}","preventionTips":["Script the environment: start Zookeeper (zkServer.sh start or docker run zookeeper), wait for port 2181, then apps.","Verify registration with `zkCli.sh ls /services/demo-provider` (adjust for spring.cloud.zookeeper.discovery.root) before calling the consumer.","Pin spring.cloud.zookeeper.connect-string and discovery root consistently across provider and consumer.","Remember Zookeeper removes instances immediately on session loss — unlike Eureka's lease grace — so build in retry/backoff for transient gaps."],"tags":["zookeeper","service-discovery","spring-cloud","ephemeral-nodes","registration","labx-25"],"backgroundTag":null,"analyzedSha":"6c12efaed06d12907a0f40dd2ad1f7020aec8798","analyzedAt":"2026-08-14T13:06:31.500Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}