欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)分布式系統(tǒng)限流

 更新時間:2022年08月12日 11:33:43   作者:陳虎_63  
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)分布式系統(tǒng)限流,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

為何使用分布式系統(tǒng)限流:

在分布式環(huán)境中,我們的系統(tǒng)都是集群化部署,那么使用了單機(jī)版的限流策略,比如我們對某一個接口的限流方案是每秒鐘最多10次請求,那么因?yàn)楦鱾€實(shí)例都會自己維護(hù)一份請求次數(shù),所以真實(shí)每秒的請求數(shù)是:
節(jié)點(diǎn)數(shù) * 每秒最多請求數(shù),這樣的話就超出了我們的預(yù)期;

分布式限流解決方案:

● 可以基于redis,做分布式限流
● 可以基于nginx做分布式限流
● 可以使用阿里開源的 sentinel 中間件

本次介紹使用 redis 做分布式限流

實(shí)現(xiàn)思路:

設(shè)計(jì)思路:假設(shè)一個用戶(用IP判斷)每分鐘訪問某一個服務(wù)接口的次數(shù)不能超過10次,那么我們可以在Redis中根據(jù)該用戶IP創(chuàng)建一個鍵,并此時我們就設(shè)置這個鍵的過期時間為60秒,當(dāng)用戶請求到來的時候,先去redis中根據(jù)用戶ip獲取這個用戶當(dāng)前分鐘請求了多少次,如果獲取不到,則說明這個用戶當(dāng)前分鐘第一次訪問,就創(chuàng)建這個健,并+1,如果獲取到了就判斷當(dāng)前有沒有超過我們限制的次數(shù),如果到了我們限制的次數(shù)則禁止訪問。

使用技術(shù):使用redis提供的:incr命令 實(shí)現(xiàn)

先引入redis的依賴:

<dependency>
? ? ? ? ? ? <groupId>redis.clients</groupId>
? ? ? ? ? ? <artifactId>jedis</artifactId>
? ? ? ? ? ? <version>2.9.0</version>
? ? ? ? </dependency>

? ? ? ? <dependency>
? ? ? ? ? ? <groupId>com.alibaba</groupId>
? ? ? ? ? ? <artifactId>fastjson</artifactId>
? ? ? ? ? ? <version>1.2.70</version>
</dependency>

redis配置類:

package org.xhs.redis;


import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
?* @Author: hu.chen
?* @Description:
?**/
public class RedisConfig {

? ? // 服務(wù)器IP地址
? ? private static String ADDR = "127.0.0.1";
? ? // 端口
? ? private static int PORT = 6379;
? ? // 密碼
? ? private static String AUTH = null;
? ? // 連接實(shí)例的最大連接數(shù)
? ? private static int MAX_ACTIVE = 1024;
? ? // 控制一個pool最多有多少個狀態(tài)為idle(空閑的)的jedis實(shí)例,默認(rèn)值也是8。
? ? private static int MAX_IDLE = 200;
? ? // 等待可用連接的最大時間,單位毫秒,默認(rèn)值為-1,表示永不超時。如果超過等待時間,則直接拋出JedisConnectionException
? ? private static int MAX_WAIT = 10000;
? ? // 連接超時的時間
? ? private static int TIMEOUT = 10000;
? ? // 在borrow一個jedis實(shí)例時,是否提前進(jìn)行validate操作;如果為true,則得到的jedis實(shí)例均是可用的;
? ? private static boolean TEST_ON_BORROW = true;

? ? ? ? private static JedisPool jedisPool = null;
? ? // 數(shù)據(jù)庫模式是16個數(shù)據(jù)庫 0~15
? ? public static final int DEFAULT_DATABASE = 0;

? ? /**
? ? ?* 初始化Redis連接池
? ? ?*/

? ? static {

? ? ? ? try {

? ? ? ? ? ? JedisPoolConfig config = new JedisPoolConfig();
? ? ? ? ? ? config.setMaxTotal(MAX_ACTIVE);
? ? ? ? ? ? config.setMaxIdle(MAX_IDLE);
? ? ? ? ? ? config.setMaxWaitMillis(MAX_WAIT);
? ? ? ? ? ? config.setTestOnBorrow(TEST_ON_BORROW);
? ? ? ? ? ? jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH, DEFAULT_DATABASE);

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }

? ? /**
? ? ?* 獲取Jedis實(shí)例
? ? ?*/
? ? public static Jedis getJedis() {
? ? ? ? try {

? ? ? ? ? ? if (jedisPool != null) {
? ? ? ? ? ? ? ? Jedis resource = jedisPool.getResource();
? ? ? ? ? ? ? ? return resource;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return null;
? ? ? ? ? ? }
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? return null;
? ? ? ? }

? ? }

}

redis工具類:

package org.xhs.redis;

import redis.clients.jedis.Jedis;

/**
?* @Author: hu.chen
?* @Description:
?* @DateTime: 2022/1/21 1:06 PM
?**/
public class RedisUtils {

? ? /**
? ? ?* 將指定的key遞增1(可用于樂觀鎖)
? ? ?*
? ? ?* @param key
? ? ?* @return
? ? ?*/
? ? public static Long incr(final String key) {

? ? ? ? Jedis jedis = RedisConfig.getJedis();
? ? ? ? Long ?incr = jedis.incr(key);

? ? ? ? returnJedis(jedis);
? ? ? ? return incr;
? ? }


? ? /**
? ? ?* 給指定key設(shè)置過期時間
? ? ?*
? ? ?* @param key
? ? ?* @param seconds
? ? ?* @author ruan 2013-4-11
? ? ?*/
? ? public static void expire(String key, int seconds) {
? ? ? ? if (seconds <= 0) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? Jedis jedis = RedisConfig.getJedis();
? ? ? ? jedis.expire(key, seconds);
? ? ? ? // 將連接還回連接池
? ? ? ? returnJedis(jedis);
? ? }


? ? /**
? ? ?* 回收jedis
? ? ?*
? ? ?* @param jedis
? ? ?*/
? ? private static void returnJedis(Jedis jedis) {
? ? ? ? if (jedis != null) {
? ? ? ? ? ? jedis.close();
? ? ? ? }
? ? }
}

實(shí)現(xiàn):

package org.xhs.redis;


import java.util.ArrayList;
import java.util.List;


/**
?* @Author: hu.chen
?* @Description:
?**/
public class TestRedis {
? ? /**
? ? ?* 超時時間(單位秒)
? ? ?*/
? ? private static int TIMEOUT = 30;

? ? /**
? ? ?* 每分鐘的請求次數(shù)限制
? ? ?*/
? ? private static int COUNT = 10;


? ? public static void main(String[] args) {

? ? ? ? List<UserRequest> tasks = new ArrayList();
? ? ? ? // 準(zhǔn)備工作,先初始化 10個線程(用戶),這10個用戶同時訪問一個接口
? ? ? ? for (int i = 1; i <= 12; i++) {
? ? ? ? ? ? String ip = "127.0.0." + i;
? ? ? ? ? ? String userName = "chenhu_";
? ? ? ? ? ? String interfaceName = "user/find_" + i;
? ? ? ? ? ? tasks.add(new UserRequest(ip, userName, interfaceName));
? ? ? ? }


? ? ? ? for (UserRequest request : tasks) {
? ? ? ? ? ? // 以用戶名為鍵
? ? ? ? ? ? if (isAccess(request.getUserName(), COUNT)) {
? ? ? ? ? ? ? ? System.err.println("用戶:"+request.getUserName()+" 當(dāng)前時間訪問次數(shù)還未達(dá)到上限,可以訪問");
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? System.err.println("當(dāng)前時間訪問失敗,"+request.getUserName()+"無法獲取令牌");
? ? ? ? ? ? }


? ? ? ? }
? ? }

? ? /**
? ? ?* 是否可以訪問
? ? ?*
? ? ?* @return
? ? ?*/
? ? private static boolean isAccess(String userName, long count) {
? ? ? ? Long incr = RedisUtils.incr(userName);
? ? ? ? if (incr == 1) {
? ? ? ? ? ? RedisUtils.expire(userName, TIMEOUT);
? ? ? ? }
? ? ? ? if (count < incr) {
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? return true;
? ? }


? ? /**
? ? ?* 實(shí)體對象
? ? ?*/
? ? private static class UserRequest {
? ? ? ? /**
? ? ? ? ?* 請求用戶ip
? ? ? ? ?*/
? ? ? ? private String ip;
? ? ? ? /**
? ? ? ? ?* 用戶名
? ? ? ? ?*/
? ? ? ? private String userName;
? ? ? ? /**
? ? ? ? ?* 請求的接口名
? ? ? ? ?*/
? ? ? ? private String interfaceName;

? ? ? ? public UserRequest(String ip, String userName, String interfaceName) {
? ? ? ? ? ? this.ip = ip;
? ? ? ? ? ? this.userName = userName;
? ? ? ? ? ? this.interfaceName = interfaceName;
? ? ? ? }

? ? ? ? public String getIp() {return ip;}

? ? ? ? public String getUserName() { return userName;}

? ? ? ? public String getInterfaceName() {return interfaceName;}
? ? }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring的@Scheduled 如何動態(tài)更新cron表達(dá)式

    Spring的@Scheduled 如何動態(tài)更新cron表達(dá)式

    這篇文章主要介紹了Spring的@Scheduled 如何動態(tài)更新cron表達(dá)式的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot整合Security安全框架實(shí)現(xiàn)控制權(quán)限

    SpringBoot整合Security安全框架實(shí)現(xiàn)控制權(quán)限

    本文主要介紹了SpringBoot整合Security安全框架實(shí)現(xiàn)控制權(quán)限,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket

    詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket

    這篇文章主要介紹了詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket ,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-01-01
  • 微信小程序與Java后端接口交互

    微信小程序與Java后端接口交互

    本文主要介紹了微信小程序與Java后端接口交互,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • 深入了解Spring的Bean生命周期

    深入了解Spring的Bean生命周期

    這篇文章主要為大家介紹了Spring的Bean生命周期,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定的參考價值,感興趣的可以學(xué)習(xí)一下
    2022-01-01
  • 簡單了解java標(biāo)識符的作用和命名規(guī)則

    簡單了解java標(biāo)識符的作用和命名規(guī)則

    這篇文章主要介紹了簡單了解java標(biāo)識符的作用和命名規(guī)則,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • 使用Spring自身提供的地址匹配工具匹配URL操作

    使用Spring自身提供的地址匹配工具匹配URL操作

    這篇文章主要介紹了使用Spring自身提供的地址匹配工具匹配URL操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java單測void類型的方法詳解

    Java單測void類型的方法詳解

    這篇文章主要給大家介紹了Java中單測void類型的方法,文中給出了詳細(xì)的示例代碼,相信對大家的理解和學(xué)習(xí)具有一定的參考借鑒價值,需要的朋友可以跟著小編下面來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-01-01
  • Java使用線程同步解決線程安全問題詳解

    Java使用線程同步解決線程安全問題詳解

    線程安全是多線程編程時的計(jì)算機(jī)程序代碼中的一個概念。在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會通過同步機(jī)制保證各個線程都可以正常且正確的執(zhí)行,不會出現(xiàn)數(shù)據(jù)污染等意外情況
    2022-05-05
  • spring boot 默認(rèn)異常處理的實(shí)現(xiàn)

    spring boot 默認(rèn)異常處理的實(shí)現(xiàn)

    這篇文章主要介紹了spring boot 默認(rèn)異常處理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評論