我正在重新設計現有的L2TP(第2層隧道協議)代碼。 對於L2TP,我們支持的隧道數量爲96K。 L2TP協議有一個保持活動的機制,它需要發送HELLO msges。需要處理大量定時器/超時的建議
說出如果我們有96,000個隧道,L2TPd需要在配置的超時值後發送HELLO msg,那麼實現它的最佳方式是什麼?
現在,我們有一個計時器線程,每隔1秒,我們迭代併發送HELLO msges。這個設計是一箇舊的設計,現在還不能擴展。
請給我一個設計來處理大量的定時器。
我正在重新設計現有的L2TP(第2層隧道協議)代碼。 對於L2TP,我們支持的隧道數量爲96K。 L2TP協議有一個保持活動的機制,它需要發送HELLO msges。需要處理大量定時器/超時的建議
說出如果我們有96,000個隧道,L2TPd需要在配置的超時值後發送HELLO msg,那麼實現它的最佳方式是什麼?
現在,我們有一個計時器線程,每隔1秒,我們迭代併發送HELLO msges。這個設計是一箇舊的設計,現在還不能擴展。
請給我一個設計來處理大量的定時器。
有一對夫婦的方式來實現定時器:
1)選擇:這個系統調用允許你等待一個文件描述符,然後醒來。您可以在不執行任何作爲超時
2)Posix的條件變量文件描述符等待:類似的選擇,他們有時間出去內置機制
3)如果你使用的是UNIX,可以設置一個UNIX信號喚醒。
這些都是基本的想法。你可以看到它們如何擴展到多個定時器。我猜你必須有多個condvars /選擇一些線程。
根據您想要的行爲,您可能需要每100個定時器左右的線程,並使用上述機制之一來喚醒其中一個定時器 。你會有一個線程坐在一個循環中,並保持100個超時中的每一個都跟蹤 ,然後醒來。
一旦您超過100個定時器,您只需創建一個新線程並讓它管理接下來的100個定時器等等。
我不知道100是否是正確的粒度,但它是你玩的東西。
希望這就是你要找的。
通常情況下,這樣的需求會通過增量隊列來滿足。當需要超時時,獲取系統滴答計數併爲其添加超時間隔。這給出了超時到期滴答計數(TETC)。將套接字對象插入通過減少TETC排序的隊列中,讓線程等待隊列頭部的項目的TETC。
通常,使用asocket超時時,隊列插入很便宜,因爲有許多超時具有相同的間隔,所以新的超時插入通常會發生在隊列尾部。
隊列的管理(實際上,因爲插入排序隊列可能發生在任何地方,它更像是列表而不是隊列,但不管:),最好保存到一個超時線程,該線程通常執行定時等待最低TETC的condvar或信號量。然後,新的超時對象可以排隊到線程安全的併發隊列上的線程,並通過sema/condvar發送到超時處理程序線程。
當超時線程在TETC超時上準備就緒時,它可能會調用對象本身的某個「OnTimeout」方法,或者它可能會將超時對象放到線程池輸入隊列中。
這樣的Δ-隊列是用於處理大量的超時比任何輪詢方案,特別是對於具有稍長的時間間隔的要求更加高效。不需要輪詢,不會因連續迭代而浪費CPU /內存帶寬,典型的延遲將成爲系統時鐘或兩個時鐘。
它是依賴於處理器/ OS,內核版本,體系結構。
在linux中,一個選項是使用其定時器功能爲多個定時器。定時器的添加可以在linux中使用add_timer來完成。您可以使用timer_list定義它,並使用init_timer初始化定時器的內部值。 隨後它使用它填充add_timer後timer_list寄存器(超時(到期),功能後超時(函數來執行),參數的函數(數據))適當地對相應的定時器。如果jiffies大於或等於超時(過期),則應觸發相應的定時器處理程序(函數)。
某些處理器具有定時器車輪(即由若干隊列的在時間上相等地安置在槽的),其可以被配置用於各種定時器的配置,超時按要求。
需要注意的是,默認情況下,「選擇」不能監視在同一時間超過1024個文件描述符。 –
其實,它可以。你必須「不限制」你的描述符(以確保你實際上可以使用超過1024個描述符),然後你必須在將FD_SETSIZE設置爲更大的值之前重新編譯你的代碼,然後再包含相應的包含。這是一個有點冒險,但它的工作原理,因爲選擇通常作爲一個位向量來實現,其中1位表示該文件描述符是相關的。 – rts1