異構環境中的時間同步
在混合環境中,機器可以在 Windows(大多數)、Linux(少數)、有時是 Android 下執行……以接近毫秒的精度進行時間同步的最佳解決方案是什麼?
我們正在開發基於微服務的解決方案,其中服務分散在我們設置中的多台機器上。在許多情況下,整合它們之間的資訊(日誌、監控等)需要一個共同的時間基準。
在 Windows 下使用 NTP 似乎有其局限性。任何可以在該作業系統上執行的開源解決方案?我們不能保證在我們的設置中總會有一台 Linux 機器。
$$ EDIT $$當我剛剛從記憶中記下舊答案時,對引用進行了重大重寫。
*簡短的回答:沒有。*今天,不可能從 x86/x64 平台上的普通作業系統獲得接近毫秒的精度。
免責聲明 這是一個外行的答案,因為我是一個普通的系統管理員,對電腦有一個普通的系統管理員視圖。一些核心開發人員和硬體架構師可能具有專業水平的計時知識。
長答案:
必須從某個地方開始。我將自上而下地執行此操作,從應用程序向下移動到振盪器開始。
第一個問題不是在一台電腦上進行計時,而是設法讓整個環境就您擁有的任何計時達成一致。什麼計時?事實證明,有幾種方法可以在今天的電腦中保持時間。我們看到最多的是系統時間(顯示在螢幕角落之一)。讓我們先假裝它是那麼簡單而復雜的事情在幾段之後。
我們希望系統時間是正確的,並且我們希望它在我們所有的電腦上都是統一的。我們需要一種方法從可信賴的來源以如此精細的級別進行通信,以滿足我們的需求,無論它們可能是什麼。
讓我們把我們的要求變成 1ms 的容差水平,也就是說,我們的時間在我們的環境中可能會偏離 1ms,或者我們錯過了一個關鍵目標。讓我們具體一點,看看微軟能為我們做些什麼。
不包括 NT 等過時的系統,Windows 本機基於簡化的 ntp(從 XP/2003 開始的加入域的電腦)或簡化的 sntp(從 Win2k 開始的未加入域的電腦)執行其計時 - 感謝@Ryan 挑剔這個細節. 微軟在進行計時實施時設定了兩個目標,這兩個目標都不包括我們想要的準確度:
“我們不保證也不支持網路上節點之間的 W32Time 服務的準確性。W32Time 服務不是滿足時間敏感應用需求的全功能 NTP 解決方案。W32Time 服務主要用於下列的:
- 使 Kerberos 版本 5 身份驗證協議工作。
- 為客戶端電腦提供寬鬆的同步時間。
W32Time 服務無法將同步時間可靠地保持在一到兩秒的範圍內。這種公差超出了 W32Time 服務的設計規範。”
好的。假設我們在不止一台電腦上執行您的服務堆棧,並且事件關聯的計時容差水平接近 1 毫秒,那真是令人失望。如果服務堆棧包括兩台電腦,我們實際上根本無法使用 Windows 原生計時。但是,當我們談到它時,讓我們強調一下關於 Windows 原生計時的一兩個關鍵點,並包含一些完整的文件:
如果您有 AD,請注意給定域中的時間將從 PDC Emulator 角色同步,無論哪個 DC 擁有它。因此,需要通過執行 PDC 模擬器角色的域控制器將正確的時間帶入域。如果在多域林中,這將轉換為林根域的 PDC 模擬器。從那時起,時間主要分散到子域的 PDC 仿真器和以扇出方式(有一些警告)的每個域成員。此處記錄了此過程。更深入的資訊在這裡
好的。我們能做些什麼?
首先,我們需要一種或其他更精確的方法來同步整個環境的時間。假設我們無法在Windows 上執行 Linux ntpd 或 ntpd,您可以查看一個名為Tardis的共享軟體客戶端,但可能還有更多可以嘗試。
我們在作為 PDC Emulator 執行的 Win2k3 伺服器上執行 Tardis,該伺服器的 CMOS 時鐘具有非常大的偏差,由於無法解釋的歷史原因,我們別無選擇,只能從中同步整個網路。現在它已經被一個專用的 Linux ntpd 所取代,非常高興,它從外部的原子鐘中引入時間,但 Tardis 令人欽佩地在當時和那裡拯救了我們。但是,我不知道它是否可以幫助您實現比 Windows 原生更高的精度。
但是讓我們假設從這一點開始,我們(我們)已經想出瞭如何實現一個完美的替代網路時間同步。由於其固有的狡猾性,它具有低於一毫秒的容差水平的能力。我們已將其落實到位,以強制執行我們的 AD 期望時間如何通過網路傳播。
這是否意味著我們可以以接近一毫秒的粒度從作業系統和微服務中獲得準確的診斷資訊?
讓我們看看 x86/x64 架構上的作業系統如何調度處理器時間。
他們使用中斷,這是富含考古物質的多面獸。然而,作業系統並不是唯一想要中斷的。硬體也希望中斷,它有辦法做到這一點!(你好鍵盤)和作業系統一起玩。
這就是它變得複雜的地方,我將通過過度簡化來解決這個問題。問題?我迴避,掩護並指出你關於這個主題的絕對優秀的論文。(如果你在 Windows 平台上尋找毫秒數,你真的應該閱讀它。)據報導, Win8.1/Win2012r2 的更新版本正在開發中,但尚未公佈發布日期。
好的,中斷。每當作業系統中發生某些事情時,中斷就會觸發隨後的操作。該動作是從核心中獲取的一堆指令,可以以多種不同的方式執行. 底線是,儘管中斷發生的時間可以根據硬體體系結構和核心中斷處理或多或少的準確性來確定,但通常不能確定後續執行部分的確切時間。一組特定的指令可能會在中斷後的早期或後期執行,它可能以可預測的順序執行,也可能是有缺陷的硬體或編寫不佳的驅動程序影響甚至難以辨識的延遲的受害者。大多數時候,一個人根本不知道。後續日誌文件中顯示的毫秒級時間戳 -非常精確,但事件發生的時間是否準確?
讓我們通過計時中斷短暫地停下來。中斷帶有優先級,最低級別是使用者應用程序(例如標準服務)獲得處理器時間的地方。其他(更高)級別保留用於硬體和核心工作。如果高於最低級別的中斷到達,系統將假裝隊列中的任何低優先級中斷也不存在(直到更高優先級的中斷得到處理)。以這種方式執行的普通應用程序和服務將排在最後一個處理器時間。相反,幾乎最高優先級被賦予時鐘中斷。時間的更新幾乎總是在系統中完成。這幾乎是對它的工作原理的過度簡化,但它服務於這個答案的目的。
更新時間實際上包括兩個任務:
- 更新系統時間/又名掛鐘/又名當有人問我現在幾點時我說的話/又名 ntp 相對於附近系統來回擺弄的東西。
- 更新滴答計數,例如在測量程式碼執行的持續時間時使用。
但是無論是掛牆時間還是滴答計數,系統從哪裡獲取時間?這很大程度上取決於硬體架構。在硬體的某個地方,一個或多個振盪器正在滴答作響,並且該滴答聲通過幾個可能的路徑之一進入與核心接觸的介面,因為它以或多或少的精度和準確度更新其壁時間和滴答計數。
多核系統中有多種振盪器佈局設計模型,主要區別似乎是同步佈局與非同步佈局。例如,這裡描述了這些以及它們各自對準確計時的挑戰。
簡而言之,同步計時每個多核有一個參考時鐘,它將其信號分配給所有核心。非同步計時每個核心有一個振盪器。值得注意的是,最新的 Intel 多核處理器 (Haswell) 使用某種形式的同步設計,使用稱為“QuickPath Interconnect”和“Forwarded Clocking”的串列匯流排,參考文獻。數據表。Forwarded Clocking 是這樣描述的,外行人(我)可以在這裡快速掌握它。
好的,所以拋開所有的書呆子主義(這表明計時是一項複雜的實際任務,有很多關於它的活生生的歷史),讓我們更仔細地看看中斷處理。
作業系統使用兩種不同的策略之一來處理中斷:ticking 或 tickless。您的系統使用其中一種,但這些術語是什麼意思?
Ticking 核心以固定的時間間隔發送中斷。作業系統無法以比滴答間隔更精細的解析度測量時間。即使這樣,執行一個或多個動作所涉及的實際處理也可能包含大於滴答間隔的延遲。例如,考慮分佈式系統(例如微服務),其中服務間呼叫固有的延遲可能會消耗相對大量的時間。然而,每組指令都將與作業系統測量的一個或多個中斷相關聯,其解析度不超過核心滴答時間。滴答時間有一個基本值,但至少在 Windows 中可以根據單個應用程序的需要減少。這是一項不僅與收益相關的行動,而且與成本相關,並且帶有相當多的細則。用它。
所謂的無滴答核心(具有非常非描述性的名稱)是一項相對較新的發明。無滴答核心以可變間隔設置滴答時間(未來盡可能長的持續時間)。原因是作業系統動態地允許處理器核心盡可能長時間地進入各種級別的睡眠,其簡單目的是節省電力。“各種級別”包括以全速處理指令、以降低的速率處理(即較慢的處理器速度)或根本不處理。允許不同的核心以不同的速率執行,並且無滴答核心試圖讓處理器盡可能地處於非活動狀態,即使在包括排隊指令以在中斷批次中觸發它們的情況下也是如此。簡而言之,允許多處理器系統中的不同核心相對於彼此在時間上漂移。這當然會對良好的時間保持造成嚴重破壞,並且到目前為止,對於更新的節能處理器架構和允許它們進行高效節能的無滴答核心來說,這是一個尚未解決的問題。將此與持續喚醒所有處理器核心的滴答核心(靜態滴答間隔)進行比較,無論它們是否接收實際工作,並且與無滴答核心相比,計時具有一定程度的不准確但相對可靠的程度。
標準的Windows 滴答時間(即係統解析度)在 Windows 8/2012 之前為 15.6 毫秒,其中預設行為是無滴答(但可恢復為滴答核心)。我相信 Linux 預設滴答時間取決於核心編譯,但這個利基遠遠超出了我的經驗(也是這個),所以你可能希望仔細檢查你是否依賴它。我相信 Linux 核心是從 2.6.21 開始無滴答編譯的,並且可以使用各種優化無滴答行為的標誌進行編譯(其中我只記得 no_hz 的幾個變體)。
裸機系統就這麼多。在虛擬系統中,情況變得更糟,因為虛擬機和管理程序以不同的方式爭用使得精確計時變得極其困難。這是VMware 的概述,這是 RHEL KVM的概述。分佈式系統也是如此。雲系統更加困難,因為我們甚至沒有接近看到實際的管理程序和硬體。
總而言之,從系統中獲取準確的時間是一個多層次的問題。現在從高層次的角度來看,我們必須解決:硬體和核心之間的內部時間同步、中斷處理和延遲執行我們希望的指令的時間,如果在虛擬環境中不准確由於封裝了第二個作業系統層,分佈式系統之間的時間同步。
因此,在計算歷史的這一點上,我們不會從 x86/x64 架構中獲得毫秒級的精度,至少不使用任何普通的作業系統。
但是我們能離多近呢?我不知道,它應該在不同系統之間有很大差異。掌握自己特定係統的不准確性是一項艱鉅的任務。只需看看英特爾建議應該如何進行程式碼基準測試,就可以看到普通系統,比如我碰巧發現自己管理的系統,從這個角度來看是非常失控的。
我什至不考慮在關鍵系統中實現*“所有電源優化、英特爾超執行緒技術、頻率縮放和渦輪模式功能都已關閉”*,更不用說在 C 中修改程式碼包裝器並執行長期測試以獲得後續答案。我只是試著讓他們活著,並儘可能多地了解他們,而不會過多地打擾他們。謝謝你的時間戳,我知道我不能完全信任你,但我知道你不會有太多的時間。當實際毫秒精度確實變得重要時,一個測量是不夠的,但需要更多的測量來驗證模式。我們還能做什麼?
最後,看看實時作業系統人員如何看待中斷延遲是很有趣的。作品中還有一個非常令人興奮的時間同步替代方案,其中公開了相當多有趣的統計數據、方法論和白皮書。再加上未來的硬體架構和核心開發,幾年後這種計時準確性可能不再是這樣的問題。人們可能希望。