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

springboot內(nèi)置tomcat調(diào)優(yōu)并發(fā)線程數(shù)解析

 更新時(shí)間:2021年12月29日 10:01:59   作者:CRUD的W  
這篇文章主要介紹了springboot內(nèi)置tomcat調(diào)優(yōu)并發(fā)線程數(shù)解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

本文解析springboot內(nèi)置tomcat調(diào)優(yōu)并發(fā)線程數(shù)的一些參數(shù),并結(jié)合源碼進(jìn)行分析

參數(shù)

線程池核心線程數(shù)

  • server.tomcat.min-spare-threads:該參數(shù)為tomcat處理業(yè)務(wù)的核心線程數(shù)大小,默認(rèn)值為10

線程池最大線程數(shù)

  • server.tomcat.max-threads:該參數(shù)為tomcat處理業(yè)務(wù)的最大線程數(shù)大小,默認(rèn)值為200,當(dāng)對(duì)并發(fā)量有一點(diǎn)值時(shí)可以調(diào)大該參數(shù)

請(qǐng)求最大連接數(shù)

  • server.tomcat.max-connections:該參數(shù)為請(qǐng)求的最大連接數(shù),默認(rèn)值為10000,注意這個(gè)參數(shù)并不是設(shè)置在線程池上的,而是在tomcat的Acceptor類(lèi)(專(zhuān)門(mén)處理連接的線程類(lèi))來(lái)控制的,結(jié)合源碼我們可以看到

在這里插入圖片描述

protected void countUpOrAwaitConnection() throws InterruptedException {
        if (maxConnections==-1) return;
        LimitLatch latch = connectionLimitLatch;
        if (latch!=null) latch.countUpOrAwait();
    }

可以看到當(dāng)最大連接數(shù)滿(mǎn)了之后會(huì)進(jìn)行等待

accept-count

server.tomcat.accept-count:這個(gè)參數(shù)實(shí)際上和tomcat沒(méi)有太大關(guān)系,默認(rèn)值為100

我們先看下文檔的定義

/**
     * Allows the server developer to specify the acceptCount (backlog) that
     * should be used for server sockets. By default, this value
     * is 100.
     */
    private int acceptCount = 100;

這個(gè)參數(shù)是服務(wù)端創(chuàng)建ServerSocket時(shí)操作系統(tǒng)控制同時(shí)連接的最大數(shù)量的,服務(wù)端接收連接是通過(guò)accept()來(lái)的,accept()是非??斓模詀ccept-count的不需要太大,正常保持默認(rèn)值100即可了,acceptCount這個(gè)參數(shù)和線程池?zé)o關(guān),會(huì)被映射為backlog參數(shù),是socket的參數(shù),在源碼的使用是在NioEndpoint類(lèi)的initServerSocket方法,在tomcat中的名字是backlog在springboot內(nèi)置tomcat中名字沒(méi)有使用backlog而是使用acceptCount

serverSock.socket().bind(addr,getAcceptCount())
protected void initServerSocket() throws Exception {
        if (!getUseInheritedChannel()) {
            serverSock = ServerSocketChannel.open();
            socketProperties.setProperties(serverSock.socket());
            InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
            // 核心代碼
            serverSock.socket().bind(addr,getAcceptCount());
        } else {
            // Retrieve the channel provided by the OS
            Channel ic = System.inheritedChannel();
            if (ic instanceof ServerSocketChannel) {
                serverSock = (ServerSocketChannel) ic;
            }
            if (serverSock == null) {
                throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
            }
        }
        serverSock.configureBlocking(true); //mimic APR behavior
    }

tomcat線程池處理機(jī)制

tomcat最終使用線程池來(lái)處理業(yè)務(wù)邏輯,java默認(rèn)的線程池的規(guī)則:

核心線程數(shù)滿(mǎn)了則優(yōu)先放入隊(duì)列,當(dāng)隊(duì)列滿(mǎn)了之后才會(huì)創(chuàng)建非核心線程來(lái)處理,那么tomcat是這樣做的嗎?

首先如果tomcat這樣做,那么當(dāng)達(dá)到核心線程后后續(xù)任務(wù)就需要等待了,這顯然是不合理的,我們通過(guò)源碼來(lái)看下tomcat是如何處理的

在AbstractEndpoint的createExecutor創(chuàng)建了處理業(yè)務(wù)數(shù)據(jù)的線程池

public void createExecutor() {
        internalExecutor = true;
        TaskQueue taskqueue = new TaskQueue();
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }

主要是使用了TaskQueue隊(duì)列,ThreadPoolExecutor并不是jdk的,而是tomcat重寫(xiě)的。

我們從線程池的處理方法execute看起

public void execute(Runnable command) {
        execute(command,0,TimeUnit.MILLISECONDS);
    }
public void execute(Runnable command, long timeout, TimeUnit unit) {
        submittedCount.incrementAndGet();
        try {
        	// 核心代碼
            super.execute(command);
        } catch (RejectedExecutionException rx) {
            if (super.getQueue() instanceof TaskQueue) {
                final TaskQueue queue = (TaskQueue)super.getQueue();
                try {
                    if (!queue.force(command, timeout, unit)) {
                        submittedCount.decrementAndGet();
                        throw new RejectedExecutionException("Queue capacity is full.");
                    }
                } catch (InterruptedException x) {
                    submittedCount.decrementAndGet();
                    throw new RejectedExecutionException(x);
                }
            } else {
                submittedCount.decrementAndGet();
                throw rx;
            }
        }
    }

又調(diào)用會(huì)jdk的execute了

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        
        int c = ctl.get();
		// 1、工作線程數(shù)小于核心線程數(shù)則添加任務(wù),核心線程會(huì)處理
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
		// 2、工作線程不小于核心線程數(shù),則放到workQueue隊(duì)列中
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
		// 3、否則添加任務(wù),addWorker會(huì)進(jìn)行創(chuàng)建線程
        else if (!addWorker(command, false))
            reject(command);
    }

從這里可以看到j(luò)dk線程池的機(jī)制,tomcat使用了自己的TaskQueue隊(duì)列,所以我們看代碼2處當(dāng)核心線程用完了會(huì)調(diào)用隊(duì)列的offer方法

我們看TaskQueue的offer

public boolean offer(Runnable o) {
        //we can't do any checks
		// parent就是指線程池,沒(méi)有線程池則添加到隊(duì)列
        if (parent==null) return super.offer(o);
        //we are maxed out on threads, simply queue the object
		// 線程數(shù)量已經(jīng)達(dá)到了最大線程數(shù),那么只能添加到隊(duì)列
        if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o);
        //we have idle threads, just add it to the queue
		// 如果當(dāng)前處理的任務(wù)數(shù)量小于當(dāng)前線程池中線程的數(shù)量,那么任務(wù)放到線程池,即相當(dāng)于馬上會(huì)有空閑線程來(lái)處理
        if (parent.getSubmittedCount()<=(parent.getPoolSize())) return super.offer(o);
        //if we have less threads than maximum force creation of a new thread
		// TODO 核心代碼,如果當(dāng)前線程數(shù)量還沒(méi)有達(dá)到線程池最大線程池的數(shù)量,那么就直接創(chuàng)建線程,這里返回false
        if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false;
        //if we reached here, we need to add it to the queue
		// 最后的策略,放到隊(duì)列
        return super.offer(o);
    }

可以看到當(dāng)執(zhí)行offer時(shí),不是直接放到隊(duì)列的,當(dāng)線程池總線程數(shù)量還沒(méi)達(dá)到線程池最大線程數(shù)時(shí)會(huì)返回false,返回false時(shí)就會(huì)執(zhí)行線程池execute的代碼3處,執(zhí)行addWorker(command, false),也就開(kāi)始創(chuàng)建新的線程來(lái)處理當(dāng)前任務(wù)了

總結(jié)

tomcat主要通過(guò)使用自己的TaskQueue隊(duì)列來(lái)對(duì)線程池做出了不同的策略,也就是tomcat當(dāng)線程數(shù)大于核心數(shù)時(shí)就會(huì)直接創(chuàng)建新的線程來(lái)處理,而不是放到隊(duì)列

想了解tomcat架構(gòu)和處理流程的可以看這篇文章 m.fzitv.net/article/233207.htm

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java中的?HashMap?的加載因子是0.75原理探討

    java中的?HashMap?的加載因子是0.75原理探討

    在Java中,HashMap是一種常用的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)鍵值對(duì),它的設(shè)計(jì)目標(biāo)是提供高效的插入、查找和刪除操作,在HashMap的實(shí)現(xiàn)中,加載因子(Load?Factor)是一個(gè)重要的概念,本文將探討為什么Java中的HashMap的加載因子被設(shè)置為0.75
    2023-10-10
  • idea中解決maven包沖突的問(wèn)題(maven helper)

    idea中解決maven包沖突的問(wèn)題(maven helper)

    這篇文章主要介紹了idea中解決maven包沖突的問(wèn)題(maven helper),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • java實(shí)現(xiàn)二叉樹(shù)遍歷的三種方式

    java實(shí)現(xiàn)二叉樹(shù)遍歷的三種方式

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)二叉樹(shù)遍歷的三種方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • java的Builder原理和實(shí)現(xiàn)詳解

    java的Builder原理和實(shí)現(xiàn)詳解

    大家好,本篇文章主要講的是java的Builder原理和實(shí)現(xiàn)詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Spring MVC中自帶的跨域問(wèn)題解決方法

    Spring MVC中自帶的跨域問(wèn)題解決方法

    最近做一個(gè)微信小項(xiàng)目遇到一個(gè)跨域問(wèn)題,就是我的前端和后端是放在不同的服務(wù)器上的,然后使用opst請(qǐng)求的時(shí)候報(bào)錯(cuò),所以通過(guò)查找相關(guān)的資料終于解決了,下面這篇文章主要給大家介紹了關(guān)于Spring MVC中自帶的跨域問(wèn)題解決方法的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • Java如何批量執(zhí)行datax腳本

    Java如何批量執(zhí)行datax腳本

    這篇文章主要介紹了Java如何批量執(zhí)行datax腳本問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Java中臨時(shí)文件目錄的使用

    Java中臨時(shí)文件目錄的使用

    :Java提供了系統(tǒng)屬性java.io.tmpdir來(lái)獲取默認(rèn)臨時(shí)文件目錄,適用于不同操作系統(tǒng),使用Files.createTempFile方法創(chuàng)建臨時(shí)文件,并在不需要時(shí)應(yīng)及時(shí)刪除,下面就來(lái)介紹一下
    2024-10-10
  • SpringBoot 自動(dòng)裝配的原理詳解分析

    SpringBoot 自動(dòng)裝配的原理詳解分析

    這篇文章主要介紹了SpringBoot 自動(dòng)裝配的原理詳解分析,文章通過(guò)通過(guò)一個(gè)案例來(lái)看一下自動(dòng)裝配的效果展開(kāi)詳情,感興趣的小伙伴可以參考一下
    2022-08-08
  • Java SpringBoot模板引擎之 Thymeleaf入門(mén)詳解

    Java SpringBoot模板引擎之 Thymeleaf入門(mén)詳解

    jsp有著強(qiáng)大的功能,能查出一些數(shù)據(jù)轉(zhuǎn)發(fā)到JSP頁(yè)面以后,我們可以用jsp輕松實(shí)現(xiàn)數(shù)據(jù)的顯示及交互等,包括能寫(xiě)Java代碼。但是,SpringBoot首先是以jar的方式,不是war;其次我們的tomcat是嵌入式的,所以現(xiàn)在默認(rèn)不支持jsp
    2021-10-10
  • SpringBoot集成Zipkin實(shí)現(xiàn)分布式全鏈路監(jiān)控

    SpringBoot集成Zipkin實(shí)現(xiàn)分布式全鏈路監(jiān)控

    這篇文章主要介紹了SpringBoot集成Zipkin實(shí)現(xiàn)分布式全鏈路監(jiān)控的方法啊,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09

最新評(píng)論

吉首市| 琼结县| 大丰市| 光泽县| 吉林市| 电白县| 乾安县| 通道| 天门市| 商河县| 响水县| 彰化县| 乐山市| 永州市| 阿拉善盟| 周至县| 兴国县| 洪湖市| 和龙市| 呼和浩特市| 商城县| 松滋市| 兴和县| 澜沧| 葵青区| 新宾| 仙居县| 台中县| 水城县| 六枝特区| 嘉义市| 个旧市| 绥滨县| 乐至县| 淳安县| 葵青区| 潼关县| 工布江达县| 江孜县| 临清市| 嘉定区|