最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率的示例

 更新時(shí)間:2024年02月03日 09:48:56   作者:????????帥龍之龍  
限流就是限制API訪問頻率,當(dāng)訪問頻率超過某個(gè)閾值時(shí)進(jìn)行拒絕訪問等操作,本文主要介紹了Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率的示例,具有一定的參考價(jià)值,感興趣的可以了解一下

前言

為啥需要限制接口請(qǐng)求頻率?這個(gè)是因?yàn)榉乐菇涌谝恢北凰?,比如發(fā)送手機(jī)驗(yàn)證碼的接口,一直被刷的話,費(fèi)錢費(fèi)資源的,至少做點(diǎn)基本的防護(hù)工作。以下分別使用Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率方案。

一、基于Redis實(shí)現(xiàn)接口限流

1.ZADD 命令

(1)用法:ZADD key score_1 value_1 score_2 value_2 ...
(2)作用:將一個(gè)或多個(gè)成員元素及其分?jǐn)?shù)值加入到有序集當(dāng)中。某個(gè)成員已經(jīng)是有序集的成員,那么更新這個(gè)成員的分?jǐn)?shù)值,并通過重新插入這個(gè)成員元素,來(lái)保證該成員在正確的位置上。分?jǐn)?shù)值可以是整數(shù)值或雙精度浮點(diǎn)數(shù)。
(3)返回值:被成功添加的新成員的數(shù)量,不包括那些被更新的、已經(jīng)存在的成員。
(4)示例

redis > ZADD runoobkey 1 redis
(integer) 1
redis > ZADD runoobkey 2 mongodb
(integer) 1
redis > ZADD runoobkey 3 mysql
(integer) 1
redis > ZADD runoobkey 3 mysql
(integer) 0
redis > ZADD runoobkey 4 mysql
(integer) 0
redis > ZRANGE runoobkey 0 10 WITHSCORES

1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

2.ZREM 命令

(1)用法:ZREM key value_1 value_2 ...
(2)作用:移除有序集中的一個(gè)或多個(gè)成員,不存在的成員將被忽略。
(3)返回值:被成功添加的新成員的數(shù)量,不包括那些被更新的、已經(jīng)存在的成員。
(4)示例

redis > ZRANGE runoobkey 0 10 WITHSCORES

1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

redis > ZREM mongodb
(integer) 1

redis > ZRANGE runoobkey 0 10 WITHSCORES
1) "redis"
2) "1"
3) "mysql"
4) "4"

3.ZCARD 命令

(1)用法:ZCARD key
(2)作用:獲取有序集合中成員的數(shù)量。
(3)返回值:當(dāng)key存在且是有序集類型時(shí),返回有序集的基數(shù)。 當(dāng)key不存在時(shí),返回0 。
(4)示例

redis > ZADD myzset 1 "one"
(integer) 1
redis > ZADD myzset 2 "two"
(integer) 1
redis > ZCARD myzset
(integer) 2

4.ZREMRANGEBYSCORE 命令

(1)用法:ZREMRANGEBYSCORE key min max
(2)作用:移除有序集中,指定分?jǐn)?shù)區(qū)間內(nèi)的所有成員。
(3)返回值:被移除成員的數(shù)量。
(4)示例

redis > ZRANGE salary 0 -1 WITHSCORES
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"

redis > ZREMRANGEBYSCORE salary 1500 3500
(integer) 2

redis> ZRANGE salary 0 -1 WITHSCORES
1) "jack"
2) "5000"

5.具體實(shí)現(xiàn)

(1)新建一個(gè)過濾器,如【/src/main/java/org/example/interceptor/RateLimiterInterceptor.java】

package org.example.interceptor;

import cn.hutool.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * 限流攔截器
 */
@Component
public class RateLimiterInterceptor implements HandlerInterceptor {
    private static final String RATE_LIMITER_PREFIX = "Rate-Limiter:";
    private static final int LIMIT = 10; // 限流閾值
    private static final int TIME_WINDOW = 60; // 時(shí)間窗口,單位為秒

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json");

        String key = RATE_LIMITER_PREFIX + request.getRequestURI() + ":" + request.getRemoteAddr(); // Rate-Limiter:/api/sendCode:127.0.0.1

        long currentTime = System.currentTimeMillis(); // 1703036748554
        long beforeTime = currentTime - TIME_WINDOW * 1000; // 1703036748554 - 60000 = 1703036688554

        // Long removeNum = stringRedisTemplate.opsForZSet().removeRangeByScore(K key, double min, double max); // 刪除有序集合中分?jǐn)?shù)在指定范圍內(nèi)的元素,返回刪除元素的數(shù)量
        stringRedisTemplate.opsForZSet().removeRangeByScore(key, 0, beforeTime); // 刪除有序集合中60秒之前存進(jìn)去的所有數(shù)據(jù),如:

        // Long memberNum = stringRedisTemplate.opsForZSet().size(K key); // 獲取有序集合中元素的數(shù)量
        long count = stringRedisTemplate.opsForZSet().size(key); // 3
        if (count >= LIMIT) {
            HashMap<String, Object> responseObj = new HashMap<>();
            responseObj.put("code", HttpStatus.TOO_MANY_REQUESTS.value());
            responseObj.put("success", false);
            responseObj.put("msg", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
            JSONObject json = new JSONObject(responseObj);
            response.getWriter().println(json);
            return false;
        } else {
            // Boolean addFlag = stringRedisTemplate.opsForZSet().add(K var1, V var2, double var3); // 向有序集合中添加一個(gè)或多個(gè)元素,并指定其分?jǐn)?shù)
            stringRedisTemplate.opsForZSet().add(key, String.valueOf(currentTime), currentTime);

            // Boolean expireFlag = stringRedisTemplate.expire(K key, long timeout, TimeUnit unit); // 對(duì)指定key的數(shù)據(jù)設(shè)置過期時(shí)間
            stringRedisTemplate.expire(key, TIME_WINDOW, TimeUnit.SECONDS);

            return true;
        }
    }
}

(2)在SpringMVC配置類中注入此過濾器,如【/src/main/java/org/example/config/ResourceConfig.java】

package org.example.config;

import org.example.interceptor.RateLimiterInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class ResourceConfig extends WebMvcConfigurationSupport {
    @Autowired
    private RateLimiterInterceptor rateLimiterInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(rateLimiterInterceptor).addPathPatterns("/abcd/api/sendCode");
    }
}

6.運(yùn)行效果

// ~

二、基于Nginx實(shí)現(xiàn)接口限流

1.在nginx.conf文件中新增限流配置

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;

    # 負(fù)載均衡
    upstream springboot {
        server xxx.xxx.xxx.xxx:8080;
    }

    # limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/s; # 定義了一個(gè)名為limit_zone的限流區(qū)域,使用IP地址進(jìn)行限流,該區(qū)域的大小為10MB,限流速率為10個(gè)請(qǐng)求每秒。

    limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/m; # 定義了一個(gè)名為limit_zone的限流區(qū)域,使用IP地址進(jìn)行限流,該區(qū)域的大小為10MB,限流速率為10個(gè)請(qǐng)求每分鐘。


    # 80端口的服務(wù)
    server { 
        listen       80;
        server_name  xxx.xxx.xxx.xxx;

        location / {
            alias  html;
            index  index.html index.htm;
            try_files $uri $uri/ /love/index.html;
            proxy_pass http://localhost;
        }

        location ^~ /love/ {
            root   html/love;
            index  index.html index.htm;
            proxy_pass http://localhost;
        }

        location ^~ /abcd/api/sendCode {
          # 在/xxx/api/sendCode接口的location中使用limit_req指令進(jìn)行限流,限流區(qū)域?yàn)閘imit_zone,同時(shí)設(shè)置了一個(gè)瞬時(shí)突發(fā)流量為20個(gè)請(qǐng)求的閾值。
          # 這樣,當(dāng)同一個(gè)IP地址在一秒鐘內(nèi)發(fā)送超過10個(gè)請(qǐng)求到此接口時(shí),Nginx會(huì)返回503錯(cuò)誤碼,表示請(qǐng)求被限流了。
          # limit_req zone=limit_zone burst=20;

          # 在/xxx/api/sendCode接口的location中使用limit_req指令進(jìn)行限流,限流區(qū)域?yàn)閘imit_zone,同時(shí)設(shè)置了一個(gè)瞬時(shí)突發(fā)流量為5個(gè)請(qǐng)求的閾值。
          # 這樣,當(dāng)同一個(gè)IP地址在一秒鐘內(nèi)發(fā)送超過10個(gè)請(qǐng)求到此接口時(shí),如果在一分鐘內(nèi)有超過10個(gè)請(qǐng)求,則允許其中的5個(gè)請(qǐng)求通過,nodelay表示不延遲響應(yīng),即立即返回503錯(cuò)誤碼。
          limit_req zone=limit_zone burst=5 nodelay;

          proxy_pass http://springboot;
        }
    }
}

2.運(yùn)行效果

// ~

到此這篇關(guān)于Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率的示例的文章就介紹到這了,更多相關(guān)Redis和Nginx限制接口請(qǐng)求頻率內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何利用Redis分布式鎖實(shí)現(xiàn)控制并發(fā)操作

    如何利用Redis分布式鎖實(shí)現(xiàn)控制并發(fā)操作

    這篇文章主要介紹了如何利用Redis分布式鎖實(shí)現(xiàn)控制并發(fā)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-09-09
  • Redis是單線程的嗎

    Redis是單線程的嗎

    Redis使用單線程的原因就是多線程并不能有效提升Redis的性能,相反可能還會(huì)降低性能,所以自然而然使用單線程,本文給大家詳細(xì)介紹了Redis為什么是單線程的,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • 深入理解redis_memcached失效原理(小結(jié))

    深入理解redis_memcached失效原理(小結(jié))

    這篇文章主要介紹了深入理解redis_memcached失效原理(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2018-08-08
  • redis過期回調(diào)功能實(shí)現(xiàn)示例

    redis過期回調(diào)功能實(shí)現(xiàn)示例

    Redis提供了一種過期回調(diào)的機(jī)制,可以在某個(gè)鍵過期時(shí)觸發(fā)一個(gè)回調(diào)函數(shù),本文就來(lái)介紹一下redis過期回調(diào)功能實(shí)現(xiàn)示例,感興趣的可以了解一下
    2023-09-09
  • Redis異步隊(duì)列的實(shí)現(xiàn)及應(yīng)用場(chǎng)景

    Redis異步隊(duì)列的實(shí)現(xiàn)及應(yīng)用場(chǎng)景

    異步隊(duì)列是一種底層基于異步 I/O 模型的消息隊(duì)列,用于在分布式系統(tǒng)中進(jìn)行同步和異步的通訊和協(xié)作,本文主要介紹了Redis異步隊(duì)列的實(shí)現(xiàn)及應(yīng)用場(chǎng)景,感興趣的可以了解一下
    2023-12-12
  • redis.config配置文件

    redis.config配置文件

    在使用Redis時(shí),我們通常需要對(duì)Redis進(jìn)行一些配置,以確保其能夠正常運(yùn)行并滿足我們的需求,本文主要介紹了redis.config配置文件,感興趣的可以了解一下
    2023-11-11
  • Linux中Redis安裝部署的操作步驟

    Linux中Redis安裝部署的操作步驟

    公司一直在使用redis集群,尋思著自己也部署一套練練手,下面這篇文章主要給大家介紹了關(guān)于Linux中Redis安裝部署的操作步驟,需要的朋友可以參考下
    2022-04-04
  • 一篇文章揭秘Redis的磁盤持久化機(jī)制

    一篇文章揭秘Redis的磁盤持久化機(jī)制

    這篇文章主要給大家介紹了如何通過一篇文章揭秘Redis的磁盤持久化機(jī)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • SpringBoot整合Redis入門之緩存數(shù)據(jù)的方法

    SpringBoot整合Redis入門之緩存數(shù)據(jù)的方法

    Redis是一個(gè)開源的使用ANSI C語(yǔ)言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的API,下面通過本文給大家介紹下SpringBoot整合Redis入門之緩存數(shù)據(jù)的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-11-11
  • Redis簡(jiǎn)介

    Redis簡(jiǎn)介

    Redis是一個(gè)開源,高級(jí)的鍵值存儲(chǔ)和一個(gè)適用的解決方案,用于構(gòu)建高性能,可擴(kuò)展的Web應(yīng)用程序。關(guān)于redis的相關(guān)知識(shí)大家可以通過本教程學(xué)習(xí)
    2017-05-05

最新評(píng)論

乃东县| 尼玛县| 酒泉市| 尉犁县| 郑州市| 惠来县| 惠安县| 建昌县| 老河口市| 霞浦县| 基隆市| 剑阁县| 关岭| 中西区| 长岛县| 昌宁县| 科技| 贵州省| 甘孜| 乌海市| 竹山县| 玉山县| 河曲县| 印江| 泰宁县| 汽车| 武威市| 红原县| 万盛区| 墨玉县| 库车县| 天等县| 商水县| 清镇市| 武乡县| 华容县| 通道| 界首市| 灵璧县| 扬州市| 惠州市|