https://blog.youkuaiyun.com/sdmanooo/article/details/115528230 这篇文章介绍了Sentinel在网关filter的应用,这一篇介绍在应用层使用@SentinelResource注解实现限流及降级的方法。
当然应用层也可以建Filter来实现,这里不介绍了。
直接上代码:
1、如果使用@SentinelResource 注解,还需要引入sentinel-annotation-aspectj依赖。所以需要引入的依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.1</version>
</dependency>
2、启动类中生成令牌桶
@SpringBootApplication
public class ZuulLimitApplication {
public static void main(String[] args) {
init();
SpringApplication.run(ZuulLimitApplication.class, args);
}
//生成限流令牌
private static void init(){
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule flowRule = new FlowRule();
flowRule.setResource("HelloWorld");//定义resource名称,限流时,根据resource名称进行限流
flowRule.setCount(1);
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rules.add(flowRule);
FlowRuleManager.loadRules(rules);
}
}
3、要使用注解,就必须有切面,所以需要注入SentinelResourceAspect
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 要想使用@SentinelResource注解,需要手动注入SentinelResourceAspect
*/
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
return new SentinelResourceAspect();
}
}
4、前3步都是准备工作,从这里就可以开始正常的业务及使用注解了。
建controller
import com.test.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* controller层
*/
@RestController
public class TestController {
@Autowired
private TestService testService;
@RequestMapping("test/{id}")
public String test(@PathVariable("id") int id) throws Exception {
return testService.test(id);
}
}
5、建sevice层,我这里省略了接口层
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;
/**
* service层
*/
@Service
public class TestService {
/**
* 使用sentinelResource注解实现限流
* value是FlowRule指定的Resouce名称,
* blockHandler指定限流之后的方法名(限流方法),
* fallback指定方法报错后执行的方法名(降级方法)
*
* @param id
* @return
* @throws Exception
*/
@SentinelResource(value = "HelloWorld", blockHandler = "testBlockHandler", fallback = "testFallBack")
public String test(int id) throws Exception {
if (id == 0) {
//当请求id是0的时候,让其走fallback方法
throw new Exception();
}
System.out.println("正常请求");
return "请求到了" + id;
}
/**
* test方法报错时的fallBack方法,
* 注意:方法名跟test不同,参数和返回值要相同
*
* @param id
* @return
*/
public String testFallBack(int id) {
System.out.println("错误请求");
return "出错了" + id;
}
/**
* test方法被限流时执行的blockHandler方法,
* 注意:方法返回值跟test要一样,参数要在test方法参数的基础上,添加一个BlockExcpetion的参数到最后一个参数。
*
* @param id
* @param e
* @return
*/
public String testBlockHandler(int id, BlockException e) {
System.out.println("限流请求");
return "限流了" + id + " error:" + e.getMessage();
}
}
至此结束。代码中的注释也比较详细了。
注意:
1、FlowRuleManager.loadRules(List) 的参数是个list集合,也就是说可以加载多个FlowRule,每个FlowRule可以指定自己的Resource。 在使用的时候只需要在@SentinelResource的value里面指定使用哪个Resource就会按照对应的FlowRule规则进行执行。
2、注意里面用到的一些类的包路径,别引错了类。java中有很多重名的类,一定注意包名。