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

Java面試之限流的實(shí)現(xiàn)方式小結(jié)

 更新時(shí)間:2024年02月27日 10:47:04   作者:Java面試真題解析  
限流是指在各種應(yīng)用場(chǎng)景中,通過(guò)技術(shù)和策略手段對(duì)數(shù)據(jù)流量、請(qǐng)求頻率或資源消耗進(jìn)行有計(jì)劃的限制,本文為大家整理了常見的限流的實(shí)現(xiàn)方式,有需要的可以參考下

限流是指在各種應(yīng)用場(chǎng)景中,通過(guò)技術(shù)和策略手段對(duì)數(shù)據(jù)流量、請(qǐng)求頻率或資源消耗進(jìn)行有計(jì)劃的限制,以避免系統(tǒng)負(fù)載過(guò)高、性能下降甚至崩潰的情況發(fā)生。限流的目標(biāo)在于維護(hù)系統(tǒng)的穩(wěn)定性和可用性,并確保服務(wù)質(zhì)量。

使用限流的好處有以下幾個(gè):

  • 保護(hù)系統(tǒng)穩(wěn)定性:過(guò)多的并發(fā)請(qǐng)求可能導(dǎo)致服務(wù)器內(nèi)存耗盡、CPU 使用率飽和,從而引發(fā)系統(tǒng)響應(yīng)慢、無(wú)法正常服務(wù)的問(wèn)題。
  • 防止資源濫用:確保有限的服務(wù)資源被合理公平地分配給所有用戶,防止個(gè)別用戶或惡意程序過(guò)度消耗資源。
  • 優(yōu)化用戶體驗(yàn):對(duì)于網(wǎng)站和應(yīng)用程序而言,如果任由高并發(fā)導(dǎo)致響應(yīng)速度變慢,會(huì)影響所有用戶的正常使用體驗(yàn)。
  • 保障安全:在網(wǎng)絡(luò)層面,限流有助于防范 DoS/DDoS 攻擊,降低系統(tǒng)遭受惡意攻擊的風(fēng)險(xiǎn)。
  • 運(yùn)維成本控制:合理的限流措施可以幫助企業(yè)減少不必要的硬件投入,節(jié)省運(yùn)營(yíng)成本。

在 Java 中,限流的實(shí)現(xiàn)方式有很多種,例如以下這些:

  • 單機(jī)限流:使用 JUC 下的 Semaphore 限流,或一些常用的框架,例如 Google 的 Guava 框架進(jìn)行限流,但這種限流方式都是基于 JVM 層面的內(nèi)存級(jí)別的單臺(tái)機(jī)器限流。
  • 網(wǎng)關(guān)層限流:?jiǎn)螜C(jī)限流往往不適用于分布式系統(tǒng),而分布式系統(tǒng)可以在網(wǎng)關(guān)層限流,如 Spring Cloud Gateway 通過(guò) Sentinel、Hystrix 對(duì)整個(gè)集群進(jìn)行限流。
  • Nginx 限流:通常在網(wǎng)關(guān)層的上游,我們會(huì)使用 Nginx 一起來(lái)配合使用,也就是用戶請(qǐng)求會(huì)先到 Nginx(或 Nginx 集群),然后再將請(qǐng)求轉(zhuǎn)發(fā)給網(wǎng)關(guān),網(wǎng)關(guān)再調(diào)用其他的微服務(wù),從而實(shí)現(xiàn)整個(gè)流程的請(qǐng)求調(diào)用,因此 Nginx 限流也是分布式系統(tǒng)中常用的限流手段。

它們限流的具體實(shí)現(xiàn)如下。

1.單機(jī)限流

JVM 層面多線程級(jí)別的限流可以使用 JUC 下的 Semaphore,具體使用示例如下:

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreExample {

    private final Semaphore semaphore = new Semaphore(5); // 只允許5個(gè)線程同時(shí)訪問(wèn)

    public void accessResource() {
        try {
            semaphore.acquire(); // 獲取許可,如果當(dāng)前許可數(shù)不足,則會(huì)阻塞
            System.out.println(Thread.currentThread().getName() + "獲得了許可,正在訪問(wèn)資源...");
            // 模擬訪問(wèn)資源的時(shí)間消耗
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + "訪問(wèn)資源結(jié)束,釋放許可...");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        } finally {
            semaphore.release(); // 訪問(wèn)結(jié)束后釋放許可
        }
    }

    public static void main(String[] args) {
        SemaphoreExample example = new SemaphoreExample();

        for (int i = 0; i < 10; i++) {
            new Thread(() -> example.accessResource()).start();
        }
    }
}

想要實(shí)現(xiàn)更平滑的單機(jī)限流,可以考慮 Google 提供的 Guava 框架,它的使用示例如下。

首先在 pom.xml 添加 guava 引用,配置如下:

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>28.2-jre</version>
</dependency>

具體實(shí)現(xiàn)代碼如下:

import com.google.common.util.concurrent.RateLimiter;
import java.time.Instant;

/**
 * Guava 實(shí)現(xiàn)限流
 */
public class RateLimiterExample {
    public static void main(String[] args) {
        // 每秒產(chǎn)生 10 個(gè)令牌(每 100 ms 產(chǎn)生一個(gè))
        RateLimiter rt = RateLimiter.create(10);
        for (int i = 0; i < 11; i++) {
            new Thread(() -> {
                // 獲取 1 個(gè)令牌,獲取到令牌就執(zhí)行,否則就阻塞等待
                rt.acquire();
                System.out.println("正常執(zhí)行方法,ts:" + Instant.now());
            }).start();
        }
    }
}

2.網(wǎng)關(guān)層限流

在 Spring Cloud Gateway 網(wǎng)關(guān)層限流,可以借助 Sentinel 等限流框架來(lái)實(shí)現(xiàn),它的實(shí)現(xiàn)步驟如下。

首先,在 pom.xml 中添加 Gateway 和 Sentinel 相關(guān)依賴,如下所示:

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

配置限流相關(guān)的規(guī)則,如下示例所示:

spring:
  application:
    name: gate-way-blog
  cloud:
    sentinel:
      transport:
        dashboard: localhost:18080
      scg: # 配置限流之后,響應(yīng)內(nèi)容
        fallback:
          # 兩種模式,一種是 response 返回文字提示信息,
          # 另一種是 redirect 重定向跳轉(zhuǎn),不過(guò)配置 redirect 也要配置對(duì)應(yīng)的跳轉(zhuǎn)的 uri
          mode: response
          # 響應(yīng)的狀態(tài)
          response-status: 200
          # 響應(yīng)體
          response-body: '{"code": -10,"message": "被熔斷或限流!"}'

最后在 Sentinel 控制臺(tái)配置網(wǎng)關(guān)的限流設(shè)置即可,當(dāng)然也可以使用 Nacos 作為數(shù)據(jù)源,兩者選擇配置其中一個(gè)即可。

3.Nginx 限流

Nginx 提供了兩種限流手段:

  • 通過(guò)控制速率來(lái)實(shí)現(xiàn)限流。
  • 通過(guò)控制并發(fā)連接數(shù)來(lái)實(shí)現(xiàn)限流。

我們一個(gè)一個(gè)來(lái)看。

3.1 控制速率實(shí)現(xiàn)限流

我們需要使用 limit_req_zone 用來(lái)限制單位時(shí)間內(nèi)的請(qǐng)求數(shù),即速率限制,示例配置如下:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
server {
  location / {
    limit_req zone=mylimit;
  }
}

以上配置表示,限制每個(gè) IP 訪問(wèn)的速度為 2r/s,因?yàn)?Nginx 的限流統(tǒng)計(jì)是基于毫秒的,我們?cè)O(shè)置的速度是 2r/s,轉(zhuǎn)換一下就是 500ms 內(nèi)單個(gè) IP 只允許通過(guò) 1 個(gè)請(qǐng)求,從 501ms 開始才允許通過(guò)第 2 個(gè)請(qǐng)求。

我們使用單 IP 在 10ms 內(nèi)發(fā)并發(fā)送了 6 個(gè)請(qǐng)求的執(zhí)行結(jié)果如下:

從以上結(jié)果可以看出他的執(zhí)行符合我們的預(yù)期,只有 1 個(gè)執(zhí)行成功了,其他的 5 個(gè)被拒絕了(第 2 個(gè)在 501ms 才會(huì)被正常執(zhí)行)。

速率限制升級(jí)版

上面的速率控制雖然很精準(zhǔn)但是應(yīng)用于真實(shí)環(huán)境未免太苛刻了,真實(shí)情況下我們應(yīng)該控制一個(gè) IP 單位總時(shí)間內(nèi)的總訪問(wèn)次數(shù),而不是像上面那么精確但毫秒,我們可以使用 burst 關(guān)鍵字開啟此設(shè)置,示例配置如下:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
server {
  location / {
    limit_req zone=mylimit burst=4;
  }
}

burst=4 表示每個(gè) IP 最多允許4個(gè)突發(fā)請(qǐng)求,如果單個(gè) IP 在 10ms 內(nèi)發(fā)送 6 次請(qǐng)求的結(jié)果如下:

從以上結(jié)果可以看出,有 1 個(gè)請(qǐng)求被立即處理了,4 個(gè)請(qǐng)求被放到 burst 隊(duì)列里排隊(duì)執(zhí)行了,另外 1 個(gè)請(qǐng)求被拒絕了。

3.2 控制并發(fā)數(shù)實(shí)現(xiàn)限流

利用 limit_conn_zone 和 limit_conn 兩個(gè)指令即可控制并發(fā)數(shù),示例配置如下:

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
  ...
  limit_conn perip 10;
  limit_conn perserver 100;
}

其中 limit_conn perip 10 表示限制單個(gè) IP 同時(shí)最多能持有 10 個(gè)連接;limit_conn perserver 100 表示 server 同時(shí)能處理并發(fā)連接的總數(shù)為 100 個(gè)。

小貼士:只有當(dāng) request header 被后端處理后,這個(gè)連接才進(jìn)行計(jì)數(shù)。

課后思考

Semaphore 限流和 Guava 限流有什么區(qū)別?Sentinel 和 Nginx 限流有什么不足?應(yīng)該如何避免?

到此這篇關(guān)于Java面試之限流的實(shí)現(xiàn)方式小結(jié)的文章就介紹到這了,更多相關(guān)Java限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 中sendredirect()和forward()方法的區(qū)別

    java 中sendredirect()和forward()方法的區(qū)別

    這篇文章主要介紹了java 中sendredirect()和forward()方法的區(qū)別,需要的朋友可以參考下
    2017-08-08
  • java?集合工具類Collections及Comparable和Comparator排序詳解

    java?集合工具類Collections及Comparable和Comparator排序詳解

    這篇文章主要介紹了java集合工具類Collections及Comparable和Comparator排序詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • 計(jì)算Java數(shù)組長(zhǎng)度函數(shù)的方法以及代碼分析

    計(jì)算Java數(shù)組長(zhǎng)度函數(shù)的方法以及代碼分析

    在本篇內(nèi)容里,小編給大家整理了關(guān)于計(jì)算Java數(shù)組長(zhǎng)度函數(shù)的方法以及代碼分析內(nèi)容,有興趣的朋友么可以學(xué)習(xí)參考下。
    2022-11-11
  • java中接口(interface)及使用方法示例

    java中接口(interface)及使用方法示例

    這篇文章主要介紹了java中接口(interface)及使用方法示例,涉及接口定義的簡(jiǎn)單介紹以及Java語(yǔ)言代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-11-11
  • spring?boot集成smart-doc自動(dòng)生成接口文檔詳解

    spring?boot集成smart-doc自動(dòng)生成接口文檔詳解

    這篇文章主要介紹了spring?boot集成smart-doc自動(dòng)生成接口文檔詳解,smart-doc是一款同時(shí)支持java?restful?api和Apache?Dubbo?rpc接口文檔生成的工具,smart-doc顛覆了傳統(tǒng)類似swagger這種大量采用注解侵入來(lái)生成文檔的實(shí)現(xiàn)方法
    2022-09-09
  • 解析Java中的默認(rèn)方法

    解析Java中的默認(rèn)方法

    這篇文章主要介紹了Java中的默認(rèn)方法,包括繼承和調(diào)用等Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-07-07
  • java中元素排序Comparable和Comparator的區(qū)別

    java中元素排序Comparable和Comparator的區(qū)別

    本文主要介紹了java中元素排序Comparable和Comparator的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Java使用Spire.Barcode for Java實(shí)現(xiàn)條形碼生成與識(shí)別

    Java使用Spire.Barcode for Java實(shí)現(xiàn)條形碼生成與識(shí)別

    在現(xiàn)代商業(yè)和技術(shù)領(lǐng)域,條形碼無(wú)處不在,本教程將引導(dǎo)您深入了解如何在您的 Java 項(xiàng)目中利用 Spire.Barcode for Java 輕松實(shí)現(xiàn)條形碼的生成與識(shí)別,希望可以助大家解決實(shí)際開發(fā)中的痛點(diǎn)
    2025-12-12
  • Java基礎(chǔ)之淺談hashCode()和equals()

    Java基礎(chǔ)之淺談hashCode()和equals()

    今天給大家?guī)?lái)的是關(guān)于Java基礎(chǔ)的相關(guān)知識(shí),文章圍繞著hashCode()和equals()展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringBoot參數(shù)校驗(yàn)Validator框架詳解

    SpringBoot參數(shù)校驗(yàn)Validator框架詳解

    Validator框架就是為了解決開發(fā)人員在開發(fā)的時(shí)候少寫代碼,提升開發(fā)效率,Validator專門用來(lái)進(jìn)行接口參數(shù)校驗(yàn),今天通過(guò)本文給大家介紹SpringBoot參數(shù)校驗(yàn)Validator框架,感興趣的朋友一起看看吧
    2022-06-06

最新評(píng)論

淮南市| 湘潭县| 台北县| 汝南县| 云南省| 内黄县| 涞水县| 嘉义市| 阜南县| 石林| 韩城市| 南丰县| 高阳县| 耒阳市| 日喀则市| 宝应县| 澄迈县| 舒兰市| 桃源县| 黄陵县| 银川市| 长海县| 淮安市| 桐城市| 马鞍山市| 龙里县| 改则县| 民和| 河北区| 东光县| 济南市| 安化县| 德庆县| 喜德县| 习水县| 云浮市| 河西区| 乌鲁木齐市| 高唐县| 彭州市| 永川市|