本文面向零基础读者,用通俗的语言讲清楚:什么是微服务、为什么用它、怎么上手。


一、从一个餐厅说起

想象你开了一家餐厅。

单体架构就像一个大排档:一个厨师负责所有事 — 炒菜、凉菜、烧烤、甜品、收银全是一个人。生意少的时候还行,一旦客满,厨师忙不过来,而且万一他生病了,整个店关门。

微服务架构就像一个专业餐厅:后厨分成热菜组、凉菜组、烧烤组、甜品组,前台有专门的服务员、收银员。每组各司其职,互不干扰。菜量大了可以给热菜组加人,烧烤组忙不过来了就多招一个烧烤师傅。

这就是微服务的核心思想:把一个大系统拆成多个独立的小服务,每个服务专注做一件事。


二、单体 vs 微服务:一张表看懂

对比维度单体架构微服务架构
部署打一个包,一次部署每个服务独立打包部署
扩展整体扩缩,浪费资源按需扩缩,哪个服务忙就扩哪个
开发所有人在一个代码仓库每个服务独立仓库、独立团队
故障隔离一个模块挂了,整个系统可能崩一个服务挂了,其他不受影响
技术选型一套技术栈用到死每个服务可以选最合适的语言/框架
上手难度简单,适合小项目复杂,运维成本高

三、微服务长什么样?一张图看懂

​

四、核心概念逐个讲

4.1 服务拆分

怎么把一个系统拆成微服务?常见思路是按业务领域拆分:

  • 电商系统 → 用户服务、商品服务、订单服务、支付服务、物流服务

  • 博客系统 → 用户服务、文章服务、评论服务、搜索服务

拆分原则:高内聚、低耦合。一个服务内部的数据和方法紧密相关,服务之间尽量少依赖。

4.2 API 网关 — "前台"

所有客户端请求先到网关,由网关转发到对应的服务。

作用:统一入口、身份认证、限流、日志、路由。

常用方案:Spring Cloud Gateway、Kong、Nginx + Lua。

4.3 服务注册与发现 — "通讯录"

几十个服务之间怎么找到对方?需要一个通讯录:

  • 注册:每个服务启动时把自己的地址(IP + 端口)报到注册中心

  • 发现:服务 A 要调服务 B 时,先去注册中心查到 B 的地址

常用方案:Nacos(阿里)、Consul、Eureka(已停更)。

4.4 远程调用 — "怎么交流"

微服务之间需要互相调用,常见方式:

方式说明常用框架
HTTP/REST最通用,同步调用Spring Cloud OpenFeign
RPC高性能,像调本地方法Dubbo、gRPC
消息队列异步解耦RabbitMQ、Kafka、RocketMQ

4.5 配置中心 — "统一管理配置"

每个服务都有自己的配置文件(数据库地址、端口号等),几十个服务散落各处根本管不过来。

配置中心把所有配置统一管理,改了配置不用重启服务就能生效。

常用方案:Nacos Config、Apollo(携程开源)。

4.6 服务熔断与降级 — "保险丝"

服务 A 调用服务 B,B 挂了,A 还在不停地重试,最终连 A 也被拖垮 — 这叫雪崩效应。

熔断:B 不可用时,A 直接不再调用 B,快速失败,就像保险丝熔断。

降级:B 不可用时,A 返回一个兜底结果,保证核心流程能走通。

常用方案:Sentinel(阿里)、Hystrix(已停更)。


五、关键词速查表

以下是你学习微服务时一定会反复遇到的术语,每个都用一句话讲清楚。

基础概念

关键词一句话解释
微服务 Microservice把一个大系统按业务拆成多个独立的小服务,各自开发、部署、升级
单体 Monolith所有功能写在一个项目里,打成一个包部署
服务 Service独立运行、对外提供特定功能的一个程序,比如「用户服务」只管用户登录注册
实例 Instance同一个服务可以启动多份,每一份就是一个实例,用来分担流量
集群 Cluster同一个服务的多个实例组成一个集群,对外像一个整体
节点 Node集群中的一台机器或一个容器

通信相关

关键词一句话解释
REST / RESTful一种用 HTTP 协议设计接口的风格,URL 表示资源,GET/POST/PUT/DELETE 表示操作
RPC远程过程调用,像调用本地方法一样调用远程服务,性能比 HTTP 高
序列化把对象转成字节流,方便网络上传输。常见:JSON、Protobuf
负载均衡 Load Balance把请求分摊到多个实例上,避免一个被打爆。网关自带这个能力
同步调用A 调用 B,A 要等 B 返回结果才能继续。类似打电话
异步调用A 给 B 发个消息就去干别的了,不等结果。类似发微信

中间件与基础设施

关键词一句话解释
注册中心 Nacos服务的「黄页电话本」,记录哪些服务在哪些地址上运行着
配置中心 Apollo / Nacos把各服务的配置文件统一放在一个地方管理,改配置不用重启
API 网关 Gateway系统唯一的入口,负责路由、认证、限流,请求先过它再转发到具体服务
消息队列 MQ异步通信的中间件,发消息的不用等接收方处理完。RabbitMQ、Kafka、RocketMQ
Sentinel阿里的流量防卫兵,做限流、熔断、降级
Seata阿里的分布式事务方案,解决跨服务数据一致性问题
SkyWalking链路追踪工具,一个请求跨了多少个服务、每个耗时多少一目了然

部署与运维

关键词一句话解释
Docker把应用和环境打包成镜像,到处都能一样地运行。"在我机器上能跑啊"的终结者
Docker Compose一条命令启动多个 Docker 容器,本地开发必备
Kubernetes (K8s)容器的编排调度平台,管理成百上千个容器的部署、扩缩容、故障恢复
容器 ContainerDocker 跑起来的一个隔离环境,类似一个超轻量的虚拟机
镜像 Image容器的模板,就像操作系统的安装盘。Dockerfile 描述怎么构建镜像
CI/CD持续集成 / 持续部署:代码提交 → 自动构建 → 自动测试 → 自动部署到服务器
DevOps开发 + 运维一体化,团队既要写代码也要管部署,打破"开发写完扔给运维"的墙
敏捷开发 Agile把大需求拆成小迭代,每 1-2 周交付一部分,快速试错。微服务天然适配这种模式

六、手把手跑通一个微服务项目

用 Spring Cloud Alibaba 全家桶,搭一个最简单的「用户服务 → 订单服务」调用链。

6.1 环境准备

工具版本要求作用
JDK17+Java 运行环境
Maven3.8+项目构建
Nacos2.x服务注册 + 配置中心
IDEA社区版即可写代码

6.2 启动 Nacos

Nacos 是第一个要启动的东西,所有服务都依赖它。

# 1. 下载 Nacos(Windows 用 zip,Mac/Linux 用 tar.gz)
# 下载地址:https://github.com/alibaba/nacos/releases
​
# 2. 解压后进入 bin 目录,启动(单机模式)
# Windows:
startup.cmd -m standalone
​
# Mac / Linux:
sh startup.sh -m standalone
​
# 3. 浏览器访问 http://localhost:8848/nacos
# 账号 nacos,密码 nacos
# 看到控制台页面就说明启动成功了

6.3 创建父工程

先建一个空的 Maven 项目作为父工程,统一管理依赖版本。

pom.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>com.example</groupId>
    <artifactId>microservice-demo</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
​
    <properties>
        <java.version>17</java.version>
        <spring-boot.version>3.2.0</spring-boot.version>
        <spring-cloud.version>2023.0.0</spring-cloud.version>
        <spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
    </properties>
​
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

6.4 创建用户服务 user-service

在父工程下新建 Module:user-service。

pom.xml(user-service):

<?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">
    <parent>
        <groupId>com.example</groupId>
        <artifactId>microservice-demo</artifactId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
​
    <artifactId>user-service</artifactId>
​
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Nacos 服务注册发现 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>

application.yml(user-service):

server:
  port: 8081
​
spring:
  application:
    name: user-service    # 服务名,注册到 Nacos 时用的就是这个
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848   # Nacos 地址

启动类 UserServiceApplication.java:

package com.example.user;
​
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
@SpringBootApplication
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

写一个接口 UserController.java:

package com.example.user.controller;
​
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
public class UserController {
​
    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id) {
        return "用户-" + id + "(来自 user-service)";
    }
}

6.5 创建订单服务 order-service

同样新建 Module:order-service。这次它要调用 user-service。

pom.xml(order-service):

<?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">
    <parent>
        <groupId>com.example</groupId>
        <artifactId>microservice-demo</artifactId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
​
    <artifactId>order-service</artifactId>
​
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- OpenFeign:声明式 HTTP 调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- Spring Cloud LoadBalancer:负载均衡 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>
</project>

application.yml(order-service):

server:
  port: 8082
​
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

启动类 OrderServiceApplication.java(注意加上 @EnableFeignClients):

package com.example.order;
​
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
​
@SpringBootApplication
@EnableFeignClients   // 开启 Feign 远程调用
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

Feign 接口 UserClient.java(声明要调哪个服务的什么接口):

package com.example.order.client;
​
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
​
// value 的值就是目标服务在 Nacos 里注册的名字
@FeignClient(value = "user-service")
public interface UserClient {
​
    @GetMapping("/user/{id}")
    String getUser(@PathVariable("id") Long id);
}

订单接口 OrderController.java(调用 user-service):

package com.example.order.controller;
​
import com.example.order.client.UserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
public class OrderController {
​
    @Autowired
    private UserClient userClient;
​
    @GetMapping("/order/{orderId}")
    public String getOrder(@PathVariable Long orderId) {
        // 远程调用 user-service
        String userInfo = userClient.getUser(1L);
        return "订单-" + orderId + ",关联用户信息:" + userInfo;
    }
}

6.6 启动与验证

按顺序启动:

1. Nacos(已经在跑了)
2. UserServiceApplication(user-service,启动后去 Nacos 控制台能看到它)
3. OrderServiceApplication(order-service,同样会注册到 Nacos)

验证调用链:浏览器访问 http://localhost:8082/order/100

你应该看到:

订单-100,关联用户信息:用户-1(来自 user-service)

发生了什么?

  1. 浏览器请求 order-service 的 /order/100

  2. order-service 通过 Feign 去 Nacos 查到 user-service 的地址

  3. Feign 发 HTTP 请求到 user-service 的 /user/1

  4. user-service 返回字符串

  5. order-service 拼上自己的内容,返回给浏览器

这就是一次最基础的微服务远程调用。

6.7 完整项目结构

microservice-demo/
├── pom.xml                          # 父工程
├── user-service/
│   ├── pom.xml
│   └── src/main/
│       ├── java/com/example/user/
│       │   ├── UserServiceApplication.java
│       │   └── controller/
│       │       └── UserController.java
│       └── resources/
│           └── application.yml
└── order-service/
    ├── pom.xml
    └── src/main/
        ├── java/com/example/order/
        │   ├── OrderServiceApplication.java
        │   ├── controller/
        │   │   └── OrderController.java
        │   └── client/
        │       └── UserClient.java
        └── resources/
            └── application.yml

七、微服务不是银弹:什么时候别用?

微服务不是越微越好,以下情况建议老老实实用单体:

  • 🚫 团队不到 5 个人

  • 🚫 项目刚起步,需求还不明确

  • 🚫 业务逻辑简单,没有高并发压力

  • 🚫 团队没有 DevOps 经验和容器化基础

Martin Fowler 的建议:先单体,等真正遇到单体的瓶颈了再拆。不要为了微服务而微服务。


八、推荐学习路线

第1步:理解概念 + 关键词(本文第五、六节)
    ↓
第2步:跟着第六节跑通第一个微服务调用链
    ↓
第3步:学 Spring Boot(微服务的基础,一个服务就是一个 Spring Boot 项目)
    ↓
第4步:深入 Nacos(服务注册 + 配置中心二合一,阿里出品)
    ↓
第5步:深入 OpenFeign(服务间 HTTP 调用)
    ↓
第6步:学 Sentinel(熔断降级)
    ↓
第7步:学 Gateway(API 网关)
    ↓
第8步:学 Docker + 基本部署
    ↓
第9步:做一个小项目,比如拆一个单体电商系统

写在最后

微服务是一门实践性很强的技术。概念看再多,不如亲手拆一个项目。建议用 Spring Cloud Alibaba 全家桶入门,国内生态最完善,文档也是中文的,对新手友好。

有问题欢迎在评论区交流,一起进步 🚀

更多推荐