配置

  • 引入redis依赖
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>
  5. spring2.x需要引入这个,否则会报下图的错误
  6. <dependency>
  7. <groupId>org.apache.commons</groupId>
  8. <artifactId>commons-pool2</artifactId>
  9. <version>2.6.2</version>
  10. </dependency>

使用Redis限制Http接口访问总次数 - 图1

  • 引入SpringBoot一些基本依赖 ```xml org.springframework.boot spring-boot-starter-web
org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-devtools true

com.alibaba.cloud spring-cloud-starter-alibaba-sentinel 2.2.1.RELEASE


- application.yml
```yaml
server:
  port: 9000
  servlet:
    context-path: /

spring:
  application:
    name: skeleton
  profiles:
    active: dev
  mvc:
    static-path-pattern: /**
  resources:
    static-locations: classpath:/META-INF/resources/, classpath:/resources/,classpath:/static/, classpath:/public/,file:${soyuan.thumbnailDir}
#    不需要sentinel的话也可以不配
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: localhost:8080
#  配置redis      
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0
    lettuce:
      shutdown-timeout: 200ms
      pool:
        max-active: 7
        max-idle: 7
        min-idle: 2
        max-wait: -1ms
  • 配一下redis地址即可。
    sentinel不需要的话,就删掉吧。

service

@Service
public class IProjectMetaServiceImpl implements IProjectMetaService {

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public void register(String key, Integer count) {
        ValueOperations<String, String> valOps = redisTemplate.opsForValue();
        valOps.set(key, String.valueOf(count));
    }

    @SentinelResource(value = "projectMetaTest",blockHandler = "testBlockHandler")
    @Override
    public String test(String key) {
        ValueOperations<String, String> valOps = redisTemplate.opsForValue();
        if (redisTemplate.hasKey(key)) {
            Long decrement = valOps.decrement(key);
            if (decrement <= 0) {
                throw new AccessLimitException("调用次数已用完...");
            }
            return key+"您的业务逻辑处理完毕";
        }
        throw new AccessLimitException("未注册用户,不能访问...");
    }

    public String testBlockHandler(String name, BlockException be) {
        System.out.println("testBlockHandler");
        return "error";
    }
}

register(String key, Integer count) 模拟后台管控系统给xxx设定访问次数。

String test(String key) 每访问一次,将次数减1,当次数小于0时,提示调用次数已用完。如果不存在key,则表示当前用户未注册

方法上的注解@SentinelResource(value = "projectMetaTest",blockHandler = "testBlockHandler") 是阿里sentinel的入门用法,不必关心。

控制接口层

@RestController
@RequestMapping("/project")
public class IndexController {

    @Autowired
    private IProjectMetaService service;

    @GetMapping("/test")
    public String test(@RequestParam("key")String key) {
        return service.test(key);
    }

    @PostMapping("/register")
    public String register(@RequestBody RegisterRqo rqo) {
        service.register(rqo.getKey(), rqo.getCount());
        return "注册成功";
    }

    public static class RegisterRqo {
        String key;
        Integer count;

        public RegisterRqo() {
        }

        public String getKey() {
            return key;
        }

        public Integer getCount() {
            return count;
        }
    }
}

很简单,就不说了。

测试

使用Redis限制Http接口访问总次数 - 图2

使用Redis限制Http接口访问总次数 - 图3

使用ab测试,结果

使用Redis限制Http接口访问总次数 - 图4

注意,失败8次。(均是因为超过调用次数导致)

仓库地址

https://github.com/tangwenixng/learn-sentinel-web