本文目录导读:

- 基于Spring Cloud + Netflix Eureka(经典方案)
- 基于Consul(更现代的方案)
- 基于ZooKeeper(原生实现)
- 基于Nacos(阿里巴巴方案)
- 手动实现服务发现(学习用)
- 选择建议
在Java中实现服务发现,主要有几种方式,从简单到复杂,适用不同的场景。
基于Spring Cloud + Netflix Eureka(经典方案)
这是微服务架构中最常见的方案。
服务注册中心(Eureka Server)
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
服务提供者(Eureka Client)
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
@RestController
public class UserController {
@GetMapping("/users/{id}")
public String getUser(@PathVariable String id) {
return "User-" + id;
}
}
// application.yml
spring:
application:
name: user-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
服务消费者
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
// Feign客户端
@FeignClient(name = "user-service")
public interface UserServiceClient {
@GetMapping("/users/{id}")
String getUser(@PathVariable String id);
}
@RestController
public class OrderController {
@Autowired
private UserServiceClient userServiceClient;
@GetMapping("/orders/{orderId}/user/{userId}")
public String getOrderWithUser(@PathVariable String orderId, @PathVariable String userId) {
String user = userServiceClient.getUser(userId);
return "Order-" + orderId + " with " + user;
}
}
基于Consul(更现代的方案)
Consul提供服务发现、健康检查和KV存储。
@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
// application.yml
spring:
application:
name: product-service
cloud:
consul:
host: localhost
port: 8500
discovery:
healthCheckPath: /actuator/health
healthCheckInterval: 10s
preferIpAddress: true
服务消费者:
@RestController
public class ShoppingCartController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/cart/{id}")
public String getCartWithProducts(@PathVariable String id) {
// 通过DiscoveryClient获取服务实例
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
ServiceInstance instance = instances.get(0);
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/products/" + id;
return "Cart with product from: " + url;
}
}
基于ZooKeeper(原生实现)
非Spring环境下的原生实现。
public class ZookeeperServiceRegistry {
private ZooKeeper zooKeeper;
private static final String BASE_PATH = "/services";
public ZookeeperServiceRegistry(String connectString) throws Exception {
zooKeeper = new ZooKeeper(connectString, 3000, event -> {});
// 确保基础路径存在
if (zooKeeper.exists(BASE_PATH, false) == null) {
zooKeeper.create(BASE_PATH, new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
// 注册服务
public void register(String serviceName, String address, int port) throws Exception {
String servicePath = BASE_PATH + "/" + serviceName;
if (zooKeeper.exists(servicePath, false) == null) {
zooKeeper.create(servicePath, new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
String instancePath = servicePath + "/instance-";
String data = address + ":" + port;
// 创建临时节点,服务下线时自动删除
zooKeeper.create(instancePath, data.getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
}
// 发现服务
public List<String> discover(String serviceName) throws Exception {
String servicePath = BASE_PATH + "/" + serviceName;
List<String> instances = zooKeeper.getChildren(servicePath, false);
List<String> result = new ArrayList<>();
for (String instance : instances) {
byte[] data = zooKeeper.getData(servicePath + "/" + instance, false, null);
result.add(new String(data));
}
return result;
}
}
基于Nacos(阿里巴巴方案)
Nacos集服务发现、配置管理于一体。
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentServiceApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentServiceApplication.class, args);
}
}
// application.yml
spring:
application:
name: payment-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: public
使用Nacos实现负载均衡:
@Configuration
public class NacosConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RestController
public class PaymentClient {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/call-payment/{id}")
public String callPayment(@PathVariable String id) {
// 直接使用服务名,自动负载均衡
String url = "http://payment-service/payments/" + id;
return restTemplate.getForObject(url, String.class);
}
}
手动实现服务发现(学习用)
适用于学习理解服务发现原理:
// 服务注册表
public class InMemoryServiceRegistry {
private static final Map<String, List<ServiceInstance>> registry = new ConcurrentHashMap<>();
public static void register(String serviceName, String host, int port) {
registry.computeIfAbsent(serviceName, k -> new CopyOnWriteArrayList<>())
.add(new ServiceInstance(host, port));
}
public static void deregister(String serviceName, String host, int port) {
List<ServiceInstance> instances = registry.get(serviceName);
if (instances != null) {
instances.remove(new ServiceInstance(host, port));
}
}
public static List<ServiceInstance> getInstances(String serviceName) {
return registry.getOrDefault(serviceName, Collections.emptyList());
}
// 带简单负载均衡的获取
public static ServiceInstance getInstance(String serviceName) {
List<ServiceInstance> instances = getInstances(serviceName);
if (instances.isEmpty()) {
return null;
}
// 轮询策略
int index = (int) (System.currentTimeMillis() % instances.size());
return instances.get(index);
}
}
@Data
@AllArgsConstructor
public class ServiceInstance {
private String host;
private int port;
}
选择建议
| 方案 | 复杂度 | 成熟度 | 适用场景 |
|---|---|---|---|
| Eureka | 低 | 高 | Spring Cloud生态,传统微服务 |
| Consul | 中 | 高 | 需要健康检查和KV存储 |
| Nacos | 中 | 高 | 阿里生态,需要配置管理 |
| ZooKeeper | 中 | 高 | 非Spring生态,大数据场景 |
| Kubernetes Service | 低 | 高 | K8s环境 |
对于新项目,建议优先考虑Nacos(国内团队常用)或Kubernetes Service(如果使用K8s),它们配置简单、功能完善。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播