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

Java 高并發(fā)編程之最實(shí)用的任務(wù)執(zhí)行架構(gòu)設(shè)計(jì)建議收藏

 更新時(shí)間:2021年10月28日 11:37:37   作者:劍客阿良_ALiang  
高并發(fā)(High Concurrency)是互聯(lián)網(wǎng)分布式系統(tǒng)架構(gòu)設(shè)計(jì)中必須考慮的因素之一,它通常是指,通過(guò)設(shè)計(jì)保證系統(tǒng)能夠同時(shí)并行處理很多請(qǐng)求,高并發(fā)相關(guān)常用的一些指標(biāo)有響應(yīng)時(shí)間(Response Time),吞吐量(Throughput),每秒查詢率QPS(Query Per Second),并發(fā)用戶數(shù)等

前言

隨著互聯(lián)網(wǎng)與軟件的發(fā)展,除了程序員,架構(gòu)師也是越來(lái)越火的職業(yè)。他們伴隨著項(xiàng)目的整個(gè)生命過(guò)程,他們更像是傳統(tǒng)工業(yè)的設(shè)計(jì)師,將項(xiàng)目當(dāng)做生命一般細(xì)心雕琢。

目前對(duì)于項(xiàng)目架構(gòu)而言,基本都會(huì)需要設(shè)計(jì)的幾個(gè)架構(gòu)。

1、業(yè)務(wù)架構(gòu)

項(xiàng)目或者產(chǎn)品的市場(chǎng)定位、需求范圍、作用場(chǎng)景都是需要在項(xiàng)目啟動(dòng)初期進(jìn)行系統(tǒng)性分析的。在設(shè)計(jì)業(yè)務(wù)架構(gòu)中,架構(gòu)師還需要明確角色。我看過(guò)很多關(guān)于架構(gòu)的文章,談到角色的很少。

什么是角色?

例如:商場(chǎng)作為一個(gè)整體系統(tǒng),角色就有消費(fèi)者、店員、收費(fèi)員、保安等等。各個(gè)角色完成好自己角色所需要承擔(dān)的任務(wù),整體系統(tǒng)就能完美的運(yùn)行。

對(duì)應(yīng)到軟件系統(tǒng)中,根據(jù)產(chǎn)品的定位和需求,也會(huì)有著對(duì)照的角色,比如:用戶、數(shù)據(jù)審核者、產(chǎn)品制作者、運(yùn)維人員等。在項(xiàng)目啟動(dòng)初期,架構(gòu)師需要對(duì)項(xiàng)目中的每個(gè)角色做好職責(zé)定位,我相信在這點(diǎn)上,大部分開(kāi)發(fā)同學(xué)在工作中,或多或少都有過(guò)職責(zé)不明確帶來(lái)的困擾。

2、技術(shù)架構(gòu)

在軟件項(xiàng)目研發(fā)過(guò)程中,我們會(huì)用到許多外部組件。在使用組件中,架構(gòu)師必須結(jié)合業(yè)務(wù)需求合理的選擇各個(gè)組件。項(xiàng)目是個(gè)生命,她會(huì)成長(zhǎng),架構(gòu)師需要明白如果一開(kāi)始就選擇重量級(jí)組件會(huì)讓還是個(gè)孩童的項(xiàng)目不受重負(fù),架構(gòu)師也需要明白如果技術(shù)架構(gòu)的設(shè)計(jì)不具備拓展性,那么這個(gè)孩子無(wú)法茁壯成長(zhǎng)。所以技術(shù)架構(gòu)尤為重要。

3、物理架構(gòu)

物理架構(gòu)又叫做部署架構(gòu),項(xiàng)目產(chǎn)品如果要在生產(chǎn)環(huán)境穩(wěn)定運(yùn)行,一個(gè)穩(wěn)定又高效的物理架構(gòu)是必不可少的。而且往往物理架構(gòu)和技術(shù)架構(gòu)是相輔相成的,性能監(jiān)控、異常告警、業(yè)務(wù)日志等等設(shè)計(jì),都是為了讓項(xiàng)目做更好的自己。

高并發(fā)任務(wù)執(zhí)行架構(gòu)

在我十年的工作中,業(yè)務(wù)相關(guān)、中間件、大數(shù)據(jù)都有做過(guò)。本文主要分享一下高并發(fā)任務(wù)執(zhí)行框架設(shè)計(jì),會(huì)由淺入深的講述一下設(shè)計(jì)演化過(guò)程。如果你不只是想做業(yè)務(wù)后端開(kāi)發(fā),那么本文會(huì)給你一個(gè)全新的視野。

需求場(chǎng)景

我們列一下該項(xiàng)目的需求場(chǎng)景,看看工作中是否遇到過(guò)。

1、有個(gè)復(fù)雜的數(shù)據(jù)需要制作,而且制作的時(shí)間很長(zhǎng),無(wú)法讓請(qǐng)求方持續(xù)等待。所以請(qǐng)求方只能給你個(gè)回調(diào)地址,需要你完成這個(gè)制作后將產(chǎn)物通知他。

2、復(fù)雜的制作過(guò)程需要消耗資源,而且資源有限,無(wú)法無(wú)限量提供。如果你有接觸過(guò)AI,就會(huì)比較了解資源有限的感受。除了ASR、TTS這類識(shí)別類型的AI功能能做到近實(shí)時(shí)的反饋,大部分的算法在運(yùn)行的時(shí)候都會(huì)消耗整張顯卡,而且耗時(shí)很長(zhǎng)。

初看場(chǎng)景,很多后端可能會(huì)第一時(shí)間想到elastic-job(一個(gè)分布式任務(wù)調(diào)度框架)。即便你熟悉使用elastic-job,一開(kāi)始就選擇重框架是不是有種殺雞用牛刀的感覺(jué)。不著急,我們一步步分析,一步步設(shè)計(jì)。

業(yè)務(wù)架構(gòu)設(shè)計(jì)

高度抽象一下我們的業(yè)務(wù),對(duì)產(chǎn)品設(shè)計(jì)者而言,貌似是個(gè)簡(jiǎn)單的不能再簡(jiǎn)單的東西。等到了技術(shù)架構(gòu),我們深入分析其中演化的功能點(diǎn),就會(huì)發(fā)現(xiàn)這是個(gè)龐大的機(jī)器。我們先給他起個(gè)簡(jiǎn)單的名字:Task Execution Engine(縮寫:TEE)

技術(shù)架構(gòu)設(shè)計(jì)

下面我們開(kāi)始進(jìn)行核心模塊的技術(shù)架構(gòu)設(shè)計(jì),按照我們的初始需求開(kāi)始我們的設(shè)計(jì)旅程。

初始設(shè)計(jì)

設(shè)計(jì)說(shuō)明:

1、業(yè)務(wù)后端發(fā)出q1請(qǐng)求,我們首先需要對(duì)該請(qǐng)求的參數(shù)做矯正,為了可用性考慮。

2、參數(shù)校驗(yàn)過(guò)后,給到執(zhí)行引擎模塊。執(zhí)行引擎主要的職責(zé)有從資源表獲取資源數(shù)據(jù)、將任務(wù)參數(shù)與資源參數(shù)封裝到任務(wù)對(duì)象內(nèi)、將任務(wù)提交線程池。有一點(diǎn)要說(shuō)明執(zhí)行引擎最好使用隊(duì)列模式,任務(wù)先進(jìn)隊(duì)列,可以通過(guò)while循環(huán)方式或者定時(shí)線程池都可以,后面會(huì)推薦更好的。

3、任務(wù)執(zhí)行的狀態(tài)與結(jié)果需要同步到數(shù)據(jù)庫(kù)中,建議使用mysql。

小結(jié):

按照初始需求,該設(shè)計(jì)相對(duì)比較簡(jiǎn)單,完全夠用了。但是按照產(chǎn)品的迭代,業(yè)務(wù)方的需求不會(huì)僅限于此。繼續(xù)演化。

演化階段一

隨著業(yè)務(wù)的上線,業(yè)務(wù)端會(huì)馬上迎來(lái)新的問(wèn)題。

1、由于提交的任務(wù)太多了,排在后面的任務(wù)遲遲無(wú)法等到自己獲取到資源執(zhí)行任務(wù)。當(dāng)然我們可以完全靠增加資源來(lái)解決,但是資源的數(shù)量在產(chǎn)品前期是不可知的。所以需要有一些策略,比如讓用戶可以取消自己任務(wù),而不是一直等待。

2、任務(wù)的種類開(kāi)始增加,業(yè)務(wù)端不滿足于單一制作,開(kāi)始要求多樣化。

3、任務(wù)的執(zhí)行過(guò)程開(kāi)始需要用到其他資源,不再是一個(gè)資源對(duì)一個(gè)任務(wù)的模式了。

4、任務(wù)的整體執(zhí)行情況不可知,需要一定的量化分析,至少讓業(yè)務(wù)組知道每天的任務(wù)成功率。

按照需求進(jìn)行第二版的設(shè)計(jì),在盡量不改變?cè)瓉?lái)整體設(shè)計(jì)的情況下,補(bǔ)充功能。

設(shè)計(jì)說(shuō)明:

1、為了解決排隊(duì)問(wèn)題,增加了雙隊(duì)列算法來(lái)解決。用圖解的方式解釋一下雙隊(duì)列。

邏輯簡(jiǎn)單說(shuō)明一下,任務(wù)優(yōu)先提交至執(zhí)行隊(duì)列,引擎的定時(shí)讀取隊(duì)列的順序優(yōu)先為等待隊(duì)列。如果等待隊(duì)列中的任務(wù)可以獲取所需資源,則立即啟動(dòng)線程執(zhí)行,否則原封不動(dòng)回到等待隊(duì)列。引擎其次讀取執(zhí)行隊(duì)列,如果無(wú)法獲取資源則進(jìn)入等待隊(duì)列,如獲取資源,則立即啟動(dòng)線程執(zhí)行。

那么取消隊(duì)列,則只需要將隊(duì)列中的任務(wù)踢出隊(duì)列即可。在送回隊(duì)里的過(guò)程中,一定要保證隊(duì)列的有序性。

2、創(chuàng)建了任務(wù)池,增加了任務(wù)封裝層,在任務(wù)池中挑選需要執(zhí)行的任務(wù)類。

3、增加了策略機(jī)模塊,添加資源調(diào)度策略,由資源調(diào)度策略堆任務(wù)所需資源合理分配??梢杂蓸I(yè)務(wù)方提供分配方案,盡可能保證任務(wù)的公平性。

4、數(shù)據(jù)庫(kù)增加統(tǒng)計(jì)表,可以考慮使用定時(shí)任務(wù),將任務(wù)表的數(shù)據(jù)統(tǒng)計(jì)存入統(tǒng)計(jì)表。

小結(jié):

現(xiàn)在看上去已經(jīng)比較完善了,合理了任務(wù)調(diào)度、增加了任務(wù)種類、合理的資源調(diào)度,好像還不錯(cuò)。但是產(chǎn)品總會(huì)有新要求的,那么繼續(xù)演化。

演化階段二

漸漸的,你設(shè)計(jì)的引擎還不錯(cuò)。那么新的挑戰(zhàn)來(lái)了。

1、更多的業(yè)務(wù)方找到你,希望也使用你的項(xiàng)目進(jìn)行任務(wù)制作,但是他們并不想共享資源,而是希望有自己的獨(dú)立資源,和獨(dú)立的隊(duì)列。但并不是所有的資源都需要獨(dú)立,一些可以支持高并發(fā)的資源,是可以共享的。簡(jiǎn)而言之,更多的業(yè)務(wù)方,由業(yè)務(wù)方為維度的獨(dú)立隊(duì)列,獨(dú)立和共享的資源分配。

2、業(yè)務(wù)方找到你,說(shuō)如果把任務(wù)1的結(jié)果給到任務(wù)2,其實(shí)就能拿到我要的結(jié)果。問(wèn)題來(lái)了,原子任務(wù)要具備可以編排成復(fù)雜任務(wù)的能力。

3、任務(wù)的狀態(tài)過(guò)程無(wú)法監(jiān)控。OK,任務(wù)狀態(tài)機(jī)。

4、既然大家都需要對(duì)接你的項(xiàng)目,能不能提供標(biāo)準(zhǔn)的sdk,我只需要引入就可以完美的對(duì)接你的系統(tǒng)。

5、相同的任務(wù)參數(shù),是不是制作出來(lái)的結(jié)果一致呢?那么是否需要增加結(jié)果緩存,降低對(duì)資源的消耗呢?

6、完正的生產(chǎn)項(xiàng)目必然需要將日志、告警等關(guān)鍵信息傳遞出來(lái),一旦發(fā)生問(wèn)題可以馬上定位到問(wèn)題的起因。

這些問(wèn)題對(duì)于新人來(lái)說(shuō)還是很有挑戰(zhàn)的,需要對(duì)系統(tǒng)深層的含義有充足的理解。沒(méi)事,我來(lái)好好來(lái)說(shuō)下設(shè)計(jì)所需要掌握的知識(shí)點(diǎn)。

設(shè)計(jì)說(shuō)明:

1、需要在資源表中區(qū)別資源類型,共享資源組所有業(yè)務(wù)組都可以使用,獨(dú)立資源則資源具備業(yè)務(wù)標(biāo)識(shí)。在執(zhí)行引擎的隊(duì)列管理中,也需要區(qū)分業(yè)務(wù)組,避免共用排隊(duì)。這里給一個(gè)建議,共享的資源一定要是可以支持并發(fā)或者可以部署多個(gè)實(shí)例的,避免所有的業(yè)務(wù)組產(chǎn)品制作癱瘓。

2、增加了高級(jí)任務(wù)概念,高級(jí)任務(wù)可以將任意的原子任務(wù)進(jìn)行組合編排,形成全新的任務(wù)。需要定義專屬于TEE的語(yǔ)法規(guī)則。對(duì)語(yǔ)法規(guī)則引擎的開(kāi)發(fā),有一些建議。你可能會(huì)選擇規(guī)則引擎,建議其實(shí)可以自己開(kāi)發(fā),畢竟語(yǔ)法不會(huì)太過(guò)復(fù)雜,沒(méi)必要引入三方的引擎。

3、增加任務(wù)狀態(tài)機(jī),執(zhí)行引擎在提交線程的同時(shí),也想任務(wù)狀態(tài)機(jī)提交任務(wù)線程信息。任務(wù)的進(jìn)度狀態(tài)可以同步給任務(wù)狀態(tài)機(jī)中,同時(shí)一旦任務(wù)執(zhí)行過(guò)長(zhǎng)的時(shí)間,除了任務(wù)自己的超時(shí)機(jī)制外,也可由狀態(tài)機(jī)的看門狗程序?qū)⒖ㄋ谰€程釋放、資源回收。

4、研發(fā)屬于TEE的SDK,作為內(nèi)部系統(tǒng)不建議SDK增加鑒權(quán)模塊。畢竟你對(duì)接的往往都是業(yè)務(wù)后端,鑒權(quán)不通過(guò)的話根本滲透不到TEE層面。給開(kāi)發(fā)SDK一些建議,盡量引用較少的包,避免業(yè)務(wù)端引入帶來(lái)的包沖突。SDK也需要添加一些回調(diào)Consumer或者Function,盡可能讓業(yè)務(wù)端對(duì)接起來(lái)代碼簡(jiǎn)單。

5、增加了緩存策略,可以設(shè)想一下,大部分情況下,相同的參數(shù)制作出來(lái)的結(jié)果也必然相同。使用redis,將任務(wù)參數(shù)與任務(wù)結(jié)果進(jìn)行緩存,主鍵可以采用任務(wù)參數(shù)的MD5值。任務(wù)在提交給任務(wù)執(zhí)行引擎前,檢查緩存中是否已經(jīng)存在結(jié)果。緩存的過(guò)期時(shí)間按照具體情況而定。

6、增加日志系統(tǒng)和監(jiān)控系統(tǒng)的對(duì)接,狀態(tài)機(jī)與任務(wù)執(zhí)行中的信息接入到日志系統(tǒng)中。對(duì)于日志系統(tǒng)的建議是,最好采用成熟的ELK架構(gòu)??梢钥紤]兩種方式

a、將日志異步推送到消息隊(duì)列(例如:kafka),使用flink將kafka存入es。

b、使用logstash將日志內(nèi)容清洗處理,推送到es。

兩種方式都可以,但是一定要異步推送日志,避免任務(wù)阻塞。

告警系統(tǒng)的接入可以使用Prometheus,將TEE的指標(biāo)信息開(kāi)放出來(lái),特別是告警信息。在Prometheus的告警監(jiān)控規(guī)則中,可以將告警信息按照某些策略發(fā)送郵件或者短信,通知運(yùn)維人員。

小結(jié):

做到這里,我們?cè)倏纯次覀兊募夹g(shù)架構(gòu)圖,是不是感到很滿足。但是這真的夠了嗎?

演化階段三

隨著業(yè)務(wù)愈發(fā)繁重,一個(gè)新的問(wèn)題出現(xiàn)。

1、TEE在本機(jī)運(yùn)行很順利,但是每個(gè)任務(wù)都是需要消耗線程的,單臺(tái)模式線程必然不是無(wú)限的,總有吃滿的時(shí)候。問(wèn)題來(lái)了,TEE得支持分布式部署結(jié)構(gòu)。但是有資源管理的存在,你無(wú)法通過(guò)加實(shí)例的方式來(lái)實(shí)現(xiàn),因?yàn)橘Y源調(diào)度必然混亂。

2、假設(shè)TEE掛掉,則等于業(yè)務(wù)組此刻提交的任務(wù)均失敗,容災(zāi)機(jī)制需要建立。

到了這一步,很多小伙伴可能覺(jué)著一陣頭大,分布式不是大數(shù)據(jù)的東西嗎?不是的,不是大數(shù)據(jù)就不能分布式部署嗎?就不能有主從節(jié)點(diǎn)嗎?就不能有注冊(cè)中心嗎?要跨過(guò)內(nèi)心的固有思想,我們往下看。

設(shè)計(jì)說(shuō)明:

1、需要先將TEE項(xiàng)目做一下代碼分解,將管理調(diào)度模塊與任務(wù)執(zhí)行模塊拆解開(kāi)了。消耗性能和線程較高的是任務(wù)執(zhí)行模塊,定義為TEE執(zhí)行節(jié)點(diǎn)。消耗性能和線程較低,卻需要參數(shù)校驗(yàn)、任務(wù)封裝、資源調(diào)度、隊(duì)列管理的是管理調(diào)度模塊,定義為TEE管理節(jié)點(diǎn)。

2、TEE執(zhí)行節(jié)點(diǎn)可以多實(shí)例,形成節(jié)點(diǎn)池。管理節(jié)點(diǎn)可以考慮做成共享任務(wù)隊(duì)列的管理池。這里有個(gè)難點(diǎn),如何共享任務(wù)隊(duì)列。建議使用zookeeper或者緩存方式,但是不管哪種方式都要注意使用集群,避免單點(diǎn)故障導(dǎo)致隊(duì)列數(shù)據(jù)丟失。

3、關(guān)于注冊(cè)中心,可以使用開(kāi)源組件,nacos、zookeeper都可以。在該架構(gòu)設(shè)計(jì)中,其實(shí)注冊(cè)中心并沒(méi)有太多功能,如果你對(duì)自己有信心,可以嘗試自己寫一個(gè)注冊(cè)中心,核心功能就是服務(wù)注冊(cè)與心跳檢測(cè)??梢杂胣etty架構(gòu)做一做,提高一下自己的代碼能力。

4、在管理池的調(diào)用方面,增加網(wǎng)關(guān)代理,可以使用nginx、konga等。主要功能是業(yè)務(wù)端調(diào)用的時(shí)候,隨機(jī)打到管理節(jié)點(diǎn)上,就算一個(gè)管理節(jié)點(diǎn)掛了,也不會(huì)影響使用,保證了生產(chǎn)線的穩(wěn)定。

小結(jié):

分布式架構(gòu),主從節(jié)點(diǎn)模式也好、哨兵模式也好、選舉模式也好,按照自己的業(yè)務(wù)需求選擇最適合自己的。不是大數(shù)據(jù)才有分布式,它是一種設(shè)計(jì)思想,要知道開(kāi)發(fā)大數(shù)據(jù)組件的大佬們,也是一行行java寫出來(lái)的。大佬們可以,為什么你不可以呢?

代碼設(shè)計(jì)

在著手開(kāi)發(fā)該系統(tǒng)的時(shí)候,我給大家一些代碼開(kāi)發(fā)的建議:

1、定時(shí)任務(wù)的實(shí)現(xiàn),從最簡(jiǎn)單的while死循環(huán)加sleep,到定時(shí)線程池,或者springboot的@Scheduled注解,都可以實(shí)現(xiàn)。我在這里推薦一下時(shí)間輪算法TimeWheel,有興趣的可以去了解一下。

2、異步消息處理,如果你只是想在項(xiàng)目?jī)?nèi)部使用消息總線,推薦使用guava包內(nèi)的EventBus。按照消息的數(shù)量級(jí),考慮使用RabbitMQ或者Kafka作為消息中間件。

3、任務(wù)執(zhí)行,推薦使用CompletableFuture進(jìn)行異步非阻塞任務(wù)編程。

4、在資源的使用中,可能存在多種協(xié)議類型http、ws、tcp等。所以代碼設(shè)計(jì)中,盡可能提供完整全面的協(xié)議工具類。

總結(jié)

最近和一個(gè)同事閑聊的時(shí)候,他和我說(shuō)了說(shuō)最近面試高級(jí)研發(fā)的情況??偨Y(jié)一下,現(xiàn)在想招一個(gè)做過(guò)高并發(fā)場(chǎng)景的太難了,大部分人選只做業(yè)務(wù)相關(guān)。這讓我想到了十年前,我剛工作的時(shí)候。那時(shí)候沒(méi)有那么多框架,大部分功能需要看很多資料研究底層的原理與算法。隨著軟件行業(yè)的日益成熟,從以前拿著谷歌翻譯看國(guó)外的組建說(shuō)明,到從阿里云直接對(duì)接功能,軟件研發(fā)的成本和時(shí)間也在大大縮短。漸漸失去了研究分析的動(dòng)力,框架什么都有為什么要抓破腦袋自己寫。

怎么成長(zhǎng)?怎么進(jìn)步?

上面給出的架構(gòu)圖,看上去都挺好理解。但真要自己去代碼實(shí)現(xiàn),中間各個(gè)環(huán)節(jié)出現(xiàn)的問(wèn)題真的好解決嗎?冰凍三尺,非一日之寒。沒(méi)有日積月累的學(xué)習(xí),是很難成功的。不要懼怕那些你看上去遙遠(yuǎn)的東西,獲取你的幾個(gè)晚上的學(xué)習(xí),它就成了你最趁手的武器。對(duì)學(xué)習(xí)而言,難的永遠(yuǎn)不是過(guò)程,而是踏出第一步。

高并發(fā)任務(wù)執(zhí)行架構(gòu)中,有一個(gè)模塊看上去很不起眼,但是在你研發(fā)的過(guò)程就會(huì)發(fā)現(xiàn)他會(huì)給你制造大麻煩-資源調(diào)度。以后有時(shí)間我會(huì)單獨(dú)做一篇關(guān)于資源調(diào)度的架構(gòu)設(shè)計(jì),與大家說(shuō)道說(shuō)道里面的坑。

最后說(shuō)一句:為什么不ban猛犸?

到此這篇關(guān)于Java 高并發(fā)編程之最實(shí)用的任務(wù)執(zhí)行架構(gòu)設(shè)計(jì)建議收藏的文章就介紹到這了,更多相關(guān)Java 高并發(fā)編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

钟祥市| 深圳市| 昆明市| 长乐市| 万盛区| 商都县| 珲春市| 都江堰市| 太原市| 池州市| 榆树市| 广昌县| 临安市| 林甸县| 临城县| 离岛区| 长治县| 南京市| 搜索| 西畴县| 聊城市| 呼和浩特市| 廉江市| 进贤县| 镇宁| 伊宁市| 贺州市| 仙游县| 大英县| 侯马市| 济阳县| 兰西县| 临城县| 永春县| 清水县| 济宁市| 张北县| 阿鲁科尔沁旗| 莲花县| 平昌县| 峨眉山市|