Java小强个人技术博客站点    手机版
当前位置: 首页 >> 开源 >> Sentinel入门Controller自动定义为资源

Sentinel入门Controller自动定义为资源

7940 开源 | 2023-2-24

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。



依赖引入

<!--使其主动对所有的url进行统计,把所有的controller接口识别成资源-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-web-servlet</artifactId>
    <version>1.8.5</version>
</dependency>


定义过滤器

package com.example.sentinel.config;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
/**
 * 该过滤器将controller自动定义为Sentinel资源
 */
@Configuration
public class SentinelFilter {
    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        registration.setName("sentinelFilter");
        registration.setOrder(1);
        return registration;
    }
}


排除同类URL

package com.example.sentinel.config;
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
import java.util.regex.Pattern;
/**
 * 一些接口采用了 @PathVariable 注解,每一个url都会被识别成资源,但是sentinel最多支持6000个,所以需要处理
 * 例如:/name/{id}可能会有/name/1、/name/2、/name/3,如果不处理就是三个资源,但是其实这是一个资源
 */
public class WebUrlCleaner implements UrlCleaner {
    /**
     * 正则匹配
     */
    private static String PATTERN_SENTINEL_TEST_NAME = "^/name/[0-9a-zA-Z]+$";
    private static String SENTINEL_RESOURCE_SENTINEL_TEST_NAME = "/name/*";
    private static Pattern pattern = Pattern.compile(PATTERN_SENTINEL_TEST_NAME);
    @Override
    public String clean(String originUrl) {
        if (pattern.matcher(originUrl).matches()) {
            return SENTINEL_RESOURCE_SENTINEL_TEST_NAME;
        } else {
            return originUrl;
        }
    }
}


异常统一处理

其默认的异常提示不友好,也不符合项目中的统一返回定义,所以需要针对该情况做修改

package com.example.sentinel.config;
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
public class WebUrlBlockHandler implements UrlBlockHandler {
    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
        HashMap<Object, Object> result = new HashMap<>(2);
        String msg = null;
        Integer code = 0;
        if (e instanceof FlowException) {
            msg = "系统繁忙";
            code = 1;
        } else if (e instanceof BlockException) {
            msg = "系统繁忙";
            code = 2;
        } else if (e instanceof ParamFlowException) {
            msg = "系统繁忙";
            code = 3;
        } else if (e instanceof SystemBlockException) {
            msg = "系统繁忙";
            code = 4;
        }
        result.put("code", code);
        result.put("msg", msg);
        response.setStatus(200);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.writeValue(response.getWriter(), result);
    }
}


把以上定义配置给Sentinel

package com.example.sentinel.config;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import org.springframework.context.annotation.Configuration;
@Configuration
public class InitSRule {
    static {
        //设置自定义的Block异常处理
        WebCallbackManager.setUrlBlockHandler(new WebUrlBlockHandler());
        //设置url清洗
        WebCallbackManager.setUrlCleaner(new WebUrlCleaner());
    }
}


定义一个普通Controller

@RequestMapping("/getHello5")
public String getHello5() {
    return "hello,now is :" + DateUtil.now();
}


访问该接口,就会在Sentinel控制台看到该资源

sentinel.jpg


END

推荐您阅读更多有关于“ 微服务 Sentinel 流控 限流 熔断降级 ”的文章

上一篇:使用Redis集合List实现消息队列 下一篇:Sentinel入门流控编码方式

猜你喜欢

发表评论: