第1章:微服务核心组件全景概览
说实话,我刚接触微服务那会儿,最头疼的就是这些组件怎么搭在一起。你想想看,一个系统拆成几十个服务,每个服务都有自己的地址、端口、配置,光靠人工记?那简直是噩梦。
这一章,我带你把服务注册与发现、配置中心、API网关这三个核心组件理清楚。它们就像微服务的骨架,缺一个都跑不起来。
1.1 服务注册与发现:Nacos vs Eureka
服务注册与发现,说白了就是让服务之间能找到彼此。我习惯把它比作「电话本」——每个服务启动时,先把自己的地址写到电话本里;要调用别人时,翻翻电话本就行了。
1.1.1 为什么需要它?
没有服务发现的时候,我们怎么做?硬编码IP地址。我在项目中遇到过,某个服务迁移服务器,结果所有调用方都得改配置、重启。那叫一个痛苦。
有了服务发现,这些问题就简单了:
- 服务启动时自动注册
- 服务下线时自动摘除
- 调用方只需知道服务名,不用关心具体IP
1.1.2 Nacos vs Eureka 怎么选?
| 特性 | Nacos | Eureka |
|---|---|---|
| CAP理论 | AP+CP 可切换 | AP |
| 健康检查 | 支持TCP/HTTP/MySQL | 仅心跳 |
| 配置中心 | 内置 | 需集成Spring Cloud Config |
| 控制台 | 功能丰富 | 较简单 |
| 社区活跃度 | 阿里主导,更新快 | Netflix已停止维护 |
我个人习惯用Nacos。原因很简单:它把注册中心和配置中心合二为一了。你想想看,少维护一个组件,运维成本直接减半。
避坑指南:我曾经在生产环境遇到过Eureka的自我保护机制导致服务下线不彻底。某个节点挂了,但Eureka Server还保留着它的注册信息,结果调用方一直往死节点发请求。Nacos在这方面做得更好,支持主动健康检查。
1.1.3 快速集成示例
用Spring Cloud Alibaba集成Nacos,其实就三步:
// 1. 添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
// 2. 配置application.yml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
// 3. 启动类加注解
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
嗯,这里要注意:namespace是用来隔离环境的。我习惯把dev、test、prod分别建不同的namespace,这样配置和注册信息就不会串了。
1.2 配置中心:Apollo vs Nacos
配置中心解决的是「改配置不用重启」的问题。我记得以前改个数据库连接池大小,得发版、重启、验证,折腾半小时。现在?改完配置,几秒钟就生效了。
1.2.1 核心能力对比
| 能力 | Apollo | Nacos Config |
|---|---|---|
| 配置实时推送 | 长轮询+通知 | 长轮询 |
| 配置灰度 | 支持 | 需自研 |
| 权限管理 | 完善 | 基础 |
| 配置回滚 | 一键回滚 | 支持 |
| 多环境管理 | 原生支持 | 通过namespace |
如果你问我怎么选?我的建议是:
- 中小团队、新项目 → Nacos Config(轻量,和注册中心共用)
- 大型项目、需要精细权限控制 → Apollo(功能更强大)
个人经验:我在一个金融项目中用过Apollo,它的配置灰度发布功能帮了大忙。先让10%的流量验证新配置,没问题再全量推送。万一出问题,一键回滚,影响范围可控。
1.2.2 配置热更新示例
// 使用Nacos Config实现配置热更新
@RefreshScope
@Component
public class DynamicConfig {
@Value("${order.timeout:5000}")
private int orderTimeout;
// 这个值会随配置中心变化而自动更新
public int getOrderTimeout() {
return orderTimeout;
}
}
// 或者用更推荐的方式:监听配置变化
@Configuration
public class NacosConfigListener {
@NacosConfigListener(dataId = "order-service.yml", groupId = "DEFAULT_GROUP")
public void onConfigChange(String config) {
// 配置变化时,重新加载
System.out.println("配置已更新:" + config);
}
}
说白了,配置中心的核心价值就两个:不改代码改配置、不改配置不重启。能做到这两点,运维效率至少提升50%。
1.3 API网关:Gateway vs Kong
API网关是微服务的「大门」。所有外部请求都先经过它,由它决定请求该去哪个服务。我习惯把网关看作「交通警察」——它负责路由、限流、鉴权、日志等横切关注点。
1.3.1 两种技术路线
| 维度 | Spring Cloud Gateway | Kong |
|---|---|---|
| 语言 | Java(Reactive) | Lua/OpenResty |
| 性能 | 中等 | 高(基于Nginx) |
| 扩展性 | Java代码扩展 | 插件机制 |
| 学习成本 | 低(Spring生态) | 中 |
| 适用场景 | Java技术栈团队 | 高性能、多语言 |
我个人习惯:如果团队全是Java,用Spring Cloud Gateway就够了。如果团队技术栈杂,或者对性能要求极高,Kong是更好的选择。
1.3.2 路由配置实战
// Spring Cloud Gateway 路由配置
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 用户服务路由
.route("user-service", r -> r
.path("/api/user/**")
.filters(f -> f
.stripPrefix(1) // 去掉/api前缀
.addRequestHeader("X-Gateway", "true")
.circuitBreaker(config -> config
.setName("userCB")
.setFallbackUri("forward:/fallback/user")))
.uri("lb://user-service"))
// 订单服务路由
.route("order-service", r -> r
.path("/api/order/**")
.filters(f -> f
.stripPrefix(1)
.requestRateLimiter(config -> config
.setRateLimiter(redisRateLimiter())))
.uri("lb://order-service"))
.build();
}
注意:我曾经在生产环境踩过一个坑——网关的超时时间设置得太短。某个服务偶尔响应慢,网关直接返回504。后来我把全局超时从2秒调到5秒,再配合熔断降级,问题就解决了。记住:超时和熔断要配合使用,不是越短越好。
1.4 三个组件如何协同工作?
你想想看,这三个组件其实是一条链:
- 服务启动 → 向Nacos注册自己,从Nacos拉配置
- 外部请求 → 先到Gateway,Gateway从Nacos发现目标服务地址
- 服务间调用 → 通过Nacos发现对方地址,使用从配置中心获取的配置
说白了,Nacos是「大脑」,存着所有服务的地址和配置;Gateway是「门卫」,负责接待和分流。两者配合,微服务才能跑得稳。
核心要点总结:
- 服务注册与发现:解决「服务在哪」的问题
- 配置中心:解决「配置怎么管」的问题
- API网关:解决「请求怎么走」的问题
- 三者缺一不可,共同构成微服务的基础设施
好了,这一章我们理清了三个核心组件的定位和选型。下一章,我会带你动手搭建一个完整的Nacos集群,从单机到生产级部署,一步步来。