微服务架构设计实战:从单体到分布式

@曹桂英
2026-07-13 17:55
阅读 739

开篇:为什么要写这篇教程

大家好,我是老K,一个985毕业的全栈工程师,目前在掘金上写了不少入门教程。今天这篇关于微服务架构的文章,其实我酝酿了很久。

我当初学微服务的时候,真的是踩了无数的坑。那时候刚从学校出来,在公司里接手了一个单体项目,代码量已经超过十万行,每次部署都要半小时,改一个小bug可能导致整个系统崩溃。当时我就想:这玩意儿到底该怎么拆?

后来我花了一年时间,从理论到实践,把微服务这套东西彻底搞明白了。现在回头看,其实微服务并没有网上说的那么玄乎,核心思想就是"分而治之"。今天这篇文章,我就用最通俗的语言,带大家从零开始,一步步把一个单体应用改造成微服务架构。

为了让大家学得更系统,我推荐大家可以搭配几本书籍来学习,比如《微服务架构设计模式》和《Spring Cloud微服务实战》,这些都是我当初啃过的经典书籍,对理解微服务的设计思想非常有帮助。另外,现在GPT-4o这样的AI工具也能帮我们快速理解一些复杂概念,大家在学习过程中遇到不懂的,也可以借助GPT-4o来辅助学习。


第一部分:什么是微服务?先搞懂单体架构的痛点

1.1 单体架构长什么样

我们先来看一个典型的单体应用结构。假设我们有一个电商系统,所有的功能都写在一个项目里:

ecommerce-app/
├── src/
│   ├── user/           # 用户模块
│   │   ├── UserController.java
│   │   ├── UserService.java
│   │   └── UserMapper.java
│   ├── product/        # 商品模块
│   │   ├── ProductController.java
│   │   ├── ProductService.java
│   │   └── ProductMapper.java
│   ├── order/          # 订单模块
│   │   ├── OrderController.java
│   │   ├── OrderService.java
│   │   └── OrderMapper.java
│   └── payment/        # 支付模块
│       ├── PaymentController.java
│       ├── PaymentService.java
│       └── PaymentMapper.java
├── pom.xml
└── application.yml

这种结构的问题是什么?我给大家列一下:

问题 具体表现 影响
代码耦合严重 改一个模块可能影响其他模块 开发效率低
部署困难 每次修改都要全量部署 发布风险大
扩展性差 只能整体扩容,不能针对热点模块扩容 资源浪费
技术栈固定 所有模块必须用同一种语言/框架 技术选型受限
团队协作冲突 多人修改同一个代码库,经常冲突 沟通成本高

1.2 微服务的核心思想

微服务的核心思想其实就一句话:把一个大的单体应用拆分成多个小的、独立部署的服务,每个服务负责一个特定的业务功能。

用文字流程图来表示这个转变过程:

【单体架构】
┌─────────────────────────────────┐
│         电商系统(一个应用)       │
│  ┌─────┐ ┌──────┐ ┌─────┐ ┌──────┐ │
│  │用户 │ │ 商品 │ │订单 │ │ 支付 │ │
│  └─────┘ └──────┘ └─────┘ └──────┘ │
│         共享一个数据库               │
└─────────────────────────────────┘

          ↓ 拆分 ↓

【微服务架构】
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 用户服务  │ │ 商品服务  │ │ 订单服务  │ │ 支付服务  │
│ 独立部署  │ │ 独立部署  │ │ 独立部署  │ │ 独立部署  │
│ 独立数据库│ │ 独立数据库│ │ 独立数据库│ │ 独立数据库│
└──────────┘ └──────────┘ └──────────┘ └──────────┘
      ↕            ↕           ↕           ↕
        通过API网关统一对外提供服务

第二部分:环境准备

在开始实战之前,我们需要准备好开发环境。我当初学的时候,光环境搭建就花了两天,所以这部分我写得特别详细。

2.1 基础环境清单

工具 版本要求 用途
JDK 17+ Java运行环境
Maven 3.8+ 项目构建工具
MySQL 8.0+ 关系型数据库
Redis 6.0+ 缓存中间件
Docker 20.0+ 容器化部署
IDEA 2023+ 开发IDE
Postman 最新版 API测试工具

2.2 用Docker快速搭建中间件

我当初学的时候,装MySQL、Redis这些中间件折腾了好久,后来发现用Docker简直太方便了。这里给大家一个docker-compose.yml文件,一键启动所有中间件:

version: '3.8'
services:
  mysql:
    image: mysql:8.0
    container_name: microservice-mysql
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: ecommerce
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql

  redis:
    image: redis:6.0
    container_name: microservice-redis
    ports:
      - "6379:6379"

  nacos:
    image: nacos/nacos-server:v2.2.0
    container_name: microservice-nacos
    environment:
      MODE: standalone
    ports:
      - "8848:8848"

volumes:
  mysql-data:

启动命令:

docker-compose up -d

2.3 创建Maven父工程

微服务项目通常采用多模块的方式组织,我们先创建一个父工程来管理所有子模块:

<?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>ecommerce-microservice</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <modules>
        <module>common</module>
        <module>user-service</module>
        <module>product-service</module>
        <module>order-service</module>
        <module>gateway</module>
    </modules>

    <properties>
        <java.version>17</java.version>
        <spring-boot.version>3.1.0</spring-boot.version>
        <spring-cloud.version>2022.0.3</spring-cloud.version>
        <spring-cloud-alibaba.version>2022.0.0.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>

第三部分:核心概念讲解

在动手写代码之前,我们需要先理解微服务架构中的几个核心概念。我当初学的时候,这些概念搞得我头大,现在用最通俗的话给大家讲清楚。

3.1 服务注册与发现

通俗解释:想象一个大型商场,每个店铺(服务)开门后都要在商场管理处(注册中心)登记自己的位置和联系方式。顾客(其他服务)想找某个店铺时,先去管理处问一下,就能找到对应的店铺了。

在Spring Cloud生态中,我们常用的注册中心有Nacos、Eureka、Consul等。本教程使用Nacos。

3.2 API网关

通俗解释:API网关就像公司的前台,所有外来访客(客户端请求)都要先经过前台,前台负责判断访客要去哪个部门(路由到哪个服务),同时还能做身份验证(鉴权)、记录来访信息(日志)等。

3.3 服务间通信

通俗解释:微服务之间的通信,就像公司里不同部门之间的协作。有两种方式:

  • 同步通信(HTTP/RPC):像打电话,A部门打电话给B部门,等B部门处理完回复
  • 异步通信(消息队列):像发邮件,A部门发封邮件给B部门,不用等回复,B部门处理完会通知

3.4 配置中心

通俗解释:以前每个服务的配置都写在自己的配置文件里,就像每个员工自己记自己的密码。配置中心就像一个统一的密码管理器,所有服务的配置都集中管理,修改配置不用重启服务。


第四部分:实战项目——电商系统微服务化

接下来我们正式开始实战,把一个电商系统拆分成微服务架构。

4.1 第一步:创建公共模块(common)

公共模块用来存放所有服务共享的代码,比如通用工具类、统一返回结果等。

// common/src/main/java/com/example/common/Result.java
package com.example.common;

public class Result<T> {
    private Integer code;
    private String message;
    private T data;

    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage("success");
        result.setData(data);
        return result;
    }

    public static <T> Result<T> error(String message) {
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMessage(message);
        return result;
    }

    // getter和setter省略
    public Integer getCode() { return code; }
    public void setCode(Integer code) { this.code = code; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public T getData() { return data; }
    public void setData(T data) { this.data = data; }
}

common模块的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>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>ecommerce-microservice</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>common</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

4.2 第二步:创建用户服务(user-service)

用户服务负责用户的注册、登录、信息查询等功能。

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>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>ecommerce-microservice</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>user-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>

实体类:

// user-service/src/main/java/com/example/user/entity/User.java
package com.example.user.entity;

import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "t_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String username;

    @Column(nullable = false)
    private String password;

    private String email;
    private String phone;
}

Repository层:

// user-service/src/main/java/com/example/user/repository/UserRepository.java
package com.example.user.repository;

import com.example.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
    boolean existsByUsername(String username);
}

Service层:

// user-service/src/main/java/com/example/user/service/UserService.java
package com.example.user.service;

import com.example.user.entity.User;
import com.example.user.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User register(String username, String password, String email) {
        if (userRepository.existsByUsername(username)) {
            throw new RuntimeException("用户名已存在");
        }
        User user = new User();
        user.setUsername(username);
        user.setPassword(password); // 实际项目中需要加密
        user.setEmail(email);
        return userRepository.save(user);
    }

    public Optional<User> login(String username, String password) {
        return userRepository.findByUsername(username)
                .filter(user -> user.getPassword().equals(password));
    }

    public Optional<User> getUserById(Long id) {
        return userRepository.findById(id);
    }
}

Controller层:

// user-service/src/main/java/com/example/user/controller/UserController.java
package com.example.user.controller;

import com.example.common.Result;
import com.example.user.entity.User;
import com.example.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public Result<User> register(@RequestParam String username,
                                  @RequestParam String password,
                                  @RequestParam String email) {
        User user = userService.register(username, password, email);
        return Result.success(user);
    }

    @PostMapping("/login")
    public Result<User> login(@RequestParam String username,
                               @RequestParam String password) {
        return userService.login(username, password)
                .map(Result::success)
                .orElse(Result.error("用户名或密码错误"));
    }

    @GetMapping("/{id}")
    public Result<User> getUserById(@PathVariable Long id) {
        return userService.getUserById(id)
                .map(Result::success)
                .orElse(Result.error("用户不存在"));
    }
}

配置文件 application.yml:

server:
  port: 8081

spring:
  application:
    name: user-service
  datasource:
    url: jdbc:mysql://localhost:3306/user_db?createDatabaseIfNotExist=true
    username: root
    password: root123
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

cloud:
  nacos:
    discovery:
      server-addr: localhost:8848

4.3 第三步:创建商品服务(product-service)

商品服务的结构和用户服务类似,这里我精简一下代码。

实体类:

// product-service/src/main/java/com/example/product/entity/Product.java
package com.example.product.entity;

import jakarta.persistence.*;
import lombok.Data;
import java.math.BigDecimal;

@Data
@Entity
@Table(name = "t_product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    private String description;

    @Column(nullable = false)
    private BigDecimal price;

    @Column(nullable = false)
    private Integer stock;
}

Service层(包含扣减库存的逻辑):

// product-service/src/main/java/com/example/product/service/ProductService.java
package com.example.product.service;

import com.example.product.entity.Product;
import com.example.product.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public Optional<Product> getProductById(Long id) {
        return productRepository.findById(id);
    }

    @Transactional
    public boolean deductStock(Long productId, Integer quantity) {
        Product product = productRepository.findById(productId)
                .orElseThrow(() -> new RuntimeException("商品不存在"));

        if (product.getStock() < quantity) {
            throw new RuntimeException("库存不足");
        }

        product.setStock(product.getStock() - quantity);
        productRepository.save(product);
        return true;
    }
}

Controller层:

// product-service/src/main/java/com/example/product/controller/ProductController.java
package com.example.product.controller;

import com.example.common.Result;
import com.example.product.entity.Product;
import com.example.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @GetMapping("/{id}")
    public Result<Product> getProduct(@PathVariable Long id) {
        return productService.getProductById(id)
                .map(Result::success)
                .orElse(Result.error("商品不存在"));
    }

    @PostMapping("/{id}/deduct-stock")
    public Result<Boolean> deductStock(@PathVariable Long id,
                                        @RequestParam Integer quantity) {
        try {
            boolean success = productService.deductStock(id, quantity);
            return Result.success(success);
        } catch (RuntimeException e) {
            return Result.error(e.getMessage());
        }
    }
}

配置文件:

server:
  port: 8082

spring:
  application:
    name: product-service
  datasource:
    url: jdbc:mysql://localhost:3306/product_db?createDatabaseIfNotExist=true
    username: root
    password: root123
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update

cloud:
  nacos:
    discovery:
      server-addr: localhost:8848

4.4 第四步:创建订单服务(order-service)——服务间调用的关键

订单服务是最能体现微服务特点的服务,因为它需要调用用户服务和商品服务。这里我们用OpenFeign来实现服务间的同步调用。

添加OpenFeign依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

定义Feign客户端(调用用户服务):

// order-service/src/main/java/com/example/order/feign/UserFeignClient.java
package com.example.order.feign;

import com.example.common.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.Map;

@FeignClient(name = "user-service")
public interface UserFeignClient {

    @GetMapping("/api/user/{id}")
    Result<Map<String, Object>> getUserById(@PathVariable("id") Long id);
}

定义Feign客户端(调用商品服务):

// order-service/src/main/java/com/example/order/feign/ProductFeignClient.java
package com.example.order.feign;

import com.example.common.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "product-service")
public interface ProductFeignClient {

    @PostMapping("/api/product/{id}/deduct-stock")
    Result<Boolean> deductStock(@PathVariable("id") Long productId,
                                 @RequestParam("quantity") Integer quantity);
}

订单实体类:

// order-service/src/main/java/com/example/order/entity/Order.java
package com.example.order.entity;

import jakarta.persistence.*;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Data
@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private Long userId;

    @Column(nullable = false)
    private Long productId;

    @Column(nullable = false)
    private Integer quantity;

    @Column(nullable = false)
    private BigDecimal totalAmount;

    private String status; // CREATED, PAID, SHIPPED, COMPLETED, CANCELLED

    private LocalDateTime createTime;

    @PrePersist
    public void prePersist() {
        this.createTime = LocalDateTime.now();
        this.status = "CREATED";
    }
}

订单Service(核心业务逻辑):

// order-service/src/main/java/com/example/order/service/OrderService.java
package com.example.order.service;

import com.example.common.Result;
import com.example.order.entity.Order;
import com.example.order.feign.ProductFeignClient;
import com.example.order.feign.UserFeignClient;
import com.example.order.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Map;
import java.util.Optional;

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Transactional
    public Order createOrder(Long userId, Long productId, Integer quantity) {
        // 1. 调用用户服务,验证用户是否存在
        Result<Map<String, Object>> userResult = userFeignClient.getUserById(userId);
        if (userResult.getCode() != 200) {
            throw new RuntimeException("用户不存在");
        }

        // 2. 调用商品服务,扣减库存
        Result<Boolean> stockResult = productFeignClient.deductStock(productId, quantity);
        if (stockResult.getCode() != 200) {
            throw new RuntimeException("库存扣减失败:" + stockResult.getMessage());
        }

        // 3. 创建订单(这里简化处理,实际应该查询商品价格)
        Order order = new Order();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setQuantity(quantity);
        order.setTotalAmount(new BigDecimal("99.90").multiply(new BigDecimal(quantity)));

        return orderRepository.save(order);
    }

    public Optional<Order> getOrderById(Long id) {
        return orderRepository.findById(id);
    }
}

订单Controller:

// order-service/src/main/java/com/example/order/controller/OrderController.java
package com.example.order.controller;

import com.example.common.Result;
import com.example.order.entity.Order;
import com.example.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/create")
    public Result<Order> createOrder(@RequestParam Long userId,
                                      @RequestParam Long productId,
                                      @RequestParam Integer quantity) {
        try {
            Order order = orderService.createOrder(userId, productId, quantity);
            return Result.success(order);
        } catch (RuntimeException e) {
            return Result.error(e.getMessage());
        }
    }

    @GetMapping("/{id}")
    public Result<Order> getOrder(@PathVariable Long id) {
        return orderService.getOrderById(id)
                .map(Result::success)
                .orElse(Result.error("订单不存在"));
    }
}

启动类(别忘了加@EnableFeignClients):

// order-service/src/main/java/com/example/order/OrderServiceApplication.java
package com.example.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

4.5 第五步:创建API网关(gateway)

网关是所有请求的统一入口,负责路由转发、鉴权、限流等。

pom.xml关键依赖:

<dependencies>
    <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>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
</dependencies>

网关配置文件:

server:
  port: 9000

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**

        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/api/product/**

        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**

      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Origin

网关启动类:

// gateway/src/main/java/com/example/gateway/GatewayApplication.java
package com.example.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

4.6 启动与测试

按照以下顺序启动所有服务:

启动步骤:
1. 启动Docker中间件 → docker-compose up -d
2. 启动Nacos → 访问 http://localhost:8848/nacos 确认服务注册
3. 启动user-service → 端口8081
4. 启动product-service → 端口8082
5. 启动order-service → 端口8083
6. 启动gateway → 端口9000

测试接口:

# 注册用户
curl -X POST "http://localhost:9000/api/user/register?username=test&password=123&email=test@example.com"

# 创建订单(通过网关统一入口)
curl -X POST "http://localhost:9000/api/order/create?userId=1&productId=1&quantity=2"

第五部分:常见问题解答

我当初学微服务的时候,这些问题几乎全踩过,给大家提前避坑。

Q1:服务启动后在Nacos上看不到?

排查步骤:

  1. 检查spring.cloud.nacos.discovery.server-addr配置是否正确
  2. 检查Nacos服务是否正常运行
  3. 检查网络是否能连通Nacos
  4. 查看启动日志是否有报错信息

Q2:Feign调用报错"Load balancer does not have available server for client"?

这个问题通常是因为:

  • 目标服务没有成功注册到Nacos
  • 缺少spring-cloud-starter-loadbalancer依赖
  • 服务名拼写错误(注意大小写)

Q3:网关路由不生效?

检查以下几点:

  • predicates中的Path路径是否和实际请求路径匹配
  • uri中的服务名是否和Nacos中注册的一致
  • 网关是否引入了spring-cloud-starter-loadbalancer

Q4:微服务之间调用超时怎么办?

可以在配置文件中增加超时设置:

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            connectTimeout: 5000
            readTimeout: 10000

第六部分:学习建议与进阶路径

恭喜你完成了微服务的入门实战!但这只是开始,微服务的世界还有很多东西要学。根据我的经验,给大家规划一个学习路径:

初级阶段(当前)

  • ✅ 理解微服务基本概念
  • ✅ 能搭建简单的微服务项目
  • ✅ 掌握服务注册发现和Feign调用

中级阶段(下一步)

  • 学习Sentinel实现服务熔断和限流
  • 学习Seata实现分布式事务
  • 学习Spring Cloud Config或Nacos Config实现配置中心
  • 了解Docker和Kubernetes容器化部署

高级阶段(长期目标)

  • 深入学习分布式系统设计理论(CAP、BASE)
  • 掌握链路追踪(SkyWalking、Zipkin)
  • 学习消息队列(RabbitMQ、Kafka)实现异步通信
  • 掌握微服务的监控和运维(Prometheus + Grafana)

推荐书籍和资源

类型 推荐内容 适合阶段
书籍 《微服务架构设计模式》 入门到中级
书籍 《Spring Cloud微服务实战》 入门
书籍 《分布式系统概念与设计》 高级
工具 GPT-4o 全阶段辅助学习
社区 掘金、思否 全阶段

总结

这篇文章从零开始,带大家完成了一个电商系统的微服务化改造。我们学习了:

  1. 为什么要用微服务——单体架构的痛点
  2. 微服务的核心概念——注册发现、网关、服务通信、配置中心
  3. 实战项目搭建——用户服务、商品服务、订单服务、API网关
  4. 服务间调用——使用OpenFeign实现同步调用

我当初学的时候,花了大概三个月才把这些东西全部搞明白。所以大家不要着急,慢慢来,先把这篇文章的代码跑通,然后再逐步深入。

记住,微服务不是银弹,不要为了微服务而微服务。当你的项目足够大、团队足够多、业务足够复杂的时候,再考虑拆分。小项目用单体架构完全够了。

最后,大家在学习过程中遇到任何问题,欢迎在评论区留言讨论。如果觉得这篇文章对你有帮助,别忘了点赞收藏!我们下篇文章见!

评论 0

最热最新
暂无评论
@曹桂英Lv.1
0
影响力
0
文章
0
粉丝