自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

時鐘輪在 RPC 中的應(yīng)用

開發(fā)
今天我們主要講解了時鐘輪的機(jī)制,以及時鐘輪在 RPC 框架中的應(yīng)用。

今天這篇文章介紹一下RPC中如何使用時鐘輪實現(xiàn)定時任務(wù),比如調(diào)用端的超時處理、定時心跳....

定時任務(wù)帶來了什么問題?

在講解時鐘輪之前,我們先來聊聊定時任務(wù)。相信你在開發(fā)的過程中,很多場景都會使用到定時任務(wù),在 RPC 框架中也有很多地方會使用到它。就以調(diào)用端請求超時的處理邏輯為例,下面我們看一下 RPC 框架是如果處理超時請求的。

在講解 Future 的時候說過:無論是同步調(diào)用還是異步調(diào)用,調(diào)用端內(nèi)部實行的都是異步,而調(diào)用端在向服務(wù)端發(fā)送消息之前會創(chuàng)建一個 Future,并存儲這個消息標(biāo)識與這個 Future 的映射,當(dāng)服務(wù)端收到消息并且處理完畢后向調(diào)用端發(fā)送響應(yīng)消息,調(diào)用端在接收到消息后會根據(jù)消息的唯一標(biāo)識找到這個 Future,并將結(jié)果注入給這個 Future。

那在這個過程中,如果服務(wù)端沒有及時響應(yīng)消息給調(diào)用端呢?調(diào)用端該如何處理超時的請求?

沒錯,就是可以利用定時任務(wù)。每次創(chuàng)建一個 Future,我們都記錄這個 Future 的創(chuàng)建時間與這個 Future 的超時時間,并且有一個定時任務(wù)進(jìn)行檢測,當(dāng)這個 Future 到達(dá)超時時間并且沒有被處理時,我們就對這個 Future 執(zhí)行超時邏輯。

那定時任務(wù)該如何實現(xiàn)呢?

有種實現(xiàn)方式是這樣的,也是最簡單的一種。每創(chuàng)建一個 Future 我們都啟動一個線程,之后 sleep,到達(dá)超時時間就觸發(fā)請求超時的處理邏輯。

這種方式吧,確實簡單,在某些場景下也是可以使用的,但弊端也是顯而易見的。就像剛才我講的那個 Future 超時處理的例子,如果我們面臨的是高并發(fā)的請求,單機(jī)每秒發(fā)送數(shù)萬次請求,請求超時時間設(shè)置的是 5 秒,那我們要創(chuàng)建多少個線程用來執(zhí)行超時任務(wù)呢?超過 10 萬個線程,這個數(shù)字真的夠嚇人了。

別急,我們還有另一種實現(xiàn)方式。我們可以用一個線程來處理所有的定時任務(wù),還以剛才那個 Future 超時處理的例子為例。假設(shè)我們要啟動一個線程,這個線程每隔 100 毫秒會掃描一遍所有的處理 Future 超時的任務(wù),當(dāng)發(fā)現(xiàn)一個 Future 超時了,我們就執(zhí)行這個任務(wù),對這個 Future 執(zhí)行超時邏輯。

這種方式我們用得最多,它也解決了第一種方式線程過多的問題,但其實它也有明顯的弊端。

同樣是高并發(fā)的請求,那么掃描任務(wù)的線程每隔 100 毫秒要掃描多少個定時任務(wù)呢?如果調(diào)用端剛好在 1 秒內(nèi)發(fā)送了 1 萬次請求,這 1 萬次請求要在 5 秒后才會超時,那么那個掃描的線程在這個 5 秒內(nèi)就會不停地對這 1 萬個任務(wù)進(jìn)行掃描遍歷,要額外掃描 40 多次(每 100 毫秒掃描一次,5 秒內(nèi)要掃描近 50 次),很浪費(fèi) CPU。

在我們使用定時任務(wù)時,它所帶來的問題,就是讓 CPU 做了很多額外的輪詢遍歷操作,浪費(fèi)了 CPU,這種現(xiàn)象在定時任務(wù)非常多的情況下,尤其明顯。

什么是時鐘輪?

這個問題也不難解決,我們只要找到一種方式,減少額外的掃描操作就行了。比如我的一批定時任務(wù)是 5 秒之后執(zhí)行,我在 4.9 秒之后才開始掃描這批定時任務(wù),這樣就大大地節(jié)省了 CPU。這時我們就可以利用時鐘輪的機(jī)制了。

我們先來看下我們生活中用到的時鐘。

圖片

很熟悉了吧,時鐘有時針、分針和秒針,秒針跳動一周之后,也就是跳動 60 個刻度之后,分針跳動 1 次,分針跳動 60 個刻度,時針走動一步。

而時鐘輪的實現(xiàn)原理就是參考了生活中的時鐘跳動的原理。

圖片

在時鐘輪機(jī)制中,有時間槽和時鐘輪的概念,時間槽就相當(dāng)于時鐘的刻度,而時鐘輪就相當(dāng)于秒針與分針等跳動的一個周期,我們會將每個任務(wù)放到對應(yīng)的時間槽位上。

時鐘輪的運(yùn)行機(jī)制和生活中的時鐘也是一樣的,每隔固定的單位時間,就會從一個時間槽位跳到下一個時間槽位,這就相當(dāng)于我們的秒針跳動了一次;

時鐘輪可以分為多層,下一層時鐘輪中每個槽位的單位時間是當(dāng)前時間輪整個周期的時間,這就相當(dāng)于 1 分鐘等于 60 秒鐘;當(dāng)時鐘輪將一個周期的所有槽位都跳動完之后,就會從下一層時鐘輪中取出一個槽位的任務(wù),重新分布到當(dāng)前的時鐘輪中,當(dāng)前時鐘輪則從第 0 槽位從新開始跳動,這就相當(dāng)于下一分鐘的第 1 秒。

為了方便你了解時鐘輪的運(yùn)行機(jī)制,我們用一個場景例子來模擬下,一起看下這個場景。

假設(shè)我們的時鐘輪有 10 個槽位,而時鐘輪一輪的周期是 1 秒,那么我們每個槽位的單位時間就是 100 毫秒,而下一層時間輪的周期就是 10 秒,每個槽位的單位時間也就是 1 秒,并且當(dāng)前的時鐘輪剛初始化完成,也就是第 0 跳,當(dāng)前在第 0 個槽位。

圖片

好,現(xiàn)在我們有 3 個任務(wù),分別是任務(wù) A(90 毫秒之后執(zhí)行)、任務(wù) B(610 毫秒之后執(zhí)行)與任務(wù) C(1 秒 610 毫秒之后執(zhí)行),我們將這 3 個任務(wù)添加到時鐘輪中,任務(wù) A 被放到第 0 槽位,任務(wù) B 被放到第 6 槽位,任務(wù) C 被放到下一層時間輪的第 1 槽位,如下面這張圖所示。

圖片

當(dāng)任務(wù) A 剛被放到時鐘輪,就被即刻執(zhí)行了,因為它被放到了第 0 槽位,而當(dāng)前時間輪正好跳到第 0 槽位(實際上還沒開始跳動,狀態(tài)為第 0 跳);600 毫秒之后,時間輪已經(jīng)進(jìn)行了 6 跳,當(dāng)前槽位是第 6 槽位,第 6 槽位所有的任務(wù)都被取出執(zhí)行;1 秒鐘之后,當(dāng)前時鐘輪的第 9 跳已經(jīng)跳完,從新開始了第 0 跳,這時下一層時鐘輪從第 0 跳跳到了第 1 跳,將第 1 槽位的任務(wù)取出,分布到當(dāng)前的時鐘輪中,這時任務(wù) C 從下一層時鐘輪中取出并放到當(dāng)前時鐘輪的第 6 槽位;1 秒 600 毫秒之后,任務(wù) C 被執(zhí)行。

圖片

看完了這個場景,相信你對時鐘輪的機(jī)制已經(jīng)有所了解了。在這個例子中,時鐘輪的掃描周期仍是 100 毫秒,但是其中的任務(wù)并沒有被過多的重復(fù)掃描,它完美地解決了 CPU 浪費(fèi)的問題。

這個機(jī)制其實不難理解,但實現(xiàn)起來還是很有難度的,其中要注意的問題也很多.

時鐘輪在 RPC 中的應(yīng)用

通過剛才對時鐘輪的講解,相信你可以看出,它就是用來執(zhí)行定時任務(wù)的,可以說在 RPC 框架中只要涉及到定時相關(guān)的操作,我們就可以使用時鐘輪。

那么 RPC 框架在哪些功能實現(xiàn)中會用到它呢?

剛才我舉例講到的調(diào)用端請求超時處理,這里我們就可以應(yīng)用到時鐘輪,我們每發(fā)一次請求,都創(chuàng)建一個處理請求超時的定時任務(wù)放到時鐘輪里,在高并發(fā)、高訪問量的情況下,時鐘輪每次只輪詢一個時間槽位中的任務(wù),這樣會節(jié)省大量的 CPU。

調(diào)用端與服務(wù)端啟動超時也可以應(yīng)用到時鐘輪,以調(diào)用端為例,假設(shè)我們想要讓應(yīng)用可以快速地部署,例如 1 分鐘內(nèi)啟動,如果超過 1 分鐘則啟動失敗。我們可以在調(diào)用端啟動時創(chuàng)建一個處理啟動超時的定時任務(wù),放到時鐘輪里。

除此之外,你還能想到 RPC 框架在哪些地方可以應(yīng)用到時鐘輪嗎?還有定時心跳。RPC 框架調(diào)用端定時向服務(wù)端發(fā)送心跳,來維護(hù)連接狀態(tài),我們可以將心跳的邏輯封裝為一個心跳任務(wù),放到時鐘輪里。

這時你可能會有一個疑問,心跳是要定時重復(fù)執(zhí)行的,而時鐘輪中的任務(wù)執(zhí)行一遍就被移除了,對于這種需要重復(fù)執(zhí)行的定時任務(wù)我們該如何處理呢?在定時任務(wù)的執(zhí)行邏輯的最后,我們可以重設(shè)這個任務(wù)的執(zhí)行時間,把它重新丟回到時鐘輪里。

總結(jié)

今天我們主要講解了時鐘輪的機(jī)制,以及時鐘輪在 RPC 框架中的應(yīng)用。

這個機(jī)制很好地解決了定時任務(wù)中,因每個任務(wù)都創(chuàng)建一個線程,導(dǎo)致的創(chuàng)建過多線程的問題,以及一個線程掃描所有的定時任務(wù),讓 CPU 做了很多額外的輪詢遍歷操作而浪費(fèi) CPU 的問題。

時鐘輪的實現(xiàn)機(jī)制就是模擬現(xiàn)實生活中的時鐘,將每個定時任務(wù)放到對應(yīng)的時間槽位上,這樣可以減少掃描任務(wù)時對其它時間槽位定時任務(wù)的額外遍歷操作。

在時間輪的使用中,有些問題需要你額外注意:

  • 時間槽位的單位時間越短,時間輪觸發(fā)任務(wù)的時間就越精確。例如時間槽位的單位時間是 10 毫秒,那么執(zhí)行定時任務(wù)的時間誤差就在 10 毫秒內(nèi),如果是 100 毫秒,那么誤差就在 100 毫秒內(nèi)
  • 時間輪的槽位越多,那么一個任務(wù)被重復(fù)掃描的概率就越小,因為只有在多層時鐘輪中的任務(wù)才會被重復(fù)掃描。比如一個時間輪的槽位有 1000 個,一個槽位的單位時間是 10 毫秒,那么下一層時間輪的一個槽位的單位時間就是 10 秒,超過 10 秒的定時任務(wù)會被放到下一層時間輪中,也就是只有超過 10 秒的定時任務(wù)會被掃描遍歷兩次,但如果槽位是 10 個,那么超過 100 毫秒的任務(wù),就會被掃描遍歷兩次。

結(jié)合這些特點,我們就可以視具體的業(yè)務(wù)場景而定,對時鐘輪的周期和時間槽數(shù)進(jìn)行設(shè)置。

在 RPC 框架中,只要涉及到定時任務(wù),我們都可以應(yīng)用時鐘輪,比較典型的就是調(diào)用端的超時處理、調(diào)用端與服務(wù)端的啟動超時以及定時心跳等等。

責(zé)任編輯:趙寧寧 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2022-03-24 10:23:51

時間輪方法任務(wù)

2020-10-15 17:38:00

Time Wheel

2024-12-27 09:32:19

2009-02-27 16:22:34

AjaxProAjax.NET

2023-03-24 09:07:22

SignalsJavaScript應(yīng)用

2011-09-15 13:25:18

IOS應(yīng)用

2017-09-04 14:40:00

LimitLatchTomcat線程

2020-05-22 10:40:33

ContinuatioJS前端

2014-08-08 16:50:21

AB 測試安卓推送

2019-05-21 06:00:29

物聯(lián)網(wǎng)體育IOT

2017-10-27 16:19:23

語音識別CNN

2011-05-18 16:02:08

XML

2021-12-07 18:35:08

物聯(lián)網(wǎng)執(zhí)法應(yīng)用IOT

2010-07-07 17:24:39

BGP協(xié)議

2024-09-30 09:48:41

RabbitMQ消息中間件

2023-11-01 07:34:04

大語言模型應(yīng)用協(xié)議識別

2010-08-09 10:21:56

XMLFlex

2009-06-25 15:54:18

設(shè)計模式EJB

2010-08-03 11:07:34

NFSVMware快照

2010-10-08 10:15:34

IFrameJS控件
點贊
收藏

51CTO技術(shù)棧公眾號