第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會有你想問的

Java中的連接池和線程池設(shè)置

Java中的連接池和線程池設(shè)置

慕虎7371278 2023-10-13 16:35:44
使用 Hikari 池的 Spring 應(yīng)用程序?,F(xiàn)在,對于來自客戶端的單個(gè)請求,我必須查詢 10 個(gè)表(業(yè)務(wù)需要),然后將結(jié)果組合在一起。而查詢每個(gè)表可能要花費(fèi)50ms到200ms。為了加快響應(yīng)時(shí)間,我FixedThreadPool在服務(wù)中創(chuàng)建一個(gè)來查詢不同線程中的每個(gè)表(偽代碼):class MyService{    final int THREAD_POOL_SIZE = 20;    final int CONNECTION_POOL_SIZE = 10;    final ExecutorService pool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);    protected DataSource ds;    MyClass(){        Class.forName(getJdbcDriverName());        HikariConfig config = new HikariConfig();        config.setMaximumPoolSize(CONNECTION_POOL_SIZE);        ds = new HikariDataSource(config);    }    public Items doQuery(){        String[] tables=["a","b"......]; //10+ tables        Items result=new Items();        CompletionService<Items> executorService = new ExecutorCompletionService<Items>(pool);        for (String tb : tables) {            Callable<Item> c = () -> {                Items items = ds.getConnection().query(tb); ......                return Items;            };            executorService.submit(c);        }        for (String tb: tables) {            final Future<Items> future = executorService.take();            Items items = future.get();            result.addAll(items);        }    }}現(xiàn)在對于單個(gè)請求,平均響應(yīng)時(shí)間可能是 500ms。但對于并發(fā)請求,平均響應(yīng)時(shí)間會迅速增加,請求越多,響應(yīng)時(shí)間就越長。我想知道如何設(shè)置正確的連接池大小和線程池大小以使應(yīng)用程序有效工作?順便說一句,數(shù)據(jù)庫在云中使用 RDS,具有 4 個(gè) cpu 16GB 內(nèi)存,最大連接數(shù)為 2000,最大 IOPS 為 8000。
查看完整描述

3 回答

?
DIEA

TA貢獻(xiàn)1820條經(jīng)驗(yàn) 獲得超2個(gè)贊

您可能需要考慮更多參數(shù):
1. 數(shù)據(jù)庫的最大并發(fā)請求參數(shù)。云提供商對不同層的并發(fā)請求有不同的限制,您可能需要檢查您的。

2.當(dāng)你說50-200ms時(shí),雖然很難說,但是平均有8個(gè)50ms的請求和2個(gè)200ms的請求還是都差不多?為什么?您的 doQuery 可能會受到查詢占用最大時(shí)間(即 200 毫秒)的限制,但花費(fèi) 50 毫秒的線程將在其任務(wù)完成后被釋放,使其可用于下一組請求。

3. 您期望獲得的 QPS 是多少?

一些計(jì)算:如果單個(gè)請求需要 10 個(gè)線程,并且您配置了 100 個(gè)連接和 100 個(gè)并發(fā)查詢限制,假設(shè)每個(gè)查詢 200 毫秒,那么您一次只能處理 10 個(gè)請求。如果大多數(shù)查詢需要 50 毫秒左右的話,可能會比 10 好一點(diǎn)(但我并不樂觀)。

當(dāng)然,如果您的任何查詢花費(fèi)> 200毫秒(網(wǎng)絡(luò)延遲或其他任何東西),那么其中一些計(jì)算就會被折騰,在這種情況下,我建議您在連接端有一個(gè)斷路器(如果允許您中止)超時(shí)后的查詢)或在 API 端。

注意最大連接限制與最大并發(fā)查詢限制不同。

建議:由于您需要 500 毫秒以下的響應(yīng),因此您還可以在池上設(shè)置約 100-150 毫秒的連接超時(shí)。最壞情況:150 毫秒連接超時(shí) + 200 毫秒查詢執(zhí)行 + 100 毫秒應(yīng)用程序處理 < 500 毫秒響應(yīng)。作品。


查看完整回答
反對 回復(fù) 2023-10-13
?
慕的地10843

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超8個(gè)贊

您可以創(chuàng)建自定義線程執(zhí)行器


public class CustomThreadPoolExecutor extends ThreadPoolExecutor {


    private CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize,

                                     long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {

        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);

    }


    /**

     * Returns a fixed thread pool where task threads take Diagnostic Context from the submitting thread.

     */


    public static ExecutorService newFixedThreadPool(int nThreads) {

        return new CustomThreadPoolExecutor(nThreads, nThreads,

                0L, TimeUnit.MILLISECONDS,

                new LinkedBlockingQueue<Runnable>());

    }

}

在配置中,您可以如下配置ExecutorService bean


@Bean

    public ExecutorService executeService() {

        return CustomThreadPoolExecutor.newFixedThreadPool(10);

    }

這是創(chuàng)建自定義線程池執(zhí)行器的最佳實(shí)踐


查看完整回答
反對 回復(fù) 2023-10-13
?
守著一只汪

TA貢獻(xiàn)1872條經(jīng)驗(yàn) 獲得超4個(gè)贊

調(diào)整連接池大小的正確方法通常是將其保留為默認(rèn)值。

如果您有 10,000 個(gè)前端用戶,那么擁有 10,000 個(gè)連接池將是瘋狂的。1000還是太恐怖了?即使是 100 個(gè)連接,也太過分了。您需要一個(gè)最多包含幾十個(gè)連接的小型池,并且希望其余應(yīng)用程序線程阻塞在池中等待連接。如果池經(jīng)過適當(dāng)調(diào)整,它將被設(shè)置為數(shù)據(jù)庫能夠同時(shí)處理的查詢數(shù)量的限制——如上所述,該限制很少超過(CPU 核心 * 2)。

如果您知道每個(gè)請求將消耗 10 個(gè)線程,那么您想打破這個(gè)建議并采用更多線程 - 將其保持在小于 100 的數(shù)字可能會提供足夠的容量。

我會像這樣實(shí)現(xiàn)控制器:

使用 s讓您的控制器/服務(wù)類中的查詢異步CompletableFuture,并讓連接池?fù)?dān)心保持其線程繁忙。

所以控制器可能看起來像這樣(我從其他一些代碼中改編了它,這些代碼不像這個(gè)例子那樣工作,所以對這段代碼持懷疑態(tài)度):

public class AppController {?


? ? @Autowired private DatabaseService databaseService;?


? ? public ResponseEntity<Thing> getThing() {?

? ? ? ? CompletableFuture<Foo> foo = CompletableFuture.runAsync(databaseService.getFoo());

? ? ? ? CompletableFuture<Bar> bar = CompletableFuture.runAsync(databaseService.getBar());

? ? ? ? CompletableFuture<Baz> baz = CompletableFuture.runAsync(databaseService.getBaz());


? ? ? ? // muck around with the completable future to return your data in the right way

? ? ? ? // this will be in there somewhere, followed by a .thenApply and .join

? ? ? ? CompletableFuture<Void> allFutures = CompletableFuture.allOf(foo, bar, baz);


? ? ? ? return new ResponseEntity<Thing>(mashUpDbData(cf.get()));

? ? }? ??

}

控制器將生成您允許ForkJoinPool使用的盡可能多的線程,它們將同時(shí)錘擊所有數(shù)據(jù)庫,并且連接池可以擔(dān)心保持連接處于活動(dòng)狀態(tài)。

但我認(rèn)為您在小負(fù)載下看到響應(yīng)時(shí)間井噴的原因是,根據(jù) JDBC 的設(shè)計(jì),它會在等待數(shù)據(jù)從數(shù)據(jù)庫返回時(shí)阻塞線程。

要阻止阻塞對響應(yīng)時(shí)間產(chǎn)生如此大的影響,您可以嘗試Spring Boot 反應(yīng)式。這使用異步 io 和背壓來匹配 IO 生產(chǎn)和消耗,基本上這意味著應(yīng)用程序線程盡可能繁忙。這應(yīng)該會阻止響應(yīng)時(shí)間以線性方式增加的負(fù)載下的行為。

請注意,如果您確實(shí)采用反應(yīng)式路徑,jdbc 驅(qū)動(dòng)程序仍然會阻塞,因此 spring 大力推動(dòng)創(chuàng)建反應(yīng)式數(shù)據(jù)庫驅(qū)動(dòng)程序。


查看完整回答
反對 回復(fù) 2023-10-13
  • 3 回答
  • 0 關(guān)注
  • 164 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號