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

代码收容所
2025-06-17 11:01
阅读 226

🧩 开篇:什么是微服务?为什么需要它?

🧩 开篇:什么是微服务?为什么需要它?

1. 什么是微服务?

想象一下,你在一个餐厅里做饭。一开始人少,你可以一个人掌勺、炒菜、洗碗。但随着客人越来越多,你一个人忙不过来。

怎么办?分工协作

于是你请来了厨师A专门负责炒菜,厨师B专门切菜,服务员负责上菜,清洁工负责洗碗。

这样,每个人只专注于自己的任务,效率提高了,也更容易扩展和维护。

在软件开发中,这种“分工协作”的思想就是——微服务架构

2. 微服务能做什么?

  • 模块化:一个大型系统被拆分成多个独立的小模块(服务)
  • 灵活部署:每个服务可以单独上线、更新
  • 横向扩展:某一个功能访问量大了,就只扩容那个服务
  • 技术自由度高:不同服务可以使用不同的编程语言或数据库

3. 微服务 vs 单体应用

项目 单体应用 微服务
部署方式 所有功能打包成一个程序 每个功能是一个独立服务
维护成本 初期低,后期高 初期高,后期易维护
技术栈 一般统一 可多样化
故障影响范围 一处出错可能导致整体崩溃 单个服务出错不影响其他

🔧 环境准备:搭建你的微服务开发环境

微服务架构示意图-1

🔧 环境准备:搭建你的微服务开发环境

我们以 Java + Spring Boot + Maven + Docker 为例来搭建环境。

💡提示:所有工具都推荐使用最新稳定版,确保兼容性

第一步:安装 JDK

下载地址:https://adoptium.net

安装后检查版本:

java -version
javac -version

第二步:安装 IntelliJ IDEA(IDE)

免费社区版即可。

下载地址:https://www.jetbrains.com/idea/download/

启动后安装插件:

  • Spring Boot
  • Lombok
  • Docker Integration

第三步:安装 Maven

Maven 是用于项目构建的工具。

Windows 用户可以使用 Chocolatey 安装:

choco install maven

Mac 使用 Homebrew:

brew install maven

验证安装:

mvn --version

第四步:安装 Docker

Docker 可以帮助我们快速运行微服务并做容器化部署。

官网下载链接:https://www.docker.com/products/docker-desktop/

安装完成后运行:

docker info

显示信息说明安装成功。


📚 核心概念讲解:通俗易懂的方式理解微服务关键概念

📚 核心概念讲解:通俗易懂的方式理解微服务关键概念

1. 服务拆分(Service Split)

把一个大系统切成多个小模块,每个模块完成一个小功能。

例如:

  • 用户服务:处理注册、登录等
  • 订单服务:处理下单、支付
  • 商品服务:处理商品展示、库存

2. API 网关(API Gateway)

就像餐厅的服务员,负责接待顾客,并把订单发给对应的厨房。

作用:

  • 请求路由
  • 身份验证
  • 流量控制

常用技术:Spring Cloud Gateway、Zuul、Nginx

3. 注册中心(Service Registry)

相当于员工名单,记录有哪些厨师在岗。

每个服务启动时都要去“打卡”注册自己。

常用技术:Eureka、Consul、Nacos

4. 远程调用(Remote Call)

两个服务之间互相通信的一种方式。

比如:用户下单 → 订单服务要向库存服务请求库存是否足够。

常用技术:REST、Feign、Dubbo、gRPC

5. 配置中心(Config Center)

类似于餐厅的菜单管理后台,菜品价格变动只需要改一次,不用通知每个厨师。

常用技术:Spring Cloud Config、Apollo、Nacos


🛠 实战项目:创建两个简单微服务并进行远程调用

我们将做一个简单的项目:

  • 创建两个服务:user-serviceorder-service
  • user-service 提供用户信息接口
  • order-service 通过 Feign 调用 user-service 获取用户信息

步骤一:创建 Spring Boot 工程

使用 Spring Initializr 创建两个项目:

user-service

  • Name: UserServiceApplication
  • Dependencies:
    • Spring Web
    • Spring Boot DevTools
    • Lombok
    • Eureka Client

order-service

  • Name: OrderServiceApplication
  • Dependencies:
    • Spring Web
    • Spring Boot DevTools
    • Lombok
    • Eureka Client
    • OpenFeign

生成后分别导入 IntelliJ IDEA

步骤二:编写 user-service

启动类:UserServiceApplication.java

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

配置 application.yml

server:
  port: 8081

spring:
  application:
    name: user-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

控制器 UserRestController.java

@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserRestController {
    private final UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        return ResponseEntity.ok(userService.getUserById(id));
    }
}

// User.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String username;
}

步骤三:编写 order-service

启动类:OrderServiceApplication.java

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

配置 application.yml

server:
  port: 8082

spring:
  application:
    name: order-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

创建 Feign 接口:UserServiceClient.java

@FeignClient(name = "user-service")
public interface UserServiceClient {
    @GetMapping("/users/{id}")
    User getUserById(@PathVariable("id") Long id);
}

控制器 OrderRestController.java

@RestController
@RequestMapping("/orders")
@RequiredArgsConstructor
public class OrderRestController {
    private final UserServiceClient userServiceClient;

    @GetMapping("/user/{id}")
    public ResponseEntity<User> getOrderAndUser(@PathVariable Long id) {
        User user = userServiceClient.getUserById(id);
        return ResponseEntity.ok(user);
    }
}

微服务架构示意图-2

步骤四:添加 Eureka Server

新建一个 EurekaServerApplication 并配置为注册中心:

启动类:

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

application.yml:

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

现在项目结构如下:

project/
├── eureka-server
├── user-service
└── order-service

启动顺序

  1. 先运行 eureka-server(默认端口8761)
  2. 再运行 user-service(端口8081)
  3. 最后运行 order-service(端口8082)

浏览器访问:

http://localhost:8082/orders/user/1

你应该能看到返回的 User JSON 数据。


❓常见问题解答

Q1:为什么我的服务注册不到 Eureka?

  • 确保 Eureka Server 已经启动
  • 查看服务中的 application.yml 是否正确配置了 defaultZone
  • 检查服务是否有开启 EurekaClient 注解:@EnableEurekaClient

Q2:Feign 调用失败怎么办?

  • 检查 Feign 接口的 URL 是否与 user-service 的一致
  • 使用 Postman 或 curl 测试 user-service 是否正常返回数据
  • 加入日志:Feign 默认不会打印详细日志,请在配置文件中启用日志输出
logging:
  level:
    com.example.client.UserServiceClient: DEBUG

Q3:服务名字对不上怎么办?

确保服务名称大小写一致,并且在 Eureka 中显示的是小写。Spring Cloud 默认会转换服务名为小写。


📚 学习建议:下一步该学什么?

恭喜你完成了第一个微服务项目!

接下来的学习路线建议如下:

  1. 服务熔断与降级
    • 学习 Hystrix、Sentinel、Resilience4j
  2. 负载均衡
    • 了解 Ribbon、Spring Cloud LoadBalancer
  3. 服务网关
    • 深入学习 Spring Cloud Gateway 或 Nginx
  4. 配置中心
    • 学习 Spring Cloud Config 或 Nacos 配置管理
  5. 链路追踪
    • Sleuth + Zipkin 实现请求链路追踪
  6. 消息队列
    • 学习 RabbitMQ / Kafka / RocketMQ 做异步通信
  7. 容器化部署
    • Docker + Kubernetes 实现自动化部署

👨‍🏫 小贴士:微服务不是万能药。如果你只是开发一个小型项目,可能更适合先使用单体架构。学会权衡是成为优秀架构师的关键!


✅ 总结

在这篇文章中,我们一步一步从零开始搭建了一个简单的微服务项目:

✅ 解释了微服务的基本概念
✅ 配置了完整的开发环境
✅ 实现了两个微服务之间的远程调用
✅ 解答了新手容易遇到的问题
✅ 给出了进一步学习的路线图

如果你按照文章操作下来,已经具备进入实际项目开发的能力了!继续加油💪,欢迎关注我,获取更多进阶内容!


🎯下一篇文章预告:《深入浅出 Spring Cloud Alibaba:Nacos + Sentinel 实战解析》敬请期待!

如需源码示例,可在评论区留言【代码】获取 GitHub 仓库地址。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝