Rumah  >  Artikel  >  Java  >  Had semasa antara muka, semua operasi hebat ada di sini!

Had semasa antara muka, semua operasi hebat ada di sini!

Java学习指南
Java学习指南ke hadapan
2023-07-26 14:22:331126semak imbas

Mengapa semasa mengehadkan

Apabila mereka bentuk sistem, kita akan mempunyai anggaran kapasiti sistem Jika ia melebihi ambang TPS/QPS yang sistem boleh tahan lama, sistem mungkin terharu, akhirnya menyebabkan keseluruhan perkhidmatan menjadi Tidak tersedia. Untuk mengelakkan situasi ini, kita perlu mengehadkan aliran permintaan antara muka.

Jadi, kami boleh melindungi sistem atau mengelakkan pembaziran sumber yang tidak perlu dengan mengehadkan kadar permintaan akses serentak atau bilangan permintaan dalam tetingkap masa Setelah had kadar dicapai, kami boleh menafikan perkhidmatan, beratur atau menunggu.

Latar belakang mengehadkan semasa

Sistem ini mempunyai antara muka untuk mendapatkan kod pengesahan SMS telefon mudah alih Kerana ia adalah antara muka terbuka, untuk mengelakkan pengguna daripada terus menghantar permintaan untuk mendapatkan kod pengesahan dan menghalang percubaan berniat jahat untuk meleret. antara muka, kami menggunakan yang terkini Kaedah kaunter mudah digunakan untuk mengehadkan aliran semasa, mengehadkan setiap IP kepada hanya satu permintaan seminit, dan kemudian had tetingkap masa nombor telefon mudah alih satu sama lain dinilai melalui logik perniagaan. Secara amnya, sesetengah antara muka mempunyai bilangan lawatan yang agak besar dan mungkin mengatasi sistem, jadi sekatan trafik perlu ditambah! Seperti: jualan kilat, dll...

Kaedah pelaksanaan

1. Memperkenalkan tanggungan

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter {
    /**
     * 限流key
     */
     String key() default Constants.RATE_LIMIT_KEY;

    /**
     * 限流时间,单位秒
     */
     int time() default 60;

    /**
     * 限流次数
     */
    int count() default 100;

    /**
     * 限流类型
     */
    LimitType limitType() default LimitType.DEFAULT;

    /**
     * 限流后返回的文字
     */
    String limitMsg() default "访问过于频繁,请稍候再试";
}

3. Aliran Terhad bahagian
@Aspect
@Component
public class RateLimiterAspect {

    private final static Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);

    @Autowired
    private RedisUtils redisUtils;

    @Before("@annotation(rateLimiter)")
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
        int time = rateLimiter.time();
        int count = rateLimiter.count();
        long total = 1L;

        String combineKey = getCombineKey(rateLimiter, point);
        try
        {
            if(redisUtils.hasKey(combineKey)){
                total = redisUtils.incr(combineKey,1);  //请求进来,对应的key加1
                if(total > count)
                    throw new ServiceRuntimeException(rateLimiter.limitMsg());
            }else{
                redisUtils.set(combineKey,1,time);  //初始化key
            }
        }
        catch (ServiceRuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new ServiceRuntimeException("网络繁忙,请稍候再试");
        }
    }

    /**
     * 获取限流key
     * @param rateLimiter
     * @param point
     * @return
     */
    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
        StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
        if (rateLimiter.limitType() == LimitType.IP)
        {
            stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
        }
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
        return stringBuffer.toString();
    }

}

4 Tulis antara muka yang mudah untuk menguji
@RestController
public class TestController {

    @RateLimiter(time = 60, count = 1, limitType = LimitType.IP, limitMsg = "一分钟内只能请求一次,请稍后重试")
    @GetMapping("/hello")
    public ResultMsg hello() {
        return ResultMsg.success("Hello World!");
    }
}

pengecualian global.

6 . Ujian antara muka🎜

1) Kali pertama anda menghantarnya, hasilnya akan dikembalikan seperti biasa

Had semasa antara muka, semua operasi hebat ada di sini!

2) Kali kedua anda menghantarnya dalam masa satu minit, anda akan mendapat ralat dan gesaan had semasa

Had semasa antara muka, semua operasi hebat ada di sini!

The di atas adalah AOP + Redis penyelesaian untuk melaksanakan had semasa antara muka, anda Adakah anda telah kehilangan pengajian anda?

Terdapat kaedah pengehad semasa yang lain, seperti kaedah pengehad arus tingkap gelongsor (lebih ketat daripada kaunter), baldi token, dll... Rakan-rakan yang berminat boleh mempelajarinya.


Atas ialah kandungan terperinci Had semasa antara muka, semua operasi hebat ada di sini!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:Java学习指南. Jika ada pelanggaran, sila hubungi admin@php.cn Padam