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

java實現(xiàn)單機限流

 更新時間:2022年08月12日 12:05:55   作者:陳虎_63  
這篇文章主要為大家詳細介紹了java實現(xiàn)單機限流,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

何時使用限流:

比如你希望自己的應(yīng)用程序 QPS不要超過1000,那么RateLimiter設(shè)置1000的速率后,就會每秒往桶里 扔1000個令牌,RateLimiter經(jīng)常用于限制對一些物理資源或者邏輯資源的訪 問速率。

簡介:

對于單機版的限流,可以使用Google 開源的 Guava項目,這個項目提供了Google在Java項目中使用一些核心庫,包含集合(Collections),緩存(Caching),并發(fā)編程庫(Concurrency),常用注解(Common annotations),String操作,I/O操作方面的眾多非常實用的函數(shù)。

這個項目也包含了限流的功能,其原理是根據(jù)令牌桶算法來實現(xiàn)。

提供了兩種限流策略:

● 平滑突發(fā)限流(SmoothBursty)
● 平滑預熱限流(SmoothWarmingUp)實現(xiàn)。

依賴:

<dependency>
? <groupId>com.google.guava</groupId>
? <artifactId>guava</artifactId>
? <version>29.0-jre</version>
</dependency>

方法描述:

模擬場景(示例):

場景一:

當我們希望某一個接口每秒的訪問量不超過10次

package org.xhs.test;

import org.apache.curator.shaded.com.google.common.util.concurrent.RateLimiter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;


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

? ? /**
? ? ?* 存儲接口名和令牌生成器的對應(yīng)關(guān)系
? ? ?*/
? ?private static Map<String, RateLimiter> interfaces = new ConcurrentHashMap<>();
? ?
? ? /**
? ? ?* 線程池
? ? ?*/
? ? private static ExecutorService threadPool = new ThreadPoolExecutor(10,15,3,TimeUnit.SECONDS,new ArrayBlockingQueue<>(100));

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

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


? ? ? ? // 先初始化好令牌生成器
? ? ? ? for (UserRequest request : tasks) {
? ? ? ? ? ? // 根據(jù)接口名限流
? ? ? ? ? ? RateLimiter rateLimiter = interfaces.get(request.getInterfaceName());

? ? ? ? ? ? if(rateLimiter==null){
? ? ? ? ? ? ? ? // 創(chuàng)建一個令牌生成器,每秒產(chǎn)生10個令牌
? ? ? ? ? ? ? ? synchronized (interfaces) {
? ? ? ? ? ? ? ? ? ? if(rateLimiter==null) {
? ? ? ? ? ? ? ? ? ? ? ? rateLimiter = RateLimiter.create(10);
? ? ? ? ? ? ? ? ? ? ? ? // 將這個令牌生成器和具體的接口進行綁定
? ? ? ? ? ? ? ? ? ? ? ? interfaces.put(request.getInterfaceName(),rateLimiter);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? // 休眠一秒,讓令牌生成器先生成令牌
? ? ? ? Thread.sleep(1000);

? ? ? ? for (UserRequest request : tasks) {
? ? ? ? ? ? // 根據(jù)接口名限流
? ? ? ? ? ? RateLimiter rateLimiter = interfaces.get(request.getInterfaceName());


? ? ? ? ? ? // 獲取令牌桶中一個令牌,如果獲取不到,則等待 timeout 時間,如果還獲取不到,則返回false,反之則返回true
? ? ? ? ? ? // timeout設(shè)置為0,表示不等待
? ? ? ? ? ? if(rateLimiter.tryAcquire(1,0,TimeUnit.SECONDS)){

? ? ? ? ? ? ? ? // 得到令牌,處理請求
? ? ? ? ? ? ? ? threadPool.execute(()->{
? ? ? ? ? ? ? ? ? ? System.err.println("接口:"+request.getInterfaceName()+" 訪問還未達到上限,"+request.getUserName()+"可以訪問");
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? // 已經(jīng)等待了10秒還獲取不到令牌,進行其他業(yè)務(wù)處理
? ? ? ? ? ? ? ? System.err.println("當前時間訪問失敗,"+request.getUserName()+"無法獲取令牌");
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ? 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;}
? ? }
}

場景二:

當我們希望某一個用戶或者ip,每秒的訪問量不超過10

package org.xhs.test;

import org.apache.curator.shaded.com.google.common.util.concurrent.RateLimiter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;


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

? ? /**
? ? ?* 存儲用戶名和令牌生成器的對應(yīng)關(guān)系
? ? ?*/
? ?private static Map<String, RateLimiter> interfaces = new ConcurrentHashMap<>();

? ? /**
? ? ?* 線程池
? ? ?*/
? ? private static ExecutorService threadPool = new ThreadPoolExecutor(10,15,3,TimeUnit.SECONDS,new ArrayBlockingQueue<>(100));

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

? ? ? ? List<UserRequest> tasks = new ArrayList<UserRequest>();
? ? ? ? // 準備工作,先初始化 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) {
? ? ? ? ? ? // 根據(jù)接口名限流
? ? ? ? ? ? RateLimiter rateLimiter = interfaces.get(request.getUserName());

? ? ? ? ? ? if(rateLimiter==null){
? ? ? ? ? ? ? ? // 創(chuàng)建一個令牌生成器,每秒產(chǎn)生5個令牌
? ? ? ? ? ? ? ? synchronized (interfaces) {
? ? ? ? ? ? ? ? ? ? if(rateLimiter==null) {
? ? ? ? ? ? ? ? ? ? ? ? rateLimiter = RateLimiter.create(10);
? ? ? ? ? ? ? ? ? ? ? ? // 將這個令牌生成器和具體的接口進行綁定
? ? ? ? ? ? ? ? ? ? ? ? interfaces.put(request.getUserName(),rateLimiter);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? // 休眠一秒,讓令牌生成器先生成令牌
? ? ? ? Thread.sleep(1000);

? ? ? ? for (UserRequest request : tasks) {
? ? ? ? ? ? // 根據(jù)接口名限流
? ? ? ? ? ? RateLimiter rateLimiter = interfaces.get(request.getUserName());


? ? ? ? ? ? // 獲取令牌桶中一個令牌,如果獲取不到,則等待 timeout 時間,如果還獲取不到,則返回false,反之則返回true
? ? ? ? ? ? // timeout設(shè)置為0,表示不等待
? ? ? ? ? ? if(rateLimiter.tryAcquire(1,0,TimeUnit.SECONDS)){

? ? ? ? ? ? ? ? // 得到令牌,處理請求
? ? ? ? ? ? ? ? threadPool.execute(()->{
? ? ? ? ? ? ? ? ? ? System.err.println("用戶:"+request.getUserName()+" 當前時間訪問次數(shù)還未達到上限,可以訪問");
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? // 已經(jīng)等待了10秒還獲取不到令牌,進行其他業(yè)務(wù)處理
? ? ? ? ? ? ? ? System.err.println("當前時間訪問失敗,"+request.getUserName()+"無法獲取令牌");
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ? 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)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 線程安全的單例模式的幾種實現(xiàn)方法分享

    線程安全的單例模式的幾種實現(xiàn)方法分享

    線程安全的單例模式實現(xiàn)有幾種思路,個人認為第2種方案最優(yōu)雅:、餓漢式、借助內(nèi)部類、普通加鎖解決、雙重檢測,但要注意寫法,如果單體模式繼續(xù)擴展為N元單體模式,那就是對象池模式了
    2014-02-02
  • Java8中用foreach循環(huán)獲取對象的index下標詳解

    Java8中用foreach循環(huán)獲取對象的index下標詳解

    這篇文章主要給大家介紹了關(guān)于Java8中用foreach循環(huán)獲取對象的index下標的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • MybatisPlus查詢條件為空字符串或null問題及解決

    MybatisPlus查詢條件為空字符串或null問題及解決

    這篇文章主要介紹了MybatisPlus查詢條件為空字符串或null問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 輕松掌握Java命令模式

    輕松掌握Java命令模式

    這篇文章主要幫助大家輕松掌握Java命令模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Springboot常用注解及作用說明

    Springboot常用注解及作用說明

    這篇文章主要介紹了Springboot常用注解及作用說明,Springboot開發(fā)中注解是非常重要的不可或缺的,那么Springboot中有哪些常用的注解呢,今天我們就來看一下這些注解和其作用,需要的朋友可以參考下
    2023-08-08
  • 詳解用java描述矩陣求逆的算法

    詳解用java描述矩陣求逆的算法

    這篇文章主要介紹了用java描述矩陣求逆的算法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • Java均攤復雜度和防止復雜度的震蕩原理分析

    Java均攤復雜度和防止復雜度的震蕩原理分析

    這篇文章主要介紹了Java均攤復雜度和防止復雜度的震蕩,結(jié)合實例形式分析了Java均攤復雜度和防止復雜度的震蕩相關(guān)概念、原理、實現(xiàn)方法與注意事項,需要的朋友可以參考下
    2020-03-03
  • Springboot整合JPA配置多數(shù)據(jù)源流程詳解

    Springboot整合JPA配置多數(shù)據(jù)源流程詳解

    這篇文章主要介紹了Springboot整合JPA配置多數(shù)據(jù)源,JPA可以通過實體類生成數(shù)據(jù)庫的表,同時自帶很多增刪改查方法,大部分sql語句不需要我們自己寫,配置完成后直接調(diào)用方法即可,很方便
    2022-11-11
  • Spring表達式語言SpEL用法詳解

    Spring表達式語言SpEL用法詳解

    這篇文章主要介紹了spring表達式語言SpEL用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • Spring MVC 中 AJAX請求并返回JSON的示例

    Spring MVC 中 AJAX請求并返回JSON的示例

    本篇文章主要介紹了Spring MVC 中 AJAX請求并返回JSON,具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01

最新評論