概述
上篇把地图铺好了------微服务是什么、拆完会冒出哪些新问题、SpringCloud 里各组件各管哪一段。今天不再停在概念层,直接把示例工程 cloud-demo 拆开、把服务连起来,一天走完:服务拆分 → Eureka → Ribbon → Nacos 四站。
纲要
- 今天的范围边界:只讲"服务怎么拆、怎么调、地址从哪来、多实例怎么选",网关、Feign、配置管理留给明天
- 四个站点的先后顺序,以及每一步是被什么问题逼出来的
- 每站学完能做什么:关键注解、关键类、该去哪个控制台看效果
- 全天共用的示例工程
cloud-demo的演进结构,以及基线版与终态版的差别 - 动手优先级:哪些必须亲手跑通,哪些可以先看懂再动手
- 与《微服务框架课程介绍》的分工:那篇是全模块总纲,本篇只划今天的范围
今天只走一条线
模块总纲把 Eureka、Nacos、Feign、Gateway、配置管理全列了一遍,那是十几篇的活。今天动到的只是前半段,按讲义顺序正好四块:
- 服务拆分与远程调用 ------把单体拆成
user-service和order-service,让订单服务通过 HTTP 去取用户数据 - Eureka 注册中心------服务地址不再写死在配置文件里
- Ribbon 负载均衡------有了多个实例之后,请求该落到哪一个
- Nacos 注册中心------阿里系的注册中心,以及它和 Eureka 到底差在哪
第二天才进 Gateway、Feign、Nacos 配置管理。先把这条边界记牢,今天就不会被"还有一堆组件没学"的焦虑带偏------今天这四块本身就是一条完整的因果链,缺任何一环后面的都接不上。
顺序不是排的,是被问题逼出来的
这四站的顺序不能打乱,也不是老师按目录随手排的。每一站都是上一站暴露出来的问题逼出来的:
渲染错误: Mermaid 渲染失败: Parse error on line 6: ...多个实例该选哪一个] E -->|@LoadBalanced 底层其实走 ----------------------^ Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'LINK_ID'
拆开讲每一步为什么会引出下一步:
先拆,才知道调用会变成网络请求。 单体时代 orderService.queryOrderById() 里直接 new 一个 User 就完了;拆完之后订单库里没有用户表,数据在另一个进程、另一个库里,只能调对方暴露的 Restful 接口。这一步用的是 Spring 自带的 RestTemplate,把 http://localhost:8081/user/{id} 拼出来发出去。跑通一次就会发现:调用真的变成了一次可能超时、可能失败、要处理 JSON 的网络请求。
RestTemplate 一落地,地址硬编码的问题立刻现形。 URL 里 localhost:8081 是写死的,用户服务换台机器、加个实例、改个端口,订单服务就得改配置重新发版;而且订单服务压根不知道用户服务到底有几个实例、还活着没有。这三个问题------地址怎么来、多实例怎么选、实例健康与否------单靠 RestTemplate 解决不了,注册中心就是为它们准备的。Eureka 里对应三个动作:服务注册、服务拉取、心跳。
注册中心一上,多实例的选择问题就被推到了台前。 你把用户服务启动两份(8081、8082),Eureka 里能看到两个实例,但订单服务拉到列表之后总得挑一个。这个"挑"的动作在讲义里只用了一个 @LoadBalanced 注解就完成了,背后的执行者就是 Ribbon。所以 Ribbon 不是可学可不学的加分项,它是 Eureka 服务发现的默认配套。
从 Eureka 换到 Nacos,本质是同一个岗位换代。 Eureka 归 Netflix,1.x 之后基本停止演进;Nacos 出自阿里,同样做注册中心,却多了服务分级存储(按机房分集群)、实例权重、namespace 环境隔离,健康检测也不再只是被动等心跳。它俩结构相似、用法几乎一样,讲义把它们放在一起对比,是因为面试和实际选型都必须答得出"为什么国内项目多数用 Nacos"。
每站学完手里多什么
| 站点 | 解决的问题 | 关键注解 / 类 | 该去哪个控制台看 |
|---|---|---|---|
| 服务拆分与远程调用 | 服务间不能直连数据库,只能走 Restful 接口取数 | RestTemplate、@Bean、@MapperScan |
浏览器访问 http://localhost:8081/user/1 |
| Eureka 注册中心 | 地址硬编码、实例列表与健康状态不可知 | @EnableEurekaServer、@LoadBalanced、EurekaClient |
http://127.0.0.1:10086 |
| Ribbon 负载均衡 | 拿到多个实例后按算法挑一个 | IRule、ZoneAvoidanceRule、NFLoadBalancerRuleClassName |
请求两次,看日志里打出的端口在 8081 / 8082 之间轮换 |
| Nacos 注册中心 | 更主动的健康检测、分级集群、权重与环境隔离 | NacosRule、discovery.cluster-name、discovery.namespace、ephemeral |
http://localhost:8848/nacos |
Eureka 和 Nacos 的差别,落到配置上就三行:地址从 eureka.client.service-url.defaultZone 换成 spring.cloud.nacos.server-addr,注册规则可以从 ZoneAvoidanceRule 换成 com.alibaba.cloud.nacos.ribbon.NacosRule,再加一行 ephemeral: false 就能把实例改成非临时实例(宕机也不剔除)。
全天共用一个工程
这四块不是各写一个 demo,而是围绕同一个 cloud-demo 反复改造。第一站拆出两个服务,第二站加一个注册中心服务端,第三站改一个注解加一段配置,第四站换依赖、换地址:
tree
cloud-demo/
├── pom.xml # 父工程:统一管理 SpringCloud / SpringBoot / MyBatis 版本
├── user-service/ # 用户服务,端口 8081,提供 Restful 接口
│ └── src/main/
│ ├── java/cn/itcast/user/{UserApplication,mapper,pojo,service,web}
│ └── resources/application.yml
├── order-service/ # 订单服务,基线 8080、接入注册中心后 8088
│ └── src/main/
│ ├── java/cn/itcast/order/{OrderApplication,mapper,pojo,service,web}
│ └── resources/application.yml
├── eureka-server/ # 第二站新增:注册中心服务端,端口 10086
│ └── src/main/java/cn/itcast/eureka/EurekaApplication.java
├── feign-api/ # 后置章节:Feign 客户端与公共 pojo 抽成独立模块
└── gateway/ # 后置章节:网关,外部请求的统一入口
有个容易踩的坑:课前的 资料/cloud-demo 是基线版 ------order-service 的 RestTemplate 里还写着 http://localhost:8081,两个 yml 里都没有任何 eureka / nacos 配置。而 代码/cloud-demo 是终态版,yml 里已经是 Nacos 的地址。跟着讲义敲的时候,某一节的配置要以讲义当节给的为准,别直接抄终态文件,否则你会发现"我还没学到 Nacos,配置里怎么就有 Nacos 了"。
动手优先级
时间有限的话,按这个顺序用手:
必须先亲手跑通的三块:
- 服务拆分与远程调用。这是后面所有内容的载体。不亲手感受一次"本地方法调用变成了可能失败的 HTTP 请求",后面每个组件都像在解决一个不存在的问题。
- Eureka 的注册与发现 。把两个服务注册上去,在 10086 页面上看到实例列表,再把
RestTemplate的地址从 IP 换成服务名http://userservice/user/{id}------这一改就是"服务发现"这四个字的全部含义。 - Ribbon 的策略改配与饥饿加载 。把
userservice.ribbon.NFLoadBalancerRuleClassName改成RandomRule看请求还轮不轮询,再打开ribbon.eager-load观察第一次请求的耗时变化。
可以先看懂、晚点再动手的:
- Nacos 环境隔离与集群搭建 。
namespace的坑比较多(namespace 不一致会直接报找不到服务),集群搭建偏运维,本地单机跑通注册流程就够了。 - Nacos 与 Eureka 的对比。这更像面试题,动手环节不深,重点是能说清 AP / CP、临时实例与非临时实例、心跳检测与主动检测的区别。
下一篇
今天结束,手上就该有一个"两个服务 + 一个注册中心 + 能按服务名互相调用"的可运行工程。下一篇从最底层补概念:认识微服务与服务架构演变------单体架构、分布式架构、微服务三者的定义与取舍,以及为什么说微服务是"一种经过良好架构设计的分布式架构方案"。今天先把工程跑起来,概念那块到时候对号入座会轻松很多。
官方文档
总结
今天的价值不在于记住四个组件的名字,而在于看懂它们之间"问题 → 技术"的递进:拆服务逼出远程调用,远程调用逼出注册中心,注册中心逼出负载均衡,Eureka 的停更逼出 Nacos。这条链条记牢了,明天再学 Feign 和 Gateway 时,你就能自己判断它们分别插在哪一环,而不是当成新的孤立知识点重背一遍。
工程上只有一件事要盯住:cloud-demo 全天在长大,每学一门技术它就变一次,边学边跑比最后统一补代码省事得多。端口口径别混------注册中心 10086、用户服务 8081、订单服务基线 8080 接入后 8088、Nacos 默认 8848。