Java 高级教程 — Spring Cloud微服务

前置要求:Java基础、Spring Boot基础
学习时长:约3-5天
技术栈:Spring Cloud + Nacos + Gateway + Feign
适用场景:企业级微服务架构

一、Spring Cloud是什么?

Spring Cloud是Java微服务全家桶,提供了一整套微服务解决方案。

组件作用替代方案
Nacos服务注册/配置中心Consul、Eureka
GatewayAPI网关Zuul、Kong
Feign声明式HTTP客户端RestTemplate
Sentinel熔断限流Hystrix
Seata分布式事务2PC、TCC

二、服务注册与发现(Nacos)

2.1 安装Nacos

# Docker安装
docker run -d --name nacos \
  -p 8848:8848 \
  -p 9848:9848 \
  -e MODE=standalone \
  nacos/nacos-server:latest

# 访问:http://localhost:8848/nacos
# 默认账号:nacos/nacos

2.2 服务注册

<!-- pom.xml -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

# application.yml
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

// 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}


三、API网关(Gateway)

3.1 配置网关

# application.yml
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/api/products/**

server:
  port: 8080

3.2 自定义过滤器

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        if (token == null || !token.startsWith("Bearer ")) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        // 验证token
        try {
            String userId = JwtUtils.verify(token.substring(7));
            ServerHttpRequest request = exchange.getRequest().mutate()
                .header("X-User-Id", userId)
                .build();
            return chain.filter(exchange.mutate().request(request).build());
        } catch (Exception e) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
    }
    
    @Override
    public int getOrder() {
        return -1;
    }
}


四、服务间调用(Feign)

4.1 定义Feign客户端

@FeignClient(name = "user-service", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
    
    @GetMapping("/api/users/{id}")
    ApiResponse<User> getUser(@PathVariable("id") Long id);
    
    @PostMapping("/api/users")
    ApiResponse<User> createUser(@RequestBody CreateUserRequest request);
}

@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable cause) {
        return new UserClient() {
            @Override
            public ApiResponse<User> getUser(Long id) {
                return ApiResponse.error("用户服务不可用");
            }
            
            @Override
            public ApiResponse<User> createUser(CreateUserRequest request) {
                return ApiResponse.error("用户服务不可用");
            }
        };
    }
}

4.2 使用Feign

@Service
public class OrderService {
    
    @Autowired
    private UserClient userClient;
    
    public Order createOrder(CreateOrderRequest request) {
        // 调用用户服务获取用户信息
        ApiResponse<User> userResponse = userClient.getUser(request.getUserId());
        if (userResponse.getCode() != 200) {
            throw new RuntimeException("获取用户信息失败");
        }
        
        User user = userResponse.getData();
        
        // 创建订单
        Order order = new Order();
        order.setUserId(user.getId());
        order.setUserName(user.getUsername());
        // ...
        
        return order;
    }
}


五、配置中心(Nacos Config)

5.1 配置

# application.yml
spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        file-extension: yaml
        group: DEFAULT_GROUP

5.2 动态配置

@RestController
@RefreshScope  // 支持动态刷新
public class ConfigController {
    
    @Value("${app.name}")
    private String appName;
    
    @Value("${app.version}")
    private String version;
    
    @GetMapping("/config")
    public Map<String, String> getConfig() {
        Map<String, String> config = new HashMap<>();
        config.put("appName", appName);
        config.put("version", version);
        return config;
    }
}


六、熔断限流(Sentinel)

6.1 安装Sentinel Dashboard

docker run -d --name sentinel \
  -p 8858:8858 \
  bladex/sentinel-dashboard:latest

# 访问:http://localhost:8858
# 默认账号:sentinel/sentinel

6.2 使用Sentinel

@Service
public class UserService {
    
    @SentinelResource(
        value = "getUser",
        fallback = "getUserFallback",
        blockHandler = "getUserBlockHandler"
    )
    public User getUser(Long id) {
        return userRepository.findById(id).orElse(null);
    }
    
    // 降级方法
    public User getUserFallback(Long id, Throwable t) {
        return new User(0L, "默认用户", "");
    }
    
    // 限流方法
    public User getUserBlockHandler(Long id, BlockException e) {
        throw new RuntimeException("请求被限流");
    }
}


七、分布式事务(Seata)

7.1 安装Seata

docker run -d --name seata \
  -p 8091:8091 \
  -e SEATA_PORT=8091 \
  seataio/seata-server:latest

7.2 使用分布式事务

@Service
public class OrderService {
    
    @GlobalTransactional  // 开启全局事务
    public void createOrder(CreateOrderRequest request) {
        // 1. 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        orderMapper.insert(order);
        
        // 2. 扣减库存(调用库存服务)
        inventoryClient.deduct(request.getProductId(), request.getQuantity());
        
        // 3. 扣减余额(调用账户服务)
        accountClient.debit(request.getUserId(), order.getTotalAmount());
        
        // 如果任何一步失败,所有操作都会回滚
    }
}


八、项目结构

my-microservice/
├── gateway-service/          # API网关
├── user-service/             # 用户服务
├── order-service/            # 订单服务
├── product-service/          # 商品服务
├── common/                   # 公共模块
│   ├── common-core/          # 核心工具
│   ├── common-redis/         # Redis工具
│   └── common-mybatis/       # MyBatis配置
└── pom.xml


学习建议

  1. 先理解微服务架构概念
  2. 掌握Nacos服务注册和配置
  3. 学会Gateway网关配置
  4. 掌握Feign服务间调用
  5. 了解Sentinel熔断限流

下一步学习

返回首页