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

java實(shí)現(xiàn)請(qǐng)求緩沖合并的示例代碼

 更新時(shí)間:2024年04月12日 11:23:56   作者:muguazhi  
我們對(duì)外提供了一個(gè)rest接口給第三方業(yè)務(wù)進(jìn)行調(diào)用,但是由于第三方框架限制,導(dǎo)致會(huì)發(fā)送大量相似無(wú)效請(qǐng)求,這篇文章主要介紹了java實(shí)現(xiàn)請(qǐng)求緩沖合并,需要的朋友可以參考下

業(yè)務(wù)背景:

我們對(duì)外提供了一個(gè)rest接口給第三方業(yè)務(wù)進(jìn)行調(diào)用,但是由于第三方框架限制,導(dǎo)致會(huì)發(fā)送大量相似無(wú)效請(qǐng)求,例如:接口入?yún)son包含兩個(gè)字段,createBy和receiverList,完整的入?yún)son示例如下:

{
	"createBy": "aa",
	"receiverList": [
		"bb",
		"cc"
	]
}

實(shí)際第三方業(yè)務(wù)會(huì)進(jìn)行多次調(diào)用接口,每次傳遞的數(shù)據(jù)可能如下:

{
	"createBy": "aa",
	"receiverList": [
		"bb"
	]
}
或者
{
	"createBy": "aa",
	"receiverList": [
		"cc"
	]
}
或者
{
	"createBy": "bb",
	"receiverList": [
		"cc"
	]
}
或者
{
	"createBy": "aa",
	"receiverList": [
		"bb",
		"cc"
	]
}

所有需要對(duì)第三方業(yè)務(wù)傳遞過(guò)來(lái)的數(shù)據(jù)進(jìn)行緩沖合并處理,減輕真正的后臺(tái)服務(wù)的壓力。

代碼實(shí)現(xiàn)

package com.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
 * Description: 請(qǐng)求合并管理類
 */
@Slf4j
@Component
public class RequestMerger {
    // 線程池核心線程數(shù)
    private final int corePoolSize = 200;
    // 任務(wù)執(zhí)行超時(shí)時(shí)間,單位:毫秒
    private final int timeout = 5 * 60 * 1000;
    // 隊(duì)列,隊(duì)列長(zhǎng)度為Integer.MAX_VALUE
    private final LinkedBlockingQueue<String> requestQueue = new LinkedBlockingQueue<>();
    // 定時(shí)器,所有任務(wù)共用線程池
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(corePoolSize,
            new CustomizableThreadFactory("schedule-executor-"));
    // 是否關(guān)閉標(biāo)志
    private final AtomicBoolean isShutdown = new AtomicBoolean(false);
    /**
     * 構(gòu)造函數(shù),用于初始化請(qǐng)求合并器。
     *
     * @param batchSize   每次合并的最大請(qǐng)求數(shù)量。
     * @param delayMillis 合并請(qǐng)求的周期間隔,單位為毫秒。
     */
    public RequestMerger(int batchSize, long delayMillis) {
        // 啟動(dòng)定時(shí)器,定期合并請(qǐng)求,延遲delayMillis后開(kāi)始,之后每隔delayMillis執(zhí)行一次
        scheduler.scheduleAtFixedRate(() -> {
            if (!isShutdown.get()) {
                List<String> batch = new ArrayList<>(batchSize);
                int drainedCount = requestQueue.drainTo(batch, batchSize);
                log.info("==>scheduler,drainedCount:{},nowQueueCount:{}", drainedCount, requestQueue.size());
                if (!batch.isEmpty()) {
                    // 異步執(zhí)行任務(wù),防止業(yè)務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致業(yè)務(wù)整體延遲過(guò)大
                    scheduler.submit(() -> {
                        sendRequestBatch(batch);
                    });
                }
            }
        }, delayMillis, delayMillis, TimeUnit.MILLISECONDS);
    }
    /**
     * 發(fā)送請(qǐng)求批次的方法。
     *
     * @param batch 請(qǐng)求批次。
     */
    private void sendRequestBatch(List<String> batch) {
        Future<?> future = scheduler.submit(() -> {
            try {
                // 在這里實(shí)現(xiàn)你的請(qǐng)求發(fā)送邏輯
                // 可以使用HTTP客戶端庫(kù)(如Apache HttpClient或OkHttp)來(lái)發(fā)送請(qǐng)求
                // ...
                System.out.println("Sending batch of " + batch.size() + " requests");
            } catch (Exception e) {
                // 異常處理邏輯
                System.err.println("Error sending requests: " + e.getMessage());
            }
        });
        // 嘗試獲取任務(wù)結(jié)果,如果超過(guò)超時(shí)時(shí)間則拋出TimeoutException異常,進(jìn)行取消任務(wù)
        try {
            // 超時(shí)時(shí)間,單位:毫秒
            future.get(timeout, TimeUnit.MILLISECONDS);
        } catch (TimeoutException | ExecutionException e) {
            // 超時(shí)或執(zhí)行異常時(shí)取消任務(wù)
            future.cancel(true);
        } catch (Exception e) {
            log.error("==>任務(wù)執(zhí)行異常", e);
            // 任務(wù)執(zhí)行異常
            future.cancel(true);
        }
    }
    /**
     * 在對(duì)象銷毀前執(zhí)行的關(guān)閉操作。
     * 該方法從請(qǐng)求隊(duì)列中拉取所有未處理的請(qǐng)求,并將它們批量發(fā)送。
     * 無(wú)參數(shù)和返回值。
     */
    @PreDestroy
    public void shutdown() {
        isShutdown.set(true);
        List<String> batch = new ArrayList<>();
        // 獲取請(qǐng)求隊(duì)列中的剩余所有請(qǐng)求
        int drainedCount = requestQueue.drainTo(batch);
        log.info("==>shutdown,drainedCount:{},nowQueueCount:{}", drainedCount, requestQueue.size());
        // 批量發(fā)送收集到的剩余請(qǐng)求
        sendRequestBatch(batch);
        // 關(guān)閉定時(shí)執(zhí)行器
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
                log.error("Scheduler did not terminate gracefully within 60 seconds, force shutting down.");
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            log.warn("Interrupted during scheduler termination, force shutting down.");
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
    /**
     * 向請(qǐng)求隊(duì)列中添加一個(gè)請(qǐng)求。如果服務(wù)未關(guān)閉,則直接添加到請(qǐng)求隊(duì)列中;
     * 如果服務(wù)已關(guān)閉,則將該請(qǐng)求作為一批請(qǐng)求發(fā)送。
     *
     * @param request 要添加的請(qǐng)求字符串。
     */
    public void addRequest(String request) throws InterruptedException {
        // 檢查服務(wù)是否已關(guān)閉
        if (!isShutdown.get()) {
            // 未關(guān)閉,直接添加到請(qǐng)求隊(duì)列
            requestQueue.put(request);
        } else {
            // 已關(guān)閉,將當(dāng)前請(qǐng)求作為一批發(fā)送
            List<String> batch = new ArrayList<>();
            batch.add(request);
            sendRequestBatch(batch);
        }
    }
}

參考資料

https://gitee.com/huangjuncong/mumux-framework/tree/master/merge-request/src/main/java/com/mumux/concurrent

注意:此代碼容易導(dǎo)致數(shù)據(jù)丟失。例如:調(diào)用add方法將10個(gè)元素放入隊(duì)列,但是真正獲取到9個(gè)元素。
造成原因:FlushThread#add()中使用offer方法將數(shù)據(jù)放入隊(duì)列,如果此時(shí)隊(duì)列已滿,返回值為false,實(shí)際數(shù)據(jù)未進(jìn)入隊(duì)列,需要額外對(duì)數(shù)據(jù)進(jìn)行處理。
修改建議:調(diào)大隊(duì)列長(zhǎng)度,并且將offer方法改為put方法,保證數(shù)據(jù)最終進(jìn)入隊(duì)列。

到此這篇關(guān)于java實(shí)現(xiàn)請(qǐng)求緩沖合并的文章就介紹到這了,更多相關(guān)java請(qǐng)求緩沖合并內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java捕獲異常信息存入txt文件示例

    java捕獲異常信息存入txt文件示例

    這篇文章主要介紹了java捕獲異常信息存入txt文件示例,需要的朋友可以參考下
    2014-04-04
  • 淺談Spring中@Transactional事務(wù)回滾及示例(附源碼)

    淺談Spring中@Transactional事務(wù)回滾及示例(附源碼)

    本篇文章主要介紹了淺談Spring中@Transactional事務(wù)回滾及示例(附源碼),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • IDEA實(shí)用好用插件推薦及使用方法教程詳解(必看)

    IDEA實(shí)用好用插件推薦及使用方法教程詳解(必看)

    這篇文章主要介紹了IDEA實(shí)用好用插件推薦及使用方法教程,本文通過(guò)實(shí)例截圖相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • MyBatis Mapper.xml中的命名空間及命名方式

    MyBatis Mapper.xml中的命名空間及命名方式

    這篇文章主要介紹了MyBatis Mapper.xml中的命名空間及命名方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java調(diào)用Python腳本傳遞數(shù)據(jù)并返回計(jì)算結(jié)果

    Java調(diào)用Python腳本傳遞數(shù)據(jù)并返回計(jì)算結(jié)果

    實(shí)際工程項(xiàng)目中可能會(huì)用到Java和python兩種語(yǔ)言結(jié)合進(jìn)行,這樣就會(huì)涉及到一個(gè)問(wèn)題,Java如何調(diào)用Python腳本,感興趣的可以了解一下
    2021-05-05
  • Spring如何自定義加載配置文件(分層次加載)

    Spring如何自定義加載配置文件(分層次加載)

    這篇文章主要介紹了Spring如何自定義加載配置文件(分層次加載)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列的示例

    Java用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列的示例

    下面小編就為大家?guī)?lái)一篇Java用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列的示例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • 基于HTML5+js+Java實(shí)現(xiàn)單文件文件上傳到服務(wù)器功能

    基于HTML5+js+Java實(shí)現(xiàn)單文件文件上傳到服務(wù)器功能

    應(yīng)公司要求,在HTML5頁(yè)面上實(shí)現(xiàn)上傳文件到服務(wù)器功能,對(duì)于我這樣的菜鳥,真是把我難住了,最后還是請(qǐng)教大神搞定的,下面小編把例子分享到腳本之家平臺(tái),供大家參考
    2017-08-08
  • 最流行的java后臺(tái)框架spring quartz定時(shí)任務(wù)

    最流行的java后臺(tái)框架spring quartz定時(shí)任務(wù)

    近日項(xiàng)目開(kāi)發(fā)中需要執(zhí)行一些定時(shí)任務(wù),比如需要在每天凌晨時(shí)候,分析一次前一天的日志信息,借此機(jī)會(huì)整理了一下定時(shí)任務(wù)的幾種實(shí)現(xiàn)方式,由于項(xiàng)目采用spring框架,所以我都將結(jié)合spring框架來(lái)介紹
    2015-12-12
  • SpringBoot定制JSON響應(yīng)數(shù)據(jù)的實(shí)現(xiàn)

    SpringBoot定制JSON響應(yīng)數(shù)據(jù)的實(shí)現(xiàn)

    本文主要介紹了SpringBoot定制JSON響應(yīng)數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02

最新評(píng)論