Java框架 SpringCloud 快速入门: 微服务框架课程介绍与知识地图

概述

这是整个 SpringCloud 模块的导引篇。它不讲某一个组件的接口怎么调,而是先把"微服务到底想解决什么、SpringCloud 里的这一堆组件各自负责哪一段、按什么顺序学"讲清楚------先有地图再走路,后面十几篇才不至于变成一堆互不相干的 API 堆砌。

纲要

  • 为什么要学微服务:求职、企业开发、并发增长、需求快速迭代四条现实理由
  • 单体架构在规模上撑不住的三个痛点
  • 微服务解决了老问题,又引入了哪些新问题(服务发现、远程调用、分布式配置、统一入口)
  • SpringCloud 知识地图:组件按"解决什么问题"分层串起来
  • SpringCloud 与 SpringBoot 的分工和版本对应关系(Hoxton.SR10 ↔ 2.3.9.RELEASE)
  • 本模块组件与能力对照表
  • 贯穿全模块的示例工程 cloud-demo 结构预览
  • 学习路径建议:哪些必须先动手、哪些可以后置
  • 下一篇预告

为什么要学微服务

把理由拆开看,其实就四类,前两类关于你,后两类关于企业。

求职角度:Java 后端面试里微服务是必问题。SpringCloud、注册中心、网关、熔断这些词说不上来,简历基本进不了下一轮。这不是课程宣传,是岗位 JD 里的硬门槛。

开发角度:企业项目现在极少有纯单体的了,中大型系统基本都是拆分后的多服务。进公司第一天就要在服务群里找别人的接口文档,不会微服务等于不会干活。这个模块除了讲微服务本身,还会讲微服务开发中会踩的各种坑和对应方案------所以学完拿到手的是一整套解决方案,不只是几个注解。

企业角度一,扛并发:互联网用户规模摆在那儿,一台 Tomcat 撑不住百万级并发,靠加机器也不是简单堆叠就能解决,得先把系统拆开,每个模块独立部署、独立扩容。微服务是应对高并发的前提。

企业角度二,扛变化:业务需求一直在变,单体项目所有功能耦合在一起,改一个模块要反复评估对其它模块的影响,上线一次提心吊胆。拆成服务之后,服务间耦合度低,改一个服务基本不用管别人,迭代效率高,这才撑得起敏捷开发。

单体架构撑不住的三个痛点

先把"为什么必须拆"说透。单体架构把全部业务打成一个包部署,好处是架构简单、部署成本低,做学生管理系统这种小项目完全够用。一旦规模上来,问题集中爆发在三处:

痛点 具体表现
编译部署慢 代码量堆到几十万行,改一行日志也要全量编译打包,一次构建十几分钟起步,本地启动动辄几十秒
模块边界模糊 所有功能写在同一个工程里,包结构靠人自觉维护。时间一长,订单代码调用户代码、用户代码反向调订单代码,形成循环依赖,谁也不敢动
无法按模块扩容 秒杀场景只有下单接口压力大,但单体只能整个应用一起扩容,跟着被放大的还有根本没人访问的管理后台

拆成微服务后,一个功能模块一个服务,大型企业里成百上千个服务都正常,每个服务独立部署,并发能力自然上去了。

但拆开不是免费的午餐。原来一个方法调用搞定的事,现在变成了跨网络的 HTTP 请求,紧接着冒出来一串新问题:

  • 服务地址怎么找?IP 和端口写死在代码里,服务换机器就全崩
  • 有多个实例时调哪一个?总不能手动挑
  • 某个实例挂了怎么知道?请求打过去一直超时才反应过来
  • 几十个服务的配置文件散落在各处,改一个数据库地址要挨个改
  • 用户该从哪个入口进来?每个服务都对外暴露端口、各自做鉴权显然不现实
  • 部署几十上百台服务器靠人手一个个操作,工作量巨大还容易出错

微服务的价值不在于"拆",而在于拆完之后有一套东西来管理这些新问题。 SpringCloud 就是这套东西的集合。

从问题到技术:一张对应表

下面这张表是本模块的骨架,后面每一章基本都在填其中一行。

新问题 对应技术 定位
服务之间怎么调用 RestTemplate / Feign 发起远程 HTTP 调用,Feign 让调用像调本地接口
服务地址从哪来、怎么管理调用关系 注册中心(Eureka / Nacos) 服务启动时上报自己的地址,调用方按服务名拉取实例列表
多个实例怎么选 Ribbon / Spring Cloud LoadBalancer 拿到实例列表后按算法挑一个,实现负载均衡
某个实例是不是还活着 心跳机制 实例定期上报状态,超时未上报就从列表里剔除
一堆配置散落各处 配置中心(Nacos Config) 配置集中存放,支持热更新,改完不用重启服务
用户从哪进来、谁来鉴权 服务网关(Gateway) 统一入口,负责路由、鉴权、限流、跨域
某个服务挂了会不会拖垮全链路 熔断降级 / 服务保护 故障服务快速失败,避免级联失败拖垮整条调用链
出问题怎么定位 分布式日志、链路追踪与系统监控 汇总各服务日志、监控每个节点的 CPU/内存/响应耗时
上百台机器怎么部署 容器化与持续集成(Docker、K8s) 自动化打包成镜像、编排部署,替代人工逐台操作

表里最后几行的缓存、消息队列、分布式搜索、DevOps 属于更外层的微服务解决方案,本模块先建立印象,具体技术会在对应专题里展开。

SpringCloud 知识地图

把上面的技术按调用链串起来,就是一个请求从进入系统到落库的完整路径。
#mermaid-svg-g8IFQ9TpPbwVPDPd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-g8IFQ9TpPbwVPDPd .error-icon{fill:#552222;}#mermaid-svg-g8IFQ9TpPbwVPDPd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-g8IFQ9TpPbwVPDPd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .marker.cross{stroke:#333333;}#mermaid-svg-g8IFQ9TpPbwVPDPd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-g8IFQ9TpPbwVPDPd p{margin:0;}#mermaid-svg-g8IFQ9TpPbwVPDPd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .cluster-label text{fill:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .cluster-label span{color:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .cluster-label span p{background-color:transparent;}#mermaid-svg-g8IFQ9TpPbwVPDPd .label text,#mermaid-svg-g8IFQ9TpPbwVPDPd span{fill:#333;color:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .node rect,#mermaid-svg-g8IFQ9TpPbwVPDPd .node circle,#mermaid-svg-g8IFQ9TpPbwVPDPd .node ellipse,#mermaid-svg-g8IFQ9TpPbwVPDPd .node polygon,#mermaid-svg-g8IFQ9TpPbwVPDPd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .rough-node .label text,#mermaid-svg-g8IFQ9TpPbwVPDPd .node .label text,#mermaid-svg-g8IFQ9TpPbwVPDPd .image-shape .label,#mermaid-svg-g8IFQ9TpPbwVPDPd .icon-shape .label{text-anchor:middle;}#mermaid-svg-g8IFQ9TpPbwVPDPd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .rough-node .label,#mermaid-svg-g8IFQ9TpPbwVPDPd .node .label,#mermaid-svg-g8IFQ9TpPbwVPDPd .image-shape .label,#mermaid-svg-g8IFQ9TpPbwVPDPd .icon-shape .label{text-align:center;}#mermaid-svg-g8IFQ9TpPbwVPDPd .node.clickable{cursor:pointer;}#mermaid-svg-g8IFQ9TpPbwVPDPd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .arrowheadPath{fill:#333333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-g8IFQ9TpPbwVPDPd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-g8IFQ9TpPbwVPDPd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-g8IFQ9TpPbwVPDPd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-g8IFQ9TpPbwVPDPd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .cluster text{fill:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd .cluster span{color:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-g8IFQ9TpPbwVPDPd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-g8IFQ9TpPbwVPDPd rect.text{fill:none;stroke-width:0;}#mermaid-svg-g8IFQ9TpPbwVPDPd .icon-shape,#mermaid-svg-g8IFQ9TpPbwVPDPd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-g8IFQ9TpPbwVPDPd .icon-shape p,#mermaid-svg-g8IFQ9TpPbwVPDPd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-g8IFQ9TpPbwVPDPd .icon-shape .label rect,#mermaid-svg-g8IFQ9TpPbwVPDPd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-g8IFQ9TpPbwVPDPd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-g8IFQ9TpPbwVPDPd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-g8IFQ9TpPbwVPDPd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 按路径路由

  1. 按服务名调用
  2. 返回可用实例列表
  3. 负载均衡选一个实例
  4. 发起真实 HTTP 请求
    声明式调用
    下发配置
    包裹调用
    用户 / 浏览器
    服务网关 Gateway

统一入口·路由·鉴权·跨域
order-service 订单服务
注册中心 Eureka / Nacos

服务地址不再硬编码
Ribbon / LoadBalancer
user-service 用户服务
Feign 远程调用
user 库
order 库
配置中心 Nacos Config

配置集中管理·热更新
服务保护

熔断·降级·限流

每一层用一句话说清它存在的理由:

  • 服务拆分与远程调用:不拆就没法独立扩容;拆了之后方法调用变成网络请求,得有人把 HTTP 调用封装成"像调本地方法一样"。没有它,就得手写 HttpClient、自己拼 URL、自己处理 JSON 和异常。
  • 注册中心:没有它,调用方只能把提供方的 IP 和端口写死在配置文件里,服务扩缩容、换机器、加实例都要改代码重新发版。有了它,服务按名字找,地址是动态的。
  • 负载均衡:没有它,一个服务部署了三个实例,请求全打到第一个上,等于白扩容。有了它,请求按算法分散到各实例。
  • 配置中心:没有它,几十个服务的配置散落在各自仓库,改一个公共参数要挨个提交、挨个重启。有了它,配置集中管理,还能在不停机的情况下热更新。
  • 服务网关:没有它,每个微服务都要对外暴露端口、各自实现鉴权逻辑,前端还要记住一堆地址。有了它,所有流量走一个入口,鉴权、限流、跨域这些横切关注点收在一处,就像小区门口的保安------先看你是谁、再问你要找谁,然后告诉你往哪走。
  • 服务保护:没有它,链路上任何一个服务变慢或挂掉,调用方线程会被大量阻塞,故障沿着调用链级联扩散,最终整个系统雪崩。有了它,故障服务被快速熔断,请求走降级逻辑,损失可控。

SpringCloud 与 SpringBoot 的关系

这两个名字经常被混在一起,分工其实很清楚:

  • SpringBoot 解决"单个服务怎么快速搭起来"------自动配置、内嵌 Tomcat、starter 依赖,让一个独立服务几分钟就能跑起来。
  • SpringCloud 解决"多个服务之间怎么协同"------它把注册中心、网关、负载均衡这些组件集成起来,底层基于 SpringBoot 的自动装配能力实现,所以用起来也是加依赖、加注解、写配置。

关系是前者是地基,后者是地基上盖的楼。这也意味着两者版本必须匹配,SpringCloud 的每个大版本都锁定了对应的 SpringBoot 版本区间,配错了启动就会报版本不兼容。

SpringCloud 版本 对应 SpringBoot 版本
Hoxton.SR10(本模块使用) 2.3.x(示例工程实际用 2.3.9.RELEASE)
Greenwich 2.1.x
Finchley 2.0.x
2020.x 及以后 2.4.x 往上(命名规则从地名改为年份)

版本写在哪?在父工程的 pom.xml 里用属性统一声明,子模块不写版本号,避免各写各的。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.itcast.demo</groupId>
    <artifactId>cloud-demo</artifactId>
    <version>1.0</version>
    <packaging>pom</packaging>

    <modules>
        <module>user-service</module>
        <module>order-service</module>
    </modules>

    <!-- 父工程直接继承 spring-boot-starter-parent,锁定 SpringBoot 版本 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>2.1.1</mybatis.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- 用 import 方式引入 SpringCloud 的 BOM,子模块即可省略版本号 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

有个坑值得先提一句:dependencyManagement 只是"声明版本",不会真的引入依赖。子模块必须自己写 <dependency> 才会生效,很多人第一次配完发现类找不到,就是漏了这一步。

本模块组件与能力对照表

把全模块要动手的组件列出来,方便对照后面各章的归属。

组件 定位 解决的问题 后续章节
RestTemplate Spring 自带的 HTTP 客户端 手写远程调用的起点,理解"调用变成了网络请求" 服务拆分与远程调用
Feign 声明式 HTTP 客户端 把远程调用写成接口,不用手拼 URL 和解析响应 Feign 远程调用
Eureka 注册中心(Netflix) 服务注册与发现,地址不再硬编码 认识微服务
Nacos 注册中心 + 配置中心(阿里) 国内主流方案,含集群分级、权重、环境隔离 Nacos 注册中心
Ribbon 客户端负载均衡 从实例列表里按算法选一个实例 Ribbon 负载均衡
Spring Cloud LoadBalancer 新一代负载均衡 替代进入维护期的 Ribbon 版本升级说明
Nacos Config 配置中心 配置集中管理与热更新 配置管理
Gateway 服务网关 统一入口、路由转发、鉴权、限流、跨域 网关快速入门
熔断降级组件 服务保护 防级联失败与雪崩(本模块侧重概念与场景) 服务保护

贯穿全模块的示例工程 cloud-demo

这套课程不是每章换一个 demo,而是从头到尾围绕同一个工程 cloud-demo 迭代。刚开始它只有两个服务,随着章节推进逐步长出注册中心、网关、Feign 客户端。

tree 复制代码
cloud-demo/
├── pom.xml                     # 父工程:统一管理 SpringCloud / SpringBoot / MyBatis 版本
├── user-service/               # 用户微服务(端口 8081),对外暴露 Restful 接口
│   ├── pom.xml
│   └── src/main/
│       ├── java/cn/itcast/user/
│       │   ├── UserApplication.java
│       │   ├── mapper/UserMapper.java
│       │   ├── pojo/User.java
│       │   ├── service/UserService.java
│       │   └── web/UserController.java
│       └── resources/application.yml
├── order-service/              # 订单微服务(端口 8080),查询订单时需要调用户服务
│   ├── pom.xml
│   └── src/main/
│       ├── java/cn/itcast/order/
│       │   ├── OrderApplication.java
│       │   ├── mapper/OrderMapper.java
│       │   ├── pojo/{Order.java, User.java}
│       │   ├── service/OrderService.java
│       │   └── web/OrderController.java
│       └── resources/application.yml
├── feign-api/                  # 后置章节新增:Feign 客户端与公共 pojo 抽成独立模块
│   ├── pom.xml
│   └── src/main/java/cn/itcast/feign/{clients,config,pojo}/
├── eureka-server/              # 后置章节新增:注册中心服务端(端口 10086)
│   ├── pom.xml
│   └── src/main/
│       ├── java/cn/itcast/eureka/EurekaApplication.java
│       └── resources/application.yml
└── gateway/                    # 后置章节新增:服务网关,所有外部请求的统一入口
    ├── pom.xml
    └── src/main/
        ├── java/cn/itcast/gateway/GatewayApplication.java
        └── resources/application.yml

拆分遵循三条原则,后面写代码时会反复用到:

  • 不同微服务不重复开发相同业务,用户相关的逻辑只放在 user-service
  • 数据独立,order-service 不能直接查 user 库,两张表各归各的服务管
  • 需要别人的数据时,只能通过对方暴露的 Restful 接口拿

第一条远程调用的代码长这样,先注册一个 RestTemplate 到 Spring 容器,再在订单服务里用它去请求用户服务:

java 复制代码
package cn.itcast.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    /**
     * 把 RestTemplate 交给 Spring 管理,后续直接注入即可发起 HTTP 调用。
     * 注意:这里地址还是写死的 http://localhost:8081,注册中心那一章会把它换成服务名。
     */
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

这段代码里 localhost:8081 就是"地址硬编码"的活标本。等注册中心上完,这里会被替换成 http://userservice/user/{id},Ribbon 负责把 userservice 翻译成真实 IP 和端口。

学习路径建议

知识点多且杂,按"企业使用频率 + 实用性"排优先级,别按目录顺序硬啃。

必须先动手、而且建议边写边理解的三块:

  • 服务拆分与远程调用。这是所有后续内容的载体,先感受单体调用变成 HTTP 请求之后到底多了哪些麻烦(超时、序列化、异常处理),否则后面每个组件都是在解决"不存在的问题"。
  • 注册中心。理解服务注册、服务拉取、心跳三个动作,以及为什么调用方可以只写服务名。Eureka 和 Nacos 都过一遍,重点看它们对临时实例、健康检测的处理差异。
  • 远程调用与负载均衡的配合。手动起两个 user-service 实例,观察请求怎么在两个端口之间轮询,这个"看得见的效果"比背算法名称有用得多。

可以后置的:

  • 配置管理。它是运维友好型能力,本地开发感受不深,等有了多环境(dev/test/prod)需求再重点看。
  • 服务网关。独立于服务拆分之外,晚一点学不影响前面的理解。
  • 集群搭建与高可用部署。偏向运维,面试偶尔问,实际开发中通常有专门的部署平台,放最后。
  • 熔断降级、分布式事务、分布式日志与链路追踪。这类更贴近原理、使用频率相对低,先会用再研究。

按这个顺序走,基本能做到"每学一章,手上的 cloud-demo 就真的变复杂一点",而不是攒一堆跑不起来的示例代码。

下一篇预告

下一篇从最基础的地方开始:认识微服务与服务架构演变。会讲清楚单体架构、分布式架构、微服务这三者各自的定义和优缺点,为什么说"微服务是一种经过良好架构设计的分布式架构方案",以及 SpringCloud 与 SpringCloudAlibaba 在服务治理上的技术选型差异。

这一篇是导引,只给地图和路线,不展开任何组件的技术细节------具体怎么引依赖、怎么改配置、监控页面上该看到什么,都放到对应章节里讲。

官方文档

总结

微服务不是"把项目拆小"这么简单,拆分本身只是起点,真正的成本在于拆完之后一大堆跨网络、跨进程的新问题。SpringCloud 的价值就在于它把这些问题的解法打成了标准件:注册中心管地址、负载均衡管分流、配置中心管参数、网关管入口、熔断管故障隔离。

学这一块的关键是先建立"问题 → 技术"的映射,遇到需求时能反应出该用哪个组件,而不是先记住一堆注解名字。示例工程 cloud-demo 会从头用到尾,建议自己动手跑一遍,两个 user-service 实例加一个注册中心,比看十遍原理图都直观。

版本别配错,Hoxton.SR10 配 SpringBoot 2.3.9.RELEASE,这是本模块全篇的基准。

相关推荐
Cc.Y1 小时前
Java零基础入门:集合框架:ArrayList 与 LinkedList —— 告别数组的“死板“,拥抱动态容器的“灵活
java·开发语言·python
panxianren9 小时前
Bun 1.4 的 bun test --parallel 将 4 秒的测试套件缩短到约 1 秒
java·javascript
sunshine22 girl10 小时前
Java学习七 Java 项目实战2-注册业务
java·学习
省钱兄--zs11 小时前
北京24小时自助健身房系统软件开发实战:从架构设计到部署指南
java·数据仓库·spring boot·小程序·需求分析
youdexiang11 小时前
Android录音软件时间关键词检索功能分析
java·人工智能
sunshine22 girl12 小时前
Java学习七 Java 项目实战1-项目创建和主页面搭建
java·开发语言·学习
code2cat12 小时前
Java进阶篇之AtomicStampedReference:引用回到原值,版本戳仍能记住变化
java·cas·并发编程·aba
泡茶喝茶写代码14 小时前
A股量化数据工程:从 REST 接口到策略信号(第 8 篇):成长能力因子:营收与利润增速
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口·股票数据api数据
\光辉岁月/14 小时前
7.javase-面向对象
java·开发语言