1. 服务注册与发现概述:什么是服务注册与发现、为什么需要它、核心概念
大家好,我是你们的老朋友。今天咱们正式开始聊服务注册与发现。说实话,这个主题我讲了不下几十次,但每次讲都有新感悟。你想想看,微服务架构里最头疼的问题是什么?服务之间怎么找到对方?怎么知道对方还活着?这就是注册与发现要解决的事。
1.1 什么是服务注册与发现
简单说,服务注册与发现就是一套「自动寻址」机制。传统单体应用里,A服务调用B服务,直接写死IP和端口就行。但在微服务架构下,服务实例会动态扩缩容、会迁移、会重启。你总不能每次部署都去改配置文件吧?
我习惯这么理解:注册中心就像一个「电话本」。服务提供者启动时,把自己的地址(IP+端口)登记上去。服务消费者需要调用时,去电话本里查一下,拿到地址再发起调用。就这么简单。
- 服务提供者启动 → 向注册中心注册自己的元数据
- 服务消费者启动 → 从注册中心订阅需要的服务列表
- 服务提供者下线 → 注册中心主动剔除该实例
- 服务消费者本地缓存 → 即使注册中心挂了,也能继续工作
1.2 为什么需要它
你可能要问:没有注册与发现,难道就不能做微服务了吗?嗯,理论上可以,但你会遇到一堆麻烦。
第一个痛点:硬编码地址
我在项目中遇到过这样的场景:某团队把所有服务地址写在配置文件里,每次上线都要手动改几十个文件。有一次改漏了一个,线上排查了整整三个小时。说白了,人力维护地址列表,在几十个服务规模下就是灾难。
第二个痛点:动态扩缩容
微服务的一大优势是弹性伸缩。流量高峰来了,自动扩容10个实例;流量低谷,缩容到2个。如果没有注册中心,新实例上线了,消费者怎么知道?老实例下线了,消费者还在往它发请求怎么办?
第三个痛点:健康检查
服务实例可能因为各种原因挂掉:内存溢出、网络分区、磁盘满。注册中心会定期做健康检查,把不健康的实例自动摘除。我曾经见过一个案例,某个服务挂了半小时,因为没有健康检查机制,上游服务一直往死节点发请求,导致整个调用链雪崩。
1.3 核心概念
咱们把三个核心角色拆开讲清楚。
1.3.1 注册中心
注册中心是整个机制的「大脑」。它维护着所有服务的地址列表,并提供查询和订阅能力。常见的注册中心有:
| 注册中心 | 特点 | 适用场景 |
|---|---|---|
| Eureka | AP原则,去中心化 | 中小规模,对一致性要求不高 |
| Consul | CP原则,支持多数据中心 | 需要强一致性,跨机房部署 |
| Nacos | 支持AP/CP切换 | 阿里系生态,功能丰富 |
| Zookeeper | CP原则,强一致性 | 对一致性要求极高,但性能有瓶颈 |
我个人习惯用Nacos,因为它既支持AP也支持CP,可以根据业务场景灵活切换。不过选型没有银弹,关键看你的业务对一致性和可用性的权衡。
1.3.2 服务提供者
服务提供者就是「提供服务」的一方。它启动时需要做三件事:
- 向注册中心注册自己的服务名、IP、端口、健康检查接口
- 定期发送心跳,告诉注册中心「我还活着」
- 优雅关闭时,主动通知注册中心下线
这里有个坑:我曾经遇到过服务提供者注册时,把内网IP注册上去了,但消费者在外网访问不到。所以注册时要特别注意网络可达性,最好用服务所在网卡的IP,而不是localhost。
1.3.3 服务消费者
服务消费者是「调用服务」的一方。它的工作流程是:
- 启动时从注册中心拉取服务列表,并缓存到本地
- 订阅服务变更事件,注册中心推送更新时刷新本地缓存
- 调用时,从本地缓存中选取一个实例(负载均衡策略)
- 如果调用失败,尝试重试其他实例
1.4 一个简单的注册与发现示例
光说不练假把式。咱们用Spring Cloud + Nacos演示一下核心流程。代码很简单,但背后的原理值得深思。
// 服务提供者:注册到Nacos
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
// 服务消费者:从Nacos发现服务
@RestController
public class ConsumerController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/call")
public String callService() {
// 从注册中心获取服务实例
List<ServiceInstance> instances =
discoveryClient.getInstances("my-service");
// 选取第一个实例(实际应该用负载均衡)
ServiceInstance instance = instances.get(0);
String url = "http://" + instance.getHost()
+ ":" + instance.getPort() + "/api";
// 发起调用...
return restTemplate.getForObject(url, String.class);
}
}
你看,代码里没有写死任何IP地址。服务提供者启动后自动注册,消费者通过服务名就能找到它。这就是注册与发现的价值所在。
1.5 小结
这一章咱们把服务注册与发现的「是什么、为什么、核心概念」讲清楚了。说白了,它就是微服务架构的「通讯录」,让服务之间能自动找到对方,不用人工维护地址列表。
下一章我会深入讲注册中心的工作原理,包括心跳机制、健康检查、服务剔除策略。这些都是我在生产环境踩过坑后总结出来的经验,保证实用。