spring cloud alibaba 学习(二十二)Sentinel 与 OpenFeign服务熔断总结

本文详细介绍了Sentinel的三种熔断降级策略:fallback、SentinelResource流控降级和全局熔断。通过示例代码展示了如何配置和实现这些策略,包括在Feign客户端使用fallback、定义BlockHandler处理流量控制,以及自定义全局BlockExceptionHandler。Sentinel作为微服务治理的重要组件,能有效保障系统的稳定性和容错性。
摘要由CSDN通过智能技术生成


一、fallback降级

1、在 @FeignClient 加上注解

@FeignClient(value = "server",fallback = ServerApiFallBack.class)
@Component
public interface ServerApi {

    @GetMapping("/server/test/{id}")
    Map test(@PathVariable String id);
}

2、ServerApiFallBack 熔断类

@Component
public class ServerApiFallBack implements ServerApi{
    @Override
    public Map test(String id) {
        ImmutableMap map = ImmutableMap.of("code", 500, "reason", "服务不可用");
        return map;
    }
}

3、Controller接口

@RestController
@RequestMapping("/client")
public class ClientController {

  @GetMapping("/test/{id}")
    public Map test(@PathVariable String id){
        return serverApi.test(id);
    }
    
}

4、此时调用接口,服务出现异常不步可用时,会触发 fallback 服务熔断,具体逻辑在 SentinelInvocationHandler 中实现

				catch (Throwable ex) {
					...
					if (fallbackFactory != null) {
						try {
							//回调服务熔断方法
							Object fallbackResult = fallbackMethodMap.get(method)
									.invoke(fallbackFactory.create(ex), args);
							return fallbackResult;
						}
					...

二、SentinelResource流控降级

1、在 @FeignClient 加上注解

@FeignClient(value = "server",fallback = ServerApiFallBack.class)
@Component
public interface ServerApi {

    @GetMapping("/server/test/{id}")
    Map test(@PathVariable String id);
}

2、Controller接口

 @SentinelResource(value = "sentinel-test", blockHandler = "blockHandler")
    @GetMapping("/test/{id}")
    public Map test(@PathVariable String id){
        return serverApi.test(id);
    }

    public Map blockHandler(String id ,BlockException e) {
        ImmutableMap map = ImmutableMap.of(
                "code", 500,
                "reason", "sentinel服务流量控制",
                "error", e);
        return map;
    }

3、配置熔断规则

在sentine控制台设置熔断规则

在这里插入图片描述
4、访问接口

多次访问接口,会发生熔断,结果:

{
    "code": 500,
    "reason": "sentinel服务流量控制",
    "error": {
  	...
}

此时熔断逻辑是在SentinelResourceAspect中

		try {
            entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
            Object result = pjp.proceed();
            return result;
        } catch (BlockException ex) {
        	//熔断
            return handleBlockException(pjp, annotation, ex);
        } 

根据@SentinelResource中配置的blockHandler、blockHandlerClass、fallback、defaultFallback、fallbackClass调用熔断的方法。

三、Sentinel全局熔断

1、给接口设置熔断规则,例如给controller接口设置熔断规则,资源名是/client/test/{id},当触发熔断规则时,具体逻辑是在SentinelWebInterceptor 中处理,它实现了springmvc 的 HandlerInterceptor 拦截器接口。在preHandle方法中触发接口的流控。

	catch (BlockException e) {
            try {
            	//处理熔断
                handleBlockException(request, response, e);
            } 
 protected void handleBlockException(HttpServletRequest request, HttpServletResponse response, BlockException e)
        throws Exception {
        //配置中存在BlockExceptionHandler时,调用其handle()方法
        if (baseWebMvcConfig.getBlockExceptionHandler() != null) {
            baseWebMvcConfig.getBlockExceptionHandler().handle(request, response, e);
        } else {
            // Throw BlockException directly. Users need to handle it in Spring global exception handler.
            throw e;
        }
    }

2、baseWebMvcConfig 中配置 BlockExceptionHandler

在SentinelWebAutoConfiguration配置类中,创建了SentinelWebMvcConfig

	@Autowired
	private Optional<BlockExceptionHandler> blockExceptionHandlerOptional;

	@Bean
	@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled",
			matchIfMissing = true)
	public SentinelWebMvcConfig sentinelWebMvcConfig() {
		SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();
		sentinelWebMvcConfig.setHttpMethodSpecify(properties.getHttpMethodSpecify());
		sentinelWebMvcConfig.setWebContextUnify(properties.getWebContextUnify());
		//自定义 BlockExceptionHandler
		if (blockExceptionHandlerOptional.isPresent()) {
			blockExceptionHandlerOptional
					.ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler);
		}
		else {
			//自定义熔断时跳转页面 blockPage
			if (StringUtils.hasText(properties.getBlockPage())) {
				sentinelWebMvcConfig.setBlockExceptionHandler(((request, response,
						e) -> response.sendRedirect(properties.getBlockPage())));
			}
			else {
				//默认的 DefaultBlockExceptionHandler
				sentinelWebMvcConfig
						.setBlockExceptionHandler(new DefaultBlockExceptionHandler());
			}
		}

		urlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner);
		requestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser);
		return sentinelWebMvcConfig;
	}

3、自定义 BlockExceptionHandler

@Component
public class GlobalBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {

        response.setStatus(500);

        ServletOutputStream out = response.getOutputStream();
        out.print(new String("触发 Sentinel 全局熔断处理".getBytes(StandardCharsets.UTF_8),"iso-8859-1"));
        out.flush();
        out.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_lrs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值