微服务架构设计:基于Java、Spring Boot与Spring Cloud Alibaba

291 阅读6分钟

一、架构设计

微服务架构是一种将大型单体应用拆分为一系列小型、自治服务的策略,每个服务运行在其独立的进程中,并通过轻量级通信协议(如RESTful API)相互通信。此架构促进了开发团队的敏捷性、服务的独立部署和扩展,以及技术栈的多样性。

本设计将采用Java作为编程语言,Spring Boot作为开发框架,以及Spring Cloud Alibaba进行服务治理。基于Spring Cloud Alibaba提供了一系列微服务解决方案,包括服务注册与发现、配置管理、服务调用、熔断降级、服务网关等。

二、技术选型

  • 编程语言:Java
  • 框架:Spring Boot
  • 服务治理:Spring Cloud Alibaba

三、微服务设计

服务划分

根据业务需求,我们将设计一个电商系统的微服务架构。为了简化设计,我们将重点实现用户服务(UserService)和订单服务(OrderService)两个微服务。

API设计

每个微服务将提供RESTful API接口,用于与其他微服务进行通信。我们将使用Swagger或Springfox生成API文档,以确保API的易用性和可维护性。

技术逻辑与实现过程

服务注册与发现

使用Nacos作为服务注册中心。每个微服务在启动时都会向Nacos注册自己的信息(如服务名、IP地址、端口等),以便其他微服务可以通过Nacos来查找和调用。

实现步骤:
  1. 部署并启动Nacos服务注册中心

    • 下载并安装Nacos。
    • 启动Nacos服务。
  2. 在用户服务和订单服务的Spring Boot项目中引入Spring Cloud Alibaba Nacos依赖

    • 创建一个父POM文件来管理所有子模块的公共依赖和版本。
    <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-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>pom</packaging>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-boot.version>2.7.5</spring-boot.version>
            <spring-cloud-alibaba.version>2021.1.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>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>
    
        <modules>
            <module>user-service</module>
            <module>order-service</module>
            <module>gateway</module>
        </modules>
    </project>
    
    • 每个子模块(如用户服务、订单服务、网关)的pom.xml应该继承自父POM,并添加特定于该模块的依赖。
    <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-parent</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>user-service</artifactId>
    
        <dependencies>
            <!-- Spring Boot Starter Web -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- Spring Cloud Alibaba Nacos Discovery -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!-- Spring Cloud OpenFeign -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <!-- Spring Cloud Alibaba Sentinel -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
        </dependencies>
    </project>
    
  3. 配置Nacos客户端

    • application.yml中配置Nacos客户端,包括服务名、Nacos服务器地址等。
    server:
      port: 8081 # 服务端口
    
    spring:
      application:
        name: user-service # 服务名称
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848 # Nacos服务地址
    
    feign:
      client:
        config:
          default:
            connectTimeout: 5000 # 连接超时时间
            readTimeout: 5000 # 读取超时时间
    
    sentinel:
      transport:
        dashboard: localhost:8080 # Sentinel 控制台地址
    
  4. 启动微服务

    • 启动微服务,它们将自动向Nacos注册中心注册。

服务调用

使用OpenFeign进行服务之间的调用。OpenFeign是一个声明式的Web服务客户端,它使得写HTTP客户端变得更简单。

实现步骤:
  1. 在用户服务和订单服务的Spring Boot项目中引入Spring Cloud OpenFeign依赖

    • 已在上述pom.xml中添加。
  2. 配置OpenFeign

    • application.yml中配置OpenFeign,包括服务名、超时时间等。
  3. 创建一个Feign客户端接口,用于调用其他微服务提供的API。

    package com.example.orderservice.feign;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    @FeignClient("user-service")
    public interface UserServiceClient {
        @GetMapping("/users/{userId}")
        String getUserInfo(@PathVariable("userId") String userId);
    }
    
  4. 在需要使用服务调用的地方注入Feign客户端接口,并调用其方法

    package com.example.orderservice.controller;
    
    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.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/orders")
    public class OrderController {
    
        @Autowired
        private UserServiceClient userServiceClient;
    
        @GetMapping("/{orderId}")
        public String getOrderInfo(@PathVariable("orderId") String orderId) {
            String userInfo = userServiceClient.getUserInfo("123");
            return "Order Info for Order ID: " + orderId + ", User Info: " + userInfo;
        }
    }
    

服务熔断与降级

使用Sentinel进行服务的熔断与降级。Sentinel是面向分布式服务架构的高可用防护组件,主要用于流量控制、熔断降级、系统负载保护等。

实现步骤:
  1. 在用户服务和订单服务的Spring Boot项目中引入Spring Cloud Alibaba Sentinel依赖

    • 已在上述pom.xml中添加。
  2. 配置Sentinel

    • application.yml中配置Sentinel,包括熔断规则、降级策略等。
    1. 熔断规则配置
     circuitbreaker:
       sentinel:
         enabled: true
         rules:
           - resource: getUserInfo # 资源名称,对应API方法
             count: 5 # 触发熔断的异常数
             timeWindow: 10 # 熔断持续时间(秒)
             minRequestAmount: 10 # 最小请求数
             statIntervalMs: 1000 # 统计时间窗口(毫秒)
             slowRequestRatioThreshold: 0.5 # 慢请求比例阈值
    
    1. 降级策略配置
     degrade:
       sentinel:
         rules:
           - resource: getUserInfo # 资源名称,对应API方法
             count: 5 # 降级阈值
             timeWindow: 10 # 降级持续时间(秒)
             grade: 1 # 降级策略类型(0: 异常比例, 1: 异常数)
             minRequestAmount: 10 # 最小请求数
             statIntervalMs: 1000 # 统计时间窗口(毫秒)
    
  3. 在需要熔断与降级的Feign客户端接口方法上添加@SentinelResource注解,并指定熔断后的回退方法

    package com.example.orderservice.feign;
    
    import com.alibaba.csp.sentinel.annotation.SentinelResource;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    @FeignClient("user-service")
    public interface UserServiceClient {
         @SentinelResource(value = "getUserInfo", blockHandler = "handleBlock", fallback = "handleFallback")
         @GetMapping("/users/{userId}")
         public String getUserInfo(@PathVariable("userId") String userId) {
             return "User Info for User ID: " + userId;
         }
         public String handleBlock(@PathVariable("userId") String userId, BlockException ex) {
             return "Blocked by Sentinel: " + ex.getMessage();
         }
         public String handleFallback(@PathVariable("userId") String userId) {
             return "Fallback: User Info for User ID: " + userId;
         }
    }
    
    解释
    • @SentinelResource:标记需要Sentinel保护的方法。
      • value:资源名称,对应API方法。
      • blockHandler:当请求被限流或熔断时调用的处理方法。
      • fallback:当请求失败时调用的回退方法。
    • handleBlock:处理限流或熔断的回调方法。
    • handleFallback:处理请求失败的回退方法。

服务网关

使用Gateway作为服务网关,用于路由转发、过滤、鉴权等功能。

实现步骤:
  1. 部署并启动Gateway服务网关

    • 创建一个新的Spring Boot项目作为网关服务。
  2. 在Gateway项目的Spring Boot中引入Spring Cloud Gateway依赖

    • pom.xml中添加依赖。
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    
  3. 配置Gateway的路由规则,将不同的请求路径映射到对应的服务上。

    server:
      port: 8000 # 网关服务端口
    
    spring:
      application:
        name: gateway-service # 服务名称
      cloud:
        gateway:
          routes:
            - id: user-service
              uri: lb://user-service
              predicates:
                - Path=/users/**
            - id: order-service
              uri: lb://order-service
              predicates:
                - Path=/orders/**
    
  4. (可选)配置过滤器、鉴权等功能

四、测试与验证

  • 单元测试:使用JUnit等工具对服务进行单元测试,确保服务的功能正确。
  • 集成测试:通过模拟调用和响应,验证服务之间的调用关系和熔断降级机制是否正常工作。
  • 性能测试:使用JMeter等工具对服务进行性能测试,确保服务在高并发下能够正常运行。

五、总结

本设计通过Java、Spring Boot和Spring Cloud Alibaba实现了一个微服务架构,包括用户服务和订单服务两个微服务。通过Nacos实现服务注册与发现,通过OpenFeign实现服务调用,通过Sentinel实现服务熔断与降级,通过Gateway实现服务网关。该设计提高了系统的灵活性、可扩展性和可维护性,满足了快速变化的业务需求。