照这篇做完,你能从零搭出一套带注册中心、统一网关、声明式调用和熔断限流的 Spring Cloud 微服务骨架,并能跑通一条完整调用链。
第一步:先定版本,别乱配
这套东西最大的坑不是代码,是版本对齐。建议直接抄一组经过验证的组合:
- Spring Boot 2.7.18
- Spring Cloud 2021.0.9
- Spring Cloud Alibaba 2021.0.5.0
- Nacos Server 2.2.3
如果你要用 Spring Boot 3.x,就换成 Spring Cloud 2022.0.x + Spring Cloud Alibaba 2022.0.0.0,Nacos 用 2.2.3 以上。
注意:Nacos 客户端版本和服务端版本差太多会连不上,报 server is DOWN now 之类。客户端版本跟 Spring Cloud Alibaba 走,服务端单独用官网压缩包启动。
第二步:起 Nacos,一个进程搞定注册+配置
下载 Nacos 压缩包解压,进 bin 目录:
sh startup.sh -m standalone
# Windows
startup.cmd -m standalone
浏览器打开 http://localhost:8848/nacos,默认账号密码都是 nacos。注册中心和配置中心是同一个服务的两个功能,不用分开装。
生产环境记得改 conf/application.properties 里的数据库为 MySQL,并把 -m standalone 去掉走集群。
第三步:服务提供者,注册上去
在业务模块的 pom.xml 里加:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
然后写 bootstrap.yml(配置中心的配置必须放这里,不是 application.yml):
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
启动类加 @EnableDiscoveryClient(新版可省略,但加上不报错)。启动后去 Nacos 控制台「服务列表」看有没有 user-service。
注意:如果配置不生效,八成是把 nacos config 写进了 application.yml。Spring Boot 2.4 之后默认不加载 bootstrap 上下文,必须显式引入 spring-cloud-starter-bootstrap。
第四步:Feign,把 HTTP 调用写成接口
在调用方加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
启动类加 @EnableFeignClients,然后:
@FeignClient(name = "user-service", path = "/user")
public interface UserClient {
@GetMapping("/{id}")
Result<UserVO> getById(@PathVariable("id") Long id);
}
name 就是 Nacos 里的服务名,不用写 IP。默认超时 1 秒,业务慢的话在配置里调:
feign:
client:
config:
default:
connectTimeout: 3000
readTimeout: 5000
注意:@PathVariable 必须写括号里的值,否则 Spring Boot 2.7 会直接启动失败。
第五步:Gateway 做统一入口
新建一个独立模块,只加:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置:
server:
port: 8080
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: user
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
lb:// 表示走负载均衡,后面跟服务名。
注意:Gateway 基于 WebFlux,模块里绝对不能引入 spring-boot-starter-web,否则启动时报 Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway。
第六步:Sentinel 兜住流量
下载 sentinel-dashboard.jar 启动:
java -jar sentinel-dashboard-1.8.6.jar --server.port=8858
默认账号密码 sentinel/sentinel。在 Gateway 和各业务模块加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置:
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8858
eager: true
feign:
sentinel:
enabled: true
eager: true 让你不用等首次请求就能在控制台看到服务。feign.sentinel.enabled: true 之后,Feign 调用会自动变成 Sentinel 资源,可以配熔断降级。
自定义兜底逻辑用 @SentinelResource(value = "xxx", blockHandler = "handleBlock"),方法签名要跟原方法一致,最后多一个 BlockException 参数。
注意:Sentinel 控制台里配的规则默认只存在内存,重启就没了。生产必须接 Nacos 做规则持久化,否则等于没配。
小结
- 版本组合先定死,Nacos 客户端跟 Spring Cloud Alibaba 版本走
- Nacos 一个进程同时当注册中心和配置中心,客户端配置写在
bootstrap.yml
- 配置不生效先查有没有
spring-cloud-starter-bootstrap
- Feign 靠服务名调用,
@PathVariable 要写全参数名
- Gateway 模块不能有
spring-boot-starter-web
- Sentinel 规则默认不持久化,上线前一定接 Nacos 持久化