Spring Cloud Alibaba一一SentinelResource

SentinelResource

    在定义了资源点之后,我们可以通过Dashboard控制台页面来设置限流和降级策略来对资源点进行保护。同时还能通过[**@SentinelResource**](/SentinelResource)****注解来制定出现异常时的处理策略

1、属性说明

  • value

         资源名称、必须项、因为需要通过resource name找到对应的规则,这个是必须配置的。

  • blockHandler

         blockHandler对应处理BlockException的函数名称,可选项。blockHandler函数访问范围需要是public,返回的类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException。

  • fallback

         fallback函数名称,可选项,用于在抛出异常的时候提供fallback处理逻辑。fallBack函数可以针对所有类型的异常(Throwable)

  • blockHandlerClass

         blockHandler函数默认需要和原生方法在同一个类中,如果希望使用其他类的函数,则需要指定blockhandlerClass为对应的类的Class对象,注意对应的函数必须为static函数,否则无法解析。

  • fallbackClass

         fallBackClass的应用和blockHandlerClass类似,fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass为对应的类的Class对象,注意对应的函数必须为static函数,否则无法解析。

2、自定义处理限流和业务异常

@GetMapping("/hello4")
@SentinelResource(value ="hel1o4",blockHandler ="blockHandler",fallback ="fallbackHandler")
public string hello4(Integer age){
     int i = 10 / age;
     return "hello4";
}
// hel13Handler方法的参数和返回值要和原方法一直,BlockException用来接收原方法的异常
public string blockHandler(Integer age,BlockException e){
      return"资源被限流”;
}
//hel13Handler方法的参数和返回值要和原方法一直,Throwable用来接收原方法的异常(这里必须是Throwable用来接收原方法的异常,不能是exception)
public string fallbackHandler(Integer age,Throwable e) {
    return"资源出现异常";
}

     以上这种方式可以处理资源中的限流和业务异常了,但是发现异常处理类和业务代码耦合了,而且还没办法复用。

3、处理异常类和业务类解耦

@RestController
@slf4j
public class HelloController f
     @GetMapping("/hel1o4")
     @SentinelResource(value = "hello4",
                                     blockHandlerClass = MyBlockHandlerClass.class,
                                     blockHandler ="blockHandler",
                                     fallbackClass = FallbackHandler.class,
                                     fallback ="fallbackHandler")
     public string hello4(Integer age) {
            int i = 18 / age;
            return "hel1o4";
     }
}
public class FallbackHandler {
              // 这里的方法必须是静态的,方法参数和返回值要和原方法一致
              public static string fallbackHandler(Integer age,Throwable e) {
                    return"资源出现异常"
              }
}
public class MyBlockHandlerClass f
         // 这里的方法必须是静态的,方法参数和返回值要和原方法一致
         public static string blockHandler(Integer age,BlockException e) {
              System.out.println("bolockHanlder age ="+ age +",e="+e);
              return"资源被限流”;
          }
}

Feign整合Sentinel实现降级

    Feign整合Sentinel后不同异常调用不同的处理器来解决异常。

    流控异常调用:blockHandler

   服务运行时异常调用:fallback

   feign调用异常调用:feign降级

1、导入依赖

<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-sentinel</artifactIdx
</dependency>
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、FeignFallbackFactory

@Component
public class FeignFallbackFactory implements FallbackFactory<HelloService>(
       @Autowired
        private HelloServiceImpl helloService;
        @Override
        public HelloService create(Throwable throwable) {
             System.out.println(throwable);
             return helloService;
        }
}

3、Feign接口

@FeignClient(value = "provider-1",fallbackFactory = FeignFallbackFactory.class)
public interface HelloService {
     @RequestMapping("/hello")
     public string hello();
}

4、开启sentinel

feign:
   sentinel:
     enabled: true

5、版本问题

SpringCloud版本和SpringCloudAlibaba版本冲突的问题。

Caused by:at feien.FeignsBuilder.com.alibaba.cloud.sentinel.feign,sentinelcontractHolder.parseAndvalidateMetadajava .lang.AbstractMethoderror:lane/class;)Liava/util/list:
at feignReflectiveFeigsParseHandlersByllame,apply(Reflectivefeign.java:151) feign-(ore-10.7,4,jar:na
at feign,ReflectiveFein,newinstance(ReflectiveFeign.java:49) [feign-core-10.7.4jar:na)
target(feien.ia
core-18.7.4.ar;na7
at or3.sorineframework.coudopenfeien.-strixtareter.tareetHystrixtmeter, ava:33)  sorine-cloud-enfee-ore-2.2.2,RELEASE,m2.2.2RELEASE
at r.trmewo.cou.ttr da ertat  -
at org.sprineframevwork,cIod.0pfeignFegclietactoryBen-gtTretFeclitFto Bean av282  gprn-coud-Efe-0re-2-22RELEASE.ar:2.2.2ELEASE
  am.Co.0 it B- tat 2----S22S
t org.pringframework.beans.atory, support.Fto Beamegistryuprt,0etbjectfrnFtr Ben (to Beamepistry supprtaa71)re-ns-52.4ELEASE5.2.4ELEASE
... 67 common frames omitted

解决方式

自定义一个SentinelContractHolder类,包名和源码保持一致。

packagecom.alibaba.cloud.sentinel.feign;
import feign.Contract;
import feign.MethodMetadata;
import java.util.HashMap;import
import java.util.List;import
import java.util.Map;
public class SentinelContractHolder implements Contract {
          private final Contract delegate;
           /* map key is constructed by ClassFullName + configkey. configkey is constructed by
            * (@link feign.Feign#configKey}
            */
          public final static Map<String, MethodMetadata> METADATA MAP = new HashMap<>();
          public SentinelContractHolder(Contract delegate) {
                this.delegate = delegate!
          }
         @Override
          public List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {
                     List<MethodMetadata> metadatas = delegate.parseAndValidateMetadata(targetType);
                     metadatas.forEach(metadata -> METADATA MAP.put(targetType.getName() + metadata.configkey(), metadata));
                     return metadatas;
          }
}

        Feign调用服务过程中,服务出现故障,如果服务中存在全局异常管理器,会认为这个故障已经被服务处理了,然后返回一个空的对象,feign不会调用自己的降级方法。

       sentinel持久化

 1、sentinel工作模式

    在Sentinel客户端(微服务)中用代码写的配置,在启动后,当有第一次流量进来的时候,会推送给Sentinel-Dashboard;在Sentinel-Dashboard中的配置,会被推送到Sentinel客户端(微服务);默认情况下,不论 Sentinel-Dashboard中的配置还是Sentinel客户端中的配置,都是在内存中的,一点重启,这些变化过的规则就全部消失了。

2、semtinel持久化

在此将规则持久化到nacos中,在nacos中添加规则,然后同步到dashboard中。

1、导入依赖

<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2、在yml中配置nacos信息

spring:
  application:
    name: sentinel-server
  cloud:
    nacos:
      discovery:
         server-addr: 192.168.147.11.8848
    sentinel:
       transport:
          dashboard: 192.168.147.11:8080
          port: 8719
       eager: true
       datasource:
          sentinel1:
             nacos:
                serverAddr: 192.168.147.11:8848
                dataId: ${spring.application.name}
                groupId: DEFAULT_GROUP
                data-type: json
                rule-type: flow

3、在nacos中添加规则

[
     {
         "resource":"he11o4",
         "limitApp":"default",
         "grade": 1,
         "count": 5,
         "strategy": 0,
         "controlBehavior":0,
         'clusterMode": false
     }
]
  • resource: 资源名称
  • limitApp: 来源应用
  • grade: 阈值类型, 0-线程数  1-qps
  • count: 单机阈值
  • strategy: 流控模式, 0-直接  1-关联  2-链路
  • controlBehavior:流控效果、0-快速失败,1-warm up,2-排队等待
  • clusterMode: 是否集群

4、测试

服务启动后,当有第一次流量进来的时候,Sentinel-Dashboard会从nacos中拉取流控信息。