练习题:
1、每个用户秒杀QPS不得超过1(秒杀下单userId级别)
2、6号用户是vvip,不限制QPS(例外情况)
3、666号是下架商品,不允许访问
注意:目前 Sentinel 自带的 adapter 仅 Dubbo 方法埋点带了热点参数,其它适配模块(如 Web)默认不支持热点规则,可通过自定义埋点方式指定新的资源名并传入希望的参数。注意自定义埋点的资源名不要和适配模块生成的资源名重复,否则会导致重复统计。
因此我们在使用热点规则时,需要手动添加埋点,用@SentinelResource注解将资源标注出来。
一、测试环境准备
1、OrderController类里创建seckill接口,用@SentinelResource标注seckill接口为sentinal资源,用fallback属性声明兜底回调方法,并创建出seckillFallback兜底回调方法。
注意:@SentinelResource注解中value属性给出的资源名,不能和@GetMapping中value属性的路径名相同,因为@Getmapping标注的接口,sentinal会自动探测为资源。我们又用@SentinelResource标注的资源也会被sentinal收录为资源。两个名不能重复。
@RestController @RequestMapping("/api/order") public class OrderController { @Autowired private OrderService orderService; @Autowired private OrderProperties properties; @GetMapping("seckill") @SentinelResource(value = "seckill-order",fallback = "seckillFallback") public Order seckill(@RequestParam("userId") Long userId, @RequestParam("productId") Long productId){ Order order = orderService.createOrder(productId, userId); return order; } public Order seckillFallback(Long userId, Long productId, Throwable e){ System.out.println("OrderController.seckillFallback......"); Order order = new Order(); order.setUserId(userId); order.setAddress("异常信息"+e.getClass()); return order; } }2、创建OrderService接口,实现业务处理逻辑。
public interface OrderService { Order createOrder(Long productId, Long userId); }@Service public class OrderServiceImpl implements OrderService { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @Autowired private ProductFeignClient client; @Autowired private LoadBalancerClient balancerClient; //需要导入spring-cloud-starter-loadbalancer //SentinelResource一般标注在非controller的层级 @SentinelResource(value = "createOrder", blockHandler = "createOrderFallback") @Override public Order createOrder(Long productId, Long userId) { // Product product = getProductFromRemoteWithAnnotation(productId); //使用feign完成远程调用 Product product = client.getProductById(productId); Order order = new Order(); order.setId(1L); order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum()))); order.setUserId(userId); order.setNickName("lvdandan"); order.setAddress("精神自由"); order.setProductList(Arrays.asList(product)); return order; } //兜底回调 public Order createOrderFallback(Long productId, Long userId, BlockException e) { Order order = new Order(); order.setId(0l); order.setTotalAmount(new BigDecimal(0)); order.setUserId(userId); order.setNickName("未知用户"); order.setAddress("异常信息"+e.getClass()); return order; } }3、构建ProductFeignClient接口,调用service-product服务的获取产品信息接口。
@FeignClient(value = "service-product",fallback = ProductFeignClientFallBack.class) public interface ProductFeignClient { @GetMapping("/api/product/{id}") Product getProductById(@PathVariable("id") Long id); }4、service-product服务的Contorller
@RestController @RequestMapping("/api/product") public class ProductController { @Autowired ProductService productService; @GetMapping("{id}") public Product getProduct(@PathVariable Long id){ Product product = productService.getProductById(id); return product; } }5、service-product服务的Service
public interface ProductService { Product getProductById(Long id); }@Service public class ProductServiceImpl implements ProductService { @Override public Product getProductById(Long id) { Product product = new Product(); product.setId(id); product.setProductName("苹果"+id+"手机"); product.setPrice(new BigDecimal(248)); product.setNum(2); System.out.println("hello"); return product; } }习题1配置:
参数索引表示被标注的资源方法参数列表的参数索引,从0开始。
参数索引为0 的参数表示资源方法的第0个参数,即UserId。
单机阈值:1 表示统计窗口期内只能处理一个请求。
统计窗口时长:1 秒
该配置表示,统计窗口时长内,相同的userId,只能放行1个请求。过多的请求会触发兜底回调。
@GetMapping("seckill") @SentinelResource(value = "seckill-order",fallback = "seckillFallback") public Order seckill(@Param("userId") Long userId, @Param("productId") Long productId){另外:
如果浏览器调用接口时不传userid,方法参数1给定了默认值,这种情况热点规则也会生效。
public Order seckill(@RequestParam(value = "userId",defaultValue = "1") Long userId, @RequestParam("productId") Long productId){如果浏览器调用接口时不传userId,方法参数1设置为允许为空,并没给默认值,这种情况配置的热点规则就不会生效。
public Order seckill(@RequestParam(value = "userId",required = false) Long userId, @RequestParam("productId") Long productId){习题2配置:
6号用户是vvip,不限制QPS(例外情况)
此页面入口:左侧菜单栏“热点规则” -> 点击已经配置好的一条热点规则的“编辑”按钮;新增热点规则的时候是没有高级选项的。
参数类型是userid的类型(long类型);参数值:6 表示针对6号用户的规则;限流阈值:10000 表示对6号userid每秒限制QPS为10000。 即为不限流。
习题3配置:
666号是下架商品,不允许访问
首先针对方法的第二个参数新增一条热点规则,然后点击“编辑”,修改该条规则,添加高级选项。
选定第二个参数的参数类型为long, 给出参数值为666,给出限流阈值为0,点击添加,点击保存。
即第二个参数单机阈值非常大,即为不限流。指定666号商品阈值为0,即禁止访问666号商品。