资讯动态

Spring Cloud Alibaba Sentinel @SentinelResource

发布时间:2026/9/25 16:50:17 来源:尧图企业网站定制
一、前言Sentinel提供了SentinelResource注解用于定义资源并提供可选的异常回退和Block回退。异常回退指的是SentinelResource注解标注的方法发生Java异常时的回退处理Block回退指的是当SentinelResource资源访问不符合Sentinel控制台定义的规则时的回退默认返回Blocked by Sentinel (flow limiting)。这节简单记录下该注解的用法。二、框架搭建2.1 项目搭建使用IDEA创建一个maven项目artifactId为spring-cloud-alibaba-sentinelresource然后在其下面创建两个ModuleSpring Boot项目artifactId分别为consumer和provider充当服务消费端和服务提供端spring-cloud-alibaba-sentinelresource的pom内容?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.2.RELEASE/versionrelativePath/!-- lookup parent from repository --/parentgroupIdcom.wno704/groupIdartifactIdspring-cloud-alibaba-sentinelresource/artifactIdversion0.0.1-SNAPSHOT/versionnameAlibaba-SentinelResource/namedescriptionDemo project for Spring Boot/descriptionpackagingpom/packagingpropertiesjava.version1.8/java.versionspring-cloud-alibaba.version2.2.3.RELEASE/spring-cloud-alibaba.version/propertiesmodulesmoduleconsumer/modulemoduleprovider/module/modulesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependenciesdependencyManagementdependenciesdependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring-cloud-alibaba.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project引入了spring-boot-starter-web和spring-cloud-starter-alibaba-nacos-discovery服务注册发现依赖。provider的pom的内容如下所示?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.wno704/groupIdartifactIdspring-cloud-alibaba-sentinelresource/artifactIdversion0.0.1-SNAPSHOT/versionrelativePath../pom.xml/relativePath/parentartifactIdprovider/artifactIdnameAlibaba-Provider/namedescriptionDemo project for Spring Boot/descriptionbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/projectconsumer的pom内容如下?xml version1.0 encodingUTF-8?projectxmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.wno704/groupIdartifactIdspring-cloud-alibaba-sentinelresource/artifactIdversion0.0.1-SNAPSHOT/versionrelativePath../pom.xml/relativePath/parentartifactIdconsumer/artifactIdnameAlibaba-Consumer/namedescriptionDemo project for Spring Boot/descriptiondependenciesdependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project因为要演示在消费端使用SentinelResource注解所以我们引入了spring-cloud-starter-alibaba-sentinel依赖。2.2 项目配置provider的配置文件application.yml内容如下server:port:8900spring:application:name:providercloud:nacos:server-addr:127.0.0.1:8848配置了端口号服务名和nacos地址。consumer的配置文件application.yml内容如下server:port:8901spring:application:name:consumercloud:nacos:server-addr:127.0.0.1:8848sentinel:transport:dashboard:127.0.0.1:8080port:8719配置了端口号服务名nacos地址和sentinel控制台地址等。三、基本用法3.1 创建controller我们在provider下添加一个REST资源。在provider的cc.mrbird.provider目录下新建controller包然后在该包下新建GoodsControllerRestControllerRequestMapping(goods)publicclassGoodsController{GetMapping(buy/{name}/{count})publicStringbuy(PathVariableStringname,PathVariableIntegercount){returnString.format(购买%d份%s,count,name);}}接着在consumer端通过Ribbon消费这个资源。在consumer的com.wno704.alibaba的目录下新建config文件夹新建ConsumerConfig配置类注册RestTemplate。ConfigurationpublicclassConsumerConfig{BeanpublicRestTemplaterestTemplate(){returnnewRestTemplate();}BeanpublicSentinelResourceAspectsentinelResourceAspect(){returnnewSentinelResourceAspect();}}在consumer的com.wno704.alibaba下新建controller包然后在该包下新建ConsumeControllerRestControllerpublicclassConsumeController{AutowiredprivateLoadBalancerClientloadBalancerClient;AutowiredprivateRestTemplaterestTemplate;GetMapping(buy/{name}/{count})SentinelResource(valuebuy,fallbackbuyFallback,blockHandlerbuyBlock)publicStringbuy(PathVariableStringname,PathVariableIntegercount){if(count20){thrownewIllegalArgumentException(购买数量过多);}if(wno704.equalsIgnoreCase(name)){thrownewNullPointerException(已售罄);}MapString,ObjectparamsnewHashMap(2);params.put(name,name);params.put(count,count);ServiceInstanceserviceInstanceloadBalancerClient.choose(provider);StringpathString.format(http://%s:%s/goods/buy/{name}/{count},serviceInstance.getHost(),serviceInstance.getPort());returnthis.restTemplate.getForEntity(path,String.class,params).getBody();}// 异常回退publicStringbuyFallback(PathVariableStringname,PathVariableIntegercount,Throwablethrowable){returnString.format(【进入fallback方法】购买%d份%s失败%s,count,name,throwable.getMessage());}// sentinel回退publicStringbuyBlock(PathVariableStringname,PathVariableIntegercount,BlockExceptione){returnString.format(【进入blockHandler方法】购买%d份%s失败当前购买人数过多请稍后再试,count,name);}}在buy方法中我们通过Ribbon的RestTemplate访问provider的/goods/buy接口。当count参数大于20或者name参数的值为miband的时候方法将抛出异常。buy方法上使用SentinelResource注解标注标识为一个sentinel资源资源名称为buy并且配置了fallback方法和blockHandler方法。如前面所说当buy方法本身抛出异常时会进入fallback指定的回退方法中当buy方法调用不符合sentinel控制台规定的规则如流控规则降级规则等时会进入blockHander指定的block方法中。为了确保成功地进入回退方法成功反射它们必须满足以下规则函数访问范围需要是publicFallback函数函数签名与原函数一致或末尾加一个Throwable类型的参数Block异常处理函数参数最后多一个BlockException其余与原函数一致。3.2 测试启动provider、consumer、nacos和sentinel控制台http访问http://localhost:8901/buy/ipad/2我们在sentinel控制台中添加如下流控规则QPS阈值为2。然后快速访问http://localhost:8901/buy/ipad/2可以看到当方法访问不符合sentinel控制台规则时进入的是blockHandler指定的回退方法。如果访问http://localhost:8901/buy/ipad/21或者http://localhost:8901/buy/wno704/2方法自身抛出异常引发回退进入的是fallback指定的回退方法。四、其他属性在当前类中编写回退方法会使得代码变得冗余耦合度高我们可以将回退方法抽取出来到一个指定类中。在com.wno704.alibaba包下新建reveal包然后在该包下新建BuyBlockHandlerpublicclassBuyBlockHandler{// sentinel回退publicstaticStringbuyBlock(PathVariableStringname,PathVariableIntegercount,BlockExceptione){returnString.format(【进入blockHandler方法】购买%d份%s失败当前购买人数过多请稍后再试,count,name);}}可以看到我们只是将buyBlock方法挪到了BuyBlockHandler中不过这里的方法必须是static的。接着新建BuyFallBackpublicclassBuyFallBack{// 异常回退publicstaticStringbuyFallback(PathVariableStringname,PathVariableIntegercount,Throwablethrowable){returnString.format(【进入fallback方法】购买%d份%s失败%s,count,name,throwable.getMessage());}}这样BuyController的代码就可以精简为RestControllerpublicclassConsumeController{AutowiredprivateLoadBalancerClientloadBalancerClient;AutowiredprivateRestTemplaterestTemplate;GetMapping(buy/{name}/{count})SentinelResource(valuebuy,fallbackbuyFallback,fallbackClassBuyFallBack.class,blockHandlerbuyBlock,blockHandlerClassBuyBlockHandler.class)publicStringbuy(PathVariableStringname,PathVariableIntegercount){if(count20){thrownewIllegalArgumentException(购买数量过多);}if(wno704.equalsIgnoreCase(name)){thrownewNullPointerException(已售罄);}MapString,ObjectparamsnewHashMap(2);params.put(name,name);params.put(count,count);ServiceInstanceserviceInstanceloadBalancerClient.choose(provider);StringpathString.format(http://%s:%s/goods/buy/{name}/{count},serviceInstance.getHost(),serviceInstance.getPort());returnthis.restTemplate.getForEntity(path,String.class,params).getBody();}}此外我们也可以当遇到某个类型的异常时不进行回退。比如RestControllerpublicclassConsumeController{AutowiredprivateLoadBalancerClientloadBalancerClient;AutowiredprivateRestTemplaterestTemplate;GetMapping(buy/{name}/{count})SentinelResource(valuebuy,fallbackbuyFallback,fallbackClassBuyFallBack.class,blockHandlerbuyBlock,blockHandlerClassBuyBlockHandler.class,exceptionsToIgnoreNullPointerException.class)publicStringbuy3(PathVariableStringname,PathVariableIntegercount){if(count20){thrownewIllegalArgumentException(购买数量过多);}if(wno704.equalsIgnoreCase(name)){thrownewNullPointerException(已售罄);}MapString,ObjectparamsnewHashMap(2);params.put(name,name);params.put(count,count);ServiceInstanceserviceInstanceloadBalancerClient.choose(provider);StringpathString.format(http://%s:%s/goods/buy/{name}/{count},serviceInstance.getHost(),serviceInstance.getPort());returnthis.restTemplate.getForEntity(path,String.class,params).getBody();}}exceptionsToIgnore指定当遇到空指针异常时不回退。重启consumerhttp访问http://localhost:8901/buy/wno704/2可以看到此次并没有进行回退而是直接返回error page。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑