Java服务熔断案例怎么实操

wen java案例 32

本文目录导读:

Java服务熔断案例怎么实操

  1. 使用Sentinel实现服务熔断(推荐)
  2. 使用Hystrix实现服务熔断
  3. 测试用例
  4. 监控与查看
  5. 最佳实践建议

我来为你提供一个Java服务熔断的实操案例,使用Spring Cloud Gateway + Sentinel或Hystrix来实现。

使用Sentinel实现服务熔断(推荐)

环境准备

<!-- pom.xml -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2021.0.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

业务代码示例

// 1. 模拟远程调用服务
@Service
public class UserService {
    // 模拟调用远程服务
    @SentinelResource(value = "getUserInfo", 
                     fallback = "getUserInfoFallback",
                     blockHandler = "handleBlock")
    public String getUserInfo(Long userId) {
        // 模拟远程调用
        if (userId == null || userId < 0) {
            throw new RuntimeException("参数异常");
        }
        // 模拟延迟
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "用户信息:" + userId;
    }
    // 降级处理方法
    public String getUserInfoFallback(Long userId, Throwable e) {
        return "服务暂时不可用,请稍后重试!错误:" + e.getMessage();
    }
    // 流控处理方法
    public String handleBlock(Long userId, BlockException ex) {
        return "请求已被限流,请稍后重试!";
    }
}
// 2. Controller层
@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id) {
        return userService.getUserInfo(id);
    }
}

熔断配置

# application.yml
spring:
  application:
    name: sentinel-demo
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  # Sentinel控制台地址
      eager: true
# 或者在代码中配置
@Configuration
public class SentinelConfig {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

熔断规则配置

@Component
public class SentinelRulesConfig {
    @PostConstruct
    public void initRules() {
        // 1. 熔断规则 - 异常比例
        List<DegradeRule> degradeRules = new ArrayList<>();
        DegradeRule degradeRule = new DegradeRule("getUserInfo")
            .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)  // 异常比例
            .setCount(0.5)  // 异常比例阈值为50%
            .setTimeWindow(10)  // 熔断时长10秒
            .setMinRequestAmount(5)  // 触发熔断的最小请求数
            .setStatIntervalMs(1000);  // 统计时长1秒
        degradeRules.add(degradeRule);
        DegradeRuleManager.loadRules(degradeRules);
        // 2. 熔断规则 - 慢调用比例
        List<DegradeRule> slowRules = new ArrayList<>();
        DegradeRule slowRule = new DegradeRule("getUserInfo")
            .setGrade(RuleConstant.DEGRADE_GRADE_RT)  // 慢调用
            .setCount(200)  // 响应时间超过200ms
            .setTimeWindow(10)  // 熔断时长10秒
            .setMinRequestAmount(10)  // 触发熔断的最小请求数
            .setSlowRatioThreshold(0.5);  // 慢调用比例阈值
        slowRules.add(slowRule);
        DegradeRuleManager.loadRules(slowRules);
        // 3. 流控规则
        List<FlowRule> flowRules = new ArrayList<>();
        FlowRule flowRule = new FlowRule("getUserInfo")
            .setGrade(RuleConstant.FLOW_GRADE_QPS)  // QPS限流
            .setCount(10)  // 阈值10 QPS
            .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        flowRules.add(flowRule);
        FlowRuleManager.loadRules(flowRules);
    }
}

使用Hystrix实现服务熔断

环境准备

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

业务代码示例

// 1. 服务类
@Service
public class OrderService {
    // 使用Hystrix实现熔断
    @HystrixCommand(
        fallbackMethod = "getOrderFallback",
        commandProperties = {
            // 熔断配置
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),  // 10秒内请求数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),  // 熔断时长10秒
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),  // 错误率阈值50%
            // 线程池配置
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),  // 超时时间1秒
            @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD")  // 线程池隔离
        },
        threadPoolProperties = {
            @HystrixProperty(name = "coreSize", value = "10"),  // 核心线程数
            @HystrixProperty(name = "maxQueueSize", value = "100"),  // 队列大小
            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "50")  // 队列拒绝阈值
        }
    )
    public String getOrder(Long orderId) {
        // 模拟调用远程服务
        if (orderId == null || orderId < 0) {
            throw new RuntimeException("订单ID异常");
        }
        // 模拟延迟
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "订单信息:" + orderId;
    }
    // 降级方法
    public String getOrderFallback(Long orderId, Throwable e) {
        return "订单服务不可用,请稍后重试!错误类型:" + e.getClass().getSimpleName();
    }
}
// 2. Controller层
@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @GetMapping("/{id}")
    public String getOrder(@PathVariable Long id) {
        return orderService.getOrder(id);
    }
}

启动类配置

@SpringBootApplication
@EnableCircuitBreaker  // 或者 @EnableHystrix
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

测试用例

@SpringBootTest
@RunWith(SpringRunner.class)
public class CircuitBreakerTest {
    @Autowired
    private UserService userService;
    @Test
    public void testDegrade() throws InterruptedException {
        // 模拟大量请求触发熔断
        for (int i = 0; i < 100; i++) {
            String result = userService.getUserInfo(-1L);  // 构造异常请求
            System.out.println("请求结果:" + result);
            Thread.sleep(100);
        }
        // 等待熔断恢复
        Thread.sleep(12000);
        // 再次请求(应该恢复正常)
        String result = userService.getUserInfo(1L);
        System.out.println("恢复后请求结果:" + result);
    }
}

监控与查看

Sentinel控制台

# 下载并启动Sentinel Dashboard
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.5.jar

查看熔断状态

@RestController
public class MonitorController {
    @GetMapping("/circuit-breaker/status")
    public Map<String, Object> getCircuitBreakerStatus() {
        Map<String, Object> status = new HashMap<>();
        // Sentinel状态
        Set<DegradeRule> degradeRules = DegradeRuleManager.getRules();
        status.put("sentinel.degrade.rules", degradeRules);
        // Hystrix状态
        HystrixCircuitBreaker breaker = HystrixCircuitBreaker.Factory
            .getInstance(HystrixCommandKey.Factory.asKey("getUserInfo"));
        if (breaker != null) {
            status.put("hystrix.isOpen", breaker.isOpen());
            status.put("hystrix.allowRequest", breaker.allowRequest());
        }
        return status;
    }
}

最佳实践建议

  1. 合理设置阈值:根据业务实际情况调整熔断阈值
  2. 优雅降级:降级方法提供友好的提示信息
  3. 监控告警:结合Prometheus + Grafana进行可视化监控
  4. 渐进式恢复:使用半开状态逐步恢复服务
  5. 缓存兜底:降级时返回缓存数据而不是空数据

这个实战案例涵盖了熔断的核心流程,你可以直接运行测试观察熔断效果。

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