Spring Cloud Alibaba案例

wen java案例 2

本文目录导读:

Spring Cloud Alibaba案例

  1. 项目架构概览
  2. 父工程 pom.xml
  3. common-api 模块
  4. user-service(用户服务)
  5. order-service(订单服务)
  6. gateway-service(网关服务)
  7. Nacos 配置中心配置
  8. 测试流程
  9. Sentinel 流量控制配置
  10. 扩展建议

下面是一个完整的 Spring Cloud Alibaba 微服务实战案例,涵盖服务注册与发现(Nacos)、配置中心(Nacos Config)、远程调用(OpenFeign)、流量控制(Sentinel)和网关(Gateway)。


项目架构概览

spring-cloud-alibaba-demo
├── pom.xml (父工程)
├── user-service (用户服务,端口8081)
├── order-service (订单服务,端口8082)
├── gateway-service (网关服务,端口8080)
└── common-api (公共API模块)

技术栈:Spring Boot 2.7 + Spring Cloud Alibaba 2021.0.5.0 + Nacos 2.2 + Sentinel 1.8.6


父工程 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 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-cloud-alibaba-demo</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <modules>
        <module>common-api</module>
        <module>user-service</module>
        <module>order-service</module>
        <module>gateway-service</module>
    </modules>
    <properties>
        <java.version>11</java.version>
        <spring-cloud.version>2021.0.5</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- Spring Cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud Alibaba -->
            <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>

common-api 模块

定义公共实体和DTO,供各服务复用。

User.java:

package com.example.common.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class User implements Serializable {
    private Long id;
    private String username;
    private String email;
}

Order.java:

package com.example.common.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class Order implements Serializable {
    private Long id;
    private Long userId;
    private String productName;
    private BigDecimal amount;
    private LocalDateTime createTime;
}

Result.java(统一响应体):

package com.example.common.result;
import lombok.Data;
import java.io.Serializable;
@Data
public class Result<T> implements Serializable {
    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(Integer code, String message) {
        Result<T> result = new Result<>();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
}

user-service(用户服务)

pom.xml

<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>
    <!-- Nacos 配置中心 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <!-- 公共模块 -->
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common-api</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

bootstrap.yml

spring:
  application:
    name: user-service
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        namespace: public
        group: DEFAULT_GROUP

application.yml

server:
  port: 8081
# 从 Nacos 配置中心读取的配置
user:
  default-role: USER

启动类和控制器

UserServiceApplication.java:

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

UserController.java:

package com.example.user.controller;
import com.example.common.entity.User;
import com.example.common.result.Result;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/user")
public class UserController {
    // 模拟数据库
    private static final Map<Long, User> USER_DB = new HashMap<>() {{
        put(1L, new User(1L, "张三", "zhangsan@example.com"));
        put(2L, new User(2L, "李四", "lisi@example.com"));
    }};
    @GetMapping("/{id}")
    public Result<User> getUserById(@PathVariable Long id) {
        return Result.success(USER_DB.get(id));
    }
    @GetMapping("/list")
    public Result<Map<Long, User>> listUsers() {
        return Result.success(USER_DB);
    }
}

order-service(订单服务)

pom.xml

<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>
    <!-- Nacos 配置中心 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <!-- OpenFeign 远程调用 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!-- Sentinel 流量控制 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!-- 公共模块 -->
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common-api</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

bootstrap.yml

spring:
  application:
    name: order-service
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080  # Sentinel 控制台地址
        port: 8719

application.yml

server:
  port: 8082

Feign 客户端

UserFeignClient.java:

package com.example.order.feign;
import com.example.common.entity.User;
import com.example.common.result.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service", fallback = UserFeignFallback.class)
public interface UserFeignClient {
    @GetMapping("/api/user/{id}")
    Result<User> getUserById(@PathVariable Long id);
}

UserFeignFallback.java(熔断降级):

package com.example.order.feign;
import com.example.common.entity.User;
import com.example.common.result.Result;
import org.springframework.stereotype.Component;
@Component
public class UserFeignFallback implements UserFeignClient {
    @Override
    public Result<User> getUserById(Long id) {
        return Result.error(500, "服务降级:用户服务不可用");
    }
}

启动类和控制器

OrderServiceApplication.java:

package com.example.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

OrderController.java:

package com.example.order.controller;
import com.example.common.entity.Order;
import com.example.common.entity.User;
import com.example.common.result.Result;
import com.example.order.feign.UserFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/order")
public class OrderController {
    @Autowired
    private UserFeignClient userFeignClient;
    private static final Map<Long, Order> ORDER_DB = new HashMap<>() {{
        put(1L, new Order(1L, 1L, "iPhone 15", new BigDecimal("5999.00"), LocalDateTime.now()));
        put(2L, new Order(2L, 2L, "MacBook Pro", new BigDecimal("12999.00"), LocalDateTime.now()));
    }};
    @GetMapping("/{id}")
    public Result<Map<String, Object>> getOrderWithUser(@PathVariable Long id) {
        Order order = ORDER_DB.get(id);
        if (order == null) {
            return Result.error(404, "订单不存在");
        }
        // 通过 Feign 调用用户服务
        Result<User> userResult = userFeignClient.getUserById(order.getUserId());
        return Result.success(Map.of(
            "order", order,
            "user", userResult.getData()
        ));
    }
    @GetMapping("/list")
    public Result<Map<Long, Order>> listOrders() {
        return Result.success(ORDER_DB);
    }
}

gateway-service(网关服务)

pom.xml

<dependencies>
    <!-- 网关 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- Nacos 注册中心 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- Nacos 配置中心 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

application.yml

server:
  port: 8080
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true  # 启用服务发现路由
          lower-case-service-id: true
      routes:
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
        - id: order-service-route
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

启动类

GatewayServiceApplication.java:

package com.example.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceApplication.class, args);
    }
}

Nacos 配置中心配置

在 Nacos 控制台创建配置文件:

Data ID: order-service.yaml

# order-service 的动态配置
order:
  max-amount: 10000
  discount: 0.9

Data ID: user-service.yaml

# user-service 的动态配置
user:
  default-role: ADMIN

测试流程

启动基础设施

# 启动 Nacos
cd nacos/bin
./startup.sh -m standalone
# 启动 Sentinel 控制台(可选)
java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 -jar sentinel-dashboard-1.8.6.jar

启动服务

# 依次启动
mvn spring-boot:run -pl user-service
mvn spring-boot:run -pl order-service
mvn spring-boot:run -pl gateway-service

测试接口

通过网关调用订单服务

curl http://localhost:8080/order/api/order/1

直接调用订单服务

curl http://localhost:8082/api/order/1

通过网关调用用户服务

curl http://localhost:8080/user/api/user/1

测试降级(停止 user-service 后再次调用):

curl http://localhost:8082/api/order/1
# 预期返回:{"code":500,"message":"服务降级:用户服务不可用"}

Sentinel 流量控制配置

在 Sentinel 控制台(localhost:8888)为 order-service 添加流控规则:

资源名: /api/order/list

  • 阈值类型: QPS
  • 单机阈值: 1
  • 流控效果: 快速失败

扩展建议

  1. 添加分布式事务:集成 Seata 处理跨服务事务
  2. 链路追踪:集成 SkyWalking 或 Zipkin
  3. 消息队列:使用 RocketMQ 实现异步解耦
  4. 服务监控:集成 Prometheus + Grafana
  5. 安全认证:接入 Spring Security OAuth2 或 JWT

这个案例涵盖了 Spring Cloud Alibaba 的核心组件,可以直接运行学习,如有任何问题,欢迎继续交流!

抱歉,评论功能暂时关闭!