Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)

Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)

每天多学一点点~
话不多说,这就开始吧…

文章目录

  • Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)
  • 1.前言
  • 2.下载启动
  • 3.与springcloud整合
  • 4.测试 sentinel
  • 5.与ribbon整合
  • 6.与openFeign整合
  • 7.优化错误页面
  • 8.结语

1.前言

不得不说,Hystrix再sentinel面前就是个弟弟~

sentinel git地址

2.下载启动

  1. dashboard下载
    我这里选择1.7.0 版本

Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第1张图片

  1. 启动
    java -jar sentinel-dashboard-1.7.0.jar --server.port=9999 启动(就是一个Springboot工程)
    Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第2张图片

默认账号密码是 sentinel

3.与springcloud整合

其实与这些第三方组件整合,无非就是三板斧

  1. 加依赖
			
			
			
				org.springframework.cloud
				spring-cloud-dependencies
				Greenwich.SR3
				pom
				import
			

			
				com.alibaba.cloud
				spring-cloud-alibaba-dependencies
				2.1.1.RELEASE
				pom
				import
			
			
			
			
				com.alibaba.cloud
				spring-cloud-alibaba-nacos-discovery
			
		
			
		   
				com.alibaba.csp
				sentinel-core
				1.7.0
			

			
				com.alibaba.cloud
				spring-cloud-starter-alibaba-sentinel
			
			
			
			
				org.springframework.boot
				spring-boot-starter-actuator
			
  1. yml配置
    首先,添加Sentinel后,会暴露/actuator/sentinel端点http://localhost:8080/actuator/sentinel
    而Springboot默认是没有暴露该端点的,所以我们需要自己设置
    其次,加入 dashboard 的地址
spring:
  datasource:
      xxxxxx : 这里就不写了  db的配置
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:9999
        #namespace: bc7613d2-2e22-4292-a748-48b78170f14c  #指定namespace的id
  application:
    name: order-center
  main:
    allow-bean-definition-overriding: true
server:
  port: 8080
management:
  endpoints:
    web:
      exposure:
        include: '*'

4.测试 sentinel

启动项目+nacos+sentinel dashboard 三个,随便访问一个项目接口,比如我这里的

http://localhost:8080/saveOrder

Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第3张图片

在 sentinel dashboard 中便会又显示(记住,首先要访问一次自己的端口,才会有显示)
Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第4张图片
我们给其加入 一个 流控规则 阈值为1
Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第5张图片

多访问几次接口 ,出现 Blocked by Sentinel (flow limiting) 说明被流控,成功

sentinel功能很强大,其他 关于 限流 降级 的配置 可以去git上自己去看看,这里就不演示了

sentinel git地址

5.与ribbon整合

  1. 加依赖
		
		
			org.springframework.cloud
			spring-cloud-starter-netflix-ribbon
		
  1. yml配置
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:9999
#是否开启@SentinelRestTemplate注解
resttemplate:
  sentinel:
    enabled: true
  1. 加注解
    (在 RestTemplate组件上添加 @SentinelRestTemplate注解) 并且我们可以通过在@SentinelRestTemplate 同样的可以指定我们的 blockHandlerClass fallbackClass blockHandler fallback 这四个属性
@Configuration
public class WebConfig {

    @Bean
    @LoadBalanced
    @SentinelRestTemplate(
            blockHandler = "handleException",blockHandlerClass = GlobalExceptionHandler.class,
            fallback = "fallback",fallbackClass = GlobalExceptionHandler.class

    )
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

GlobalExceptionHandler 是自己的全局异常处理类,这里简单的写一下

@Slf4j
public class GlobalExceptionHandler {


    /**
     * 限流后处理方法
     */
    public static SentinelClientHttpResponse handleException(HttpRequest request,
                                                             byte[] body, ClientHttpRequestExecution execution, BlockException ex)  {

        ProductInfo productInfo = new ProductInfo();
        productInfo.setProductName("被限制流量拉");
        productInfo.setProductNo("-1");
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            return new SentinelClientHttpResponse(objectMapper.writeValueAsString(productInfo));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 熔断后处理的方法
     */
    public static SentinelClientHttpResponse fallback(HttpRequest request,
                                                      byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
        ProductInfo productInfo = new ProductInfo();
        productInfo.setProductName("被降级拉");
        productInfo.setProductNo("-1");
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            return new SentinelClientHttpResponse(objectMapper.writeValueAsString(productInfo));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

6.与openFeign整合

sentinel默认与feign整合了
Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第6张图片

  1. 加依赖

	     
				com.alibaba.csp
				sentinel-core
				1.7.0
		
			
		
			org.springframework.cloud
			spring-cloud-starter-openfeign
		

		
			org.springframework.boot
			spring-boot-starter-actuator
		
  1. yml配置
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:9999
feign:
  httpclient:
    enabled: true   # #让feign底层使用HttpClient去调用
    max-connections: 200 #  最大连接数
    max-connections-per-route: 50 #  为每个url请求设置最大连接数
  client:
    config:
      dafult:
        connectTimeout: 5000
        readTime: 5000
      product-center:  #     要调用服务的名称
        loggerLevel: FULL   # 日志级别
   sentinel:
        enabled: true   # 打开 Sentinel 对 Feign 的支持 这样@FeignClient的fallback 才会生效

  1. 在Feign的声明式接口上添加fallback属性或者 fallbackFactory属 性
    这里直接通过 fallbackFactory 声明,因为通过 fallback 无法捕获异常
//@FeignClient(name = "product-center",fallback = ProductCenterFeignApiWithSentinelFallback.class)
@FeignClient(name = "product-center",fallbackFactory = ProductCenterFeignApiWithSentielFallbackFactory.class)
public interface ProductCenterFeignApiWithSentinel {

    /**
     * 声明式接口,远程调用http://product-center/selectProductInfoById/{productNo}
     * @param productNo
     * @return
     */
    @RequestMapping("/selectProductInfoById/{productNo}")
    ProductInfo selectProductInfoById(@PathVariable("productNo") String productNo);

}

FallbackFactory 能区别异常

@Component
@Slf4j
public class ProductCenterFeignApiWithSentielFallbackFactory implements FallbackFactory {
    @Override
    public ProductCenterFeignApiWithSentinel create(Throwable throwable) {
        return new ProductCenterFeignApiWithSentinel(){

            @Override
            public ProductInfo selectProductInfoById(String productNo) {
                log.error("原因:{}",throwable);
                ProductInfo productInfo = new ProductInfo();
                productInfo.setProductName("默认商品");
                return productInfo;
            }
        };
    }
}

Fallback 不能区别异常

@Component
public class ProductCenterFeignApiWithSentinelFallback implements ProductCenterFeignApiWithSentinel {
    @Override
    public ProductInfo selectProductInfoById(String productNo) {
        ProductInfo productInfo = new ProductInfo();
        productInfo.setProductName("默认商品");
        return productInfo;
    }
}

到此整合结束,但是 ,sentinel不支持持久化 ,即 你重启sentinel dashboard 或者 项目工程,你配置在sentinel中的流控降级等等规则全部 没了,这也是阿里比较坑的地方,为何,因为阿里云上有AHAS。。。
那么 下篇,来分享下 sentinel 持久化的 三种方式

7.优化错误页面

sentinel默认情况下,无论你是限流还是降级,触发了都会返回
Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第7张图片

这样返回实在太不友好了,所以要加入自己的配置

@Component
public class QiuqiuUrlBlockHandler implements UrlBlockHandler {

    public static final Logger log = LoggerFactory.getLogger(QiuqiuUrlBlockHandler.class);

    /**
     *  接口中加了feign,则 在 控制台中会既会显示接口 也会也是 feign的调用接口
     *   看你 限流哪个 ,限流feign  就走feign的fallback
     *                   限流原来接口,则走下面的逻辑
     * @return
     */
    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {

        if(ex instanceof FlowException) {
            log.warn("触发了流控");
            warrperResponse(response, ErrorEnum.FLOW_RULE_ERR);
        }else if(ex instanceof ParamFlowException) {
            log.warn("触发了参数流控");
            warrperResponse(response,ErrorEnum.HOT_PARAM_FLOW_RULE_ERR);
        }else if(ex instanceof AuthorityException) {
            log.warn("触发了授权规则");
            warrperResponse(response,ErrorEnum.AUTH_RULE_ERR);
        }else if(ex instanceof SystemBlockException) {
            log.warn("触发了系统规则");
            warrperResponse(response,ErrorEnum.SYS_RULE_ERR);
        }else{
            log.warn("触发了降级规则");
            warrperResponse(response,ErrorEnum.DEGRADE_RULE_ERR);
        }
    }

    private void warrperResponse(HttpServletResponse httpServletResponse, ErrorEnum errorEnum) throws IOException {
        httpServletResponse.setStatus(500);
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setHeader("Content-Type","application/json;charset=utf-8");
        httpServletResponse.setContentType("application/json;charset=utf-8");

        ObjectMapper objectMapper = new ObjectMapper();
        String errMsg =objectMapper.writeValueAsString(new ErrorResult(errorEnum));
        httpServletResponse.getWriter().write(errMsg);
    }

}

根据异常类型,自定义返回值返给前台
Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面)_第8张图片
注意:若接口中加了feign,则 在 控制台中会既会显示接口 ,也会显示 feign的调用接口
看你限流哪个 ,若限流feign 就走feign的fallback。 若限流原来接口,则走UrlBlockHandler 逻辑。
ribbon同理。

8.结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!

你可能感兴趣的:(Springcloud-alibaba集成sentinel(ribbon+openFeign+优化错误页面))