互聯(lián)網(wǎng)上的設(shè)備要保持正常運(yùn)行需要內(nèi)置時(shí)鐘運(yùn)行精準(zhǔn),像Facebook這種規(guī)模體量的互聯(lián)網(wǎng)公司對(duì)設(shè)備時(shí)鐘的精準(zhǔn)度要求會(huì)更高。本文介紹了Facebook在搭建自己的精確時(shí)間服務(wù)方面的探索實(shí)踐,最終給我們提供了測(cè)量系統(tǒng)時(shí)間誤差的方法以及對(duì)chrony的應(yīng)用實(shí)踐。
數(shù)十億連接到互聯(lián)網(wǎng)的設(shè)備幾乎都有內(nèi)置時(shí)鐘,為了保證設(shè)備的正常運(yùn)行,這些時(shí)鐘必須保持精確。因?yàn)樵S多時(shí)鐘的內(nèi)部振蕩器并不精準(zhǔn),所以可能會(huì)導(dǎo)致每天數(shù)秒的誤差,這就需要定期校正。因?yàn)椴粶?zhǔn)確的時(shí)間會(huì)導(dǎo)致一些問(wèn)題,比如錯(cuò)過(guò)重要的提醒時(shí)間,甚至導(dǎo)致宇宙飛船發(fā)射失敗。全世界的設(shè)備都依賴網(wǎng)絡(luò)時(shí)間協(xié)議(NTP),通過(guò)包交換、可變延遲的數(shù)據(jù)網(wǎng)絡(luò)來(lái)保持與更精確時(shí)鐘的同步。
隨著Facebook基礎(chǔ)設(shè)施的增長(zhǎng),系統(tǒng)中的時(shí)間精度變得越來(lái)越重要。我們需要知道數(shù)據(jù)中心中兩個(gè)隨機(jī)服務(wù)器之間的準(zhǔn)確時(shí)間差,以便數(shù)據(jù)存儲(chǔ)寫入數(shù)據(jù)時(shí)不會(huì)打亂事務(wù)順序。我們需要以亞毫秒級(jí)的精度同步多個(gè)數(shù)據(jù)中心的所有服務(wù)器。為此,我們測(cè)試了chrony,這是一個(gè)功能豐富的現(xiàn)代NTP服務(wù)器實(shí)現(xiàn)。在測(cè)試期間,我們發(fā)現(xiàn)與以前使用的服務(wù)ntpd相比,chrony具有更高的精確性和可伸縮性,這就讓我們很安心的用chrony替換了基礎(chǔ)設(shè)施中的ntpd。Chrony也是Facebook公共NTP服務(wù)time.facebook.com的基礎(chǔ)。在這篇文章中,我們將分享將時(shí)間精度從10毫秒提高到100微秒所做的工作,以及我們?nèi)绾卧谟?jì)時(shí)實(shí)驗(yàn)室驗(yàn)證這些結(jié)果的。
閏秒
在深入了解NTP服務(wù)細(xì)節(jié)之前,我們需要了解一種稱為閏秒的現(xiàn)象。由于地球不規(guī)律的自轉(zhuǎn),我們有時(shí)需要增加或減少一秒,或一閏秒。對(duì)于人類來(lái)說(shuō),增加或減少一秒在看鐘表的時(shí)候幾乎察覺(jué)不到。然而,這種事情發(fā)生在服務(wù)器上,就可能導(dǎo)致大量事務(wù)或事件丟失,甚至發(fā)生嚴(yán)重的軟件故障。解決這一問(wèn)題最通常的做法是“抹去”閏秒,也就是說(shuō)每過(guò)幾個(gè)小時(shí)稍微修改一下時(shí)間。
規(guī)模建設(shè)NTP服務(wù)
Facebook的NTP服務(wù)分為四個(gè)層次:
·第0層是一層擁有極其精確原子鐘的衛(wèi)星,這些原子鐘來(lái)自全球?qū)Ш叫l(wèi)星系統(tǒng)(GNSS),如GPS、GLONASS和Galileo。
·第1層是Facebook的原子鐘,與GNSS同步。
·第2層是一個(gè)與層1設(shè)備同步的NTP服務(wù)器池。在這一層,閏秒開始出現(xiàn)。
·第3層是更大規(guī)模配置的服務(wù)器層。他們接收被處理過(guò)的時(shí)間,這一層就感知不到閏秒了。
在某些系統(tǒng)中,可能有多達(dá)16個(gè)層來(lái)分配工作,對(duì)層數(shù)的需求取決于系統(tǒng)規(guī)模和精度要求。
當(dāng)我們開始構(gòu)建NTP服務(wù)時(shí),我們測(cè)試了以下后臺(tái)程序使用的時(shí)間:
1.Ntpd:一個(gè)通用的后臺(tái)程序,Ntpd過(guò)去常常應(yīng)用在大多數(shù)類Unix操作系統(tǒng)中。多年來(lái),它一直是穩(wěn)定的解決方案,現(xiàn)在的大多數(shù)計(jì)算機(jī)上依舊運(yùn)行著Ntpd。
2.Chrony:一個(gè)比較新的后臺(tái)程序,它具有豐富的特性,并且可以為NTP提供精確的時(shí)間同步。Chrony還提供了可擴(kuò)展控制協(xié)議,理論上可以將精度降低到納秒。從資源消耗的角度來(lái)看,我們發(fā)現(xiàn)ntpd和chrony非常相似,chrony消耗的內(nèi)存甚至稍微少一些(大約有1 MiB的差異)。
評(píng)估后臺(tái)程序
無(wú)論系統(tǒng)是使用ntpd還是chrony,每個(gè)系統(tǒng)都提供了一些評(píng)估的度量方法。通過(guò)使用這些后臺(tái)程序的命令行工具可以進(jìn)行評(píng)估。這些評(píng)估是基于一定的假設(shè)為前提的,例如:
·客戶機(jī)和服務(wù)器之間的網(wǎng)絡(luò)路徑要有對(duì)稱性。
·當(dāng)時(shí)間戳被添加到NTP包并調(diào)用send()時(shí),操作系統(tǒng)會(huì)立即發(fā)送它。
·振蕩器的溫度和輸入電壓是恒定的。
Ntpd包含ntpq命令行工具,可以顯示時(shí)間沒(méi)有同步的狀態(tài):
[user@client ~]# ntpq -p
remote refid st t when poll reach delay offset jitter
=========================================================================
+server1 .FB. 2 u 406 1024 377 0.029 0.149 0.035
+server2 .FB. 2 u 548 1024 377 0.078 0.035 0.083
*server3 .FB. 2 u 460 1024 377 0.049 -0.185 0.114
然而,這些數(shù)據(jù)可信么?如果ntpd報(bào)告時(shí)間差了0.185 ms,是否準(zhǔn)確?答案是否定的。服務(wù)器根據(jù)包中的多個(gè)時(shí)間戳估計(jì)偏移量,而實(shí)際值應(yīng)該在一個(gè)10倍大的窗口內(nèi)。換句話說(shuō),差0.185毫秒的結(jié)果意味著偏差可能在+/-2毫秒內(nèi)(總共4毫秒)。我們的測(cè)試表明,ntpd的準(zhǔn)確性一般在10毫秒以內(nèi)。
我們有更高精度的技術(shù)要求。例如,多主數(shù)據(jù)庫(kù)將微秒甚至納秒的精度直接轉(zhuǎn)換為理論吞吐量。另一個(gè)需要中等精度的示例是日志記錄,為了在分布式系統(tǒng)的節(jié)點(diǎn)之間匹配日志,通常需要毫秒級(jí)的精度。
下面讓我們看看如果用chrony替換ntpd,效果會(huì)怎樣:
[user@client ~]# chronyc sources -v
210 Number of sources = 19
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current synced, '+' = combined , '-' = not combined,
| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable.
|| .- xxxx [ yyyy ] +/- zzzz
|| Reachability register (octal) -. | xxxx = adjusted offset,
|| Log2(Polling interval) --. | | yyyy = measured offset,
|| \ | | zzzz = estimated error.
|| | | \
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^+ server1 2 6 377 2 +10us[ +10us] +/- 481us
^- server2 2 6 377 0 -4804us[-4804us] +/- 77ms
^* server3 2 6 377 59 -42us[ -46us] +/- 312us
^+ server4 3 6 377 60 +11ns[-3913ns] +/- 193us
注意最后三個(gè)數(shù)字。在最后,從右向左看:
·最后一個(gè)數(shù)字是估計(jì)誤差。它的前綴是+/-。它表示chrony的最大誤差范圍。有時(shí)是10毫秒,有時(shí)是100微秒(100倍的差異)。這是因?yàn)楫?dāng)chrony與另一個(gè)chrony同步時(shí),使用擴(kuò)展的NTP協(xié)議,這極大地提高了精度。效果還不錯(cuò)。
·下一個(gè)是方括號(hào)中的數(shù)字。它顯示了測(cè)量的偏移量。除了server4(我們稍后將討論這個(gè)),其它的我們看到也大約有100倍的差異。
·方括號(hào)左邊的數(shù)字顯示的是最初的測(cè)量值,經(jīng)過(guò)調(diào)整后,允許自第一次測(cè)量以來(lái)的任何slews應(yīng)用于本地時(shí)鐘。同樣,我們可以看到ntpd和chrony之間的差異也是100倍。
請(qǐng)看下圖:
藍(lán)色豎線表示ntpd被chrony替換的時(shí)間點(diǎn)。對(duì)于ntpd,其范圍是+/-1.5 ms。用了chrony后,變動(dòng)范圍在微秒內(nèi)。更重要的是,估計(jì)誤差(窗口)下降到了100微秒的范圍,這些是可以通過(guò)實(shí)驗(yàn)室測(cè)量來(lái)確認(rèn)的(下面會(huì)有更多的介紹)。但是,這些值是用后臺(tái)程序估算的。實(shí)際上,實(shí)際時(shí)間可能完全不同。我們?nèi)绾悟?yàn)證這些數(shù)字的準(zhǔn)確性呢?
每秒脈沖數(shù)(1PPS)
我們可以從原子鐘中提取模擬信號(hào)(實(shí)際上是來(lái)自層1設(shè)備的內(nèi)部計(jì)時(shí)電路)。這個(gè)信號(hào)叫做1PPS,意思是每秒1個(gè)脈沖;它在每一秒的開始都會(huì)在同軸電纜上產(chǎn)生一個(gè)脈沖。這是一種主流的、精確的同步方法。我們可以在NTP服務(wù)器上生成相同的脈沖,然后比較各個(gè)階段的差異。這里有個(gè)困難點(diǎn)就是,并非所有服務(wù)器都支持1PPS,因此需要專門的網(wǎng)絡(luò)擴(kuò)展卡。
我們第一次測(cè)試是手動(dòng)完成的,使用了一臺(tái)顯示相移的示波器。
通過(guò)10分鐘的測(cè)量,我們估算出ntpd的偏移約為3.5毫秒,有時(shí)會(huì)跳到10毫秒。
這個(gè)測(cè)試在Facebook大規(guī)模服務(wù)器上實(shí)現(xiàn)起來(lái)是極其困難并且也不切實(shí)際。更好的測(cè)試方法是將測(cè)試服務(wù)器的1PPS輸出連接到層1設(shè)備本身的1PPS輸入,并監(jiān)控其差異。
這種方法可以實(shí)現(xiàn)上一個(gè)測(cè)試方法中所有優(yōu)點(diǎn),同時(shí)也不需要在數(shù)據(jù)中心使用示波器。如果使用該方法,我們能夠在任何時(shí)間點(diǎn)進(jìn)行測(cè)量并驗(yàn)證真實(shí)的NTP偏移量。
通過(guò)這兩個(gè)測(cè)量結(jié)果,我們對(duì)實(shí)際的NTP偏移有了很好的了解,使用1PPS誤差估計(jì)在納秒內(nèi),這主要是由電纜長(zhǎng)度導(dǎo)致的。
這些方法的不足之處是:
·電纜鋪設(shè):做這樣的測(cè)試需要同軸電纜。在不同的數(shù)據(jù)中心進(jìn)行測(cè)試需要更改數(shù)據(jù)中心的布局設(shè)計(jì),這是比較困難的。
·定制硬件:不是所有網(wǎng)卡都有1PPS輸出。這樣的測(cè)試需要特殊的網(wǎng)卡和服務(wù)器。
·層1設(shè)備需要1PPS輸入。
·服務(wù)器上需要安裝1PPS軟件:為了運(yùn)行測(cè)試,我們必須在我們的測(cè)試服務(wù)器上安裝ntpd。這個(gè)后臺(tái)程序可能會(huì)導(dǎo)致意外錯(cuò)誤,因?yàn)樗谟脩艨臻g中工作,并會(huì)被Linux調(diào)度。
專用測(cè)試設(shè)備
市場(chǎng)上有一些設(shè)備可以進(jìn)行準(zhǔn)確性測(cè)試。它們包含GNSS接收器,一個(gè)原子鐘,多個(gè)1PPS和網(wǎng)絡(luò)接口,還可以充當(dāng)NTP客戶端。這就讓我們可以直接使用NTP協(xié)議執(zhí)行相同的測(cè)試。接收到的NTP包由原子鐘或GNSS接收器以非常精確的時(shí)間戳記錄。
以下就是常見的裝備:
上面的照片是我們最初臨時(shí)用的測(cè)試設(shè)備。使用該設(shè)備進(jìn)行測(cè)量有以下幾個(gè)優(yōu)點(diǎn):
·它不需要額外的1PPS電纜。我們雖然仍然需要約束原子鐘,但這可以通過(guò)使用GNSS或?qū)?設(shè)備本身和一根短電纜來(lái)實(shí)現(xiàn)。
·它使用原子鐘的數(shù)據(jù)來(lái)標(biāo)記傳輸和接收的網(wǎng)絡(luò)數(shù)據(jù)包。這使得操作系統(tǒng)的影響可以忽略不計(jì),誤差率只有幾納秒。
·它同時(shí)支持NTP和PTP(精確時(shí)間協(xié)議)。
·該設(shè)備是便攜式的,我們可以在不同地點(diǎn)之間移動(dòng)它來(lái)執(zhí)行測(cè)試。
·設(shè)備使用自己的數(shù)據(jù)點(diǎn)集格式,但它可以將數(shù)據(jù)導(dǎo)出到CSV,也就是說(shuō)我們可以按我們的數(shù)據(jù)標(biāo)準(zhǔn)導(dǎo)出數(shù)據(jù)。
NTPD測(cè)量
結(jié)果與我們?cè)诤笈_(tái)程序評(píng)估和1PPS測(cè)量中看到的非常相似。首先,我們發(fā)現(xiàn)有一個(gè)10毫秒的下降,然后慢慢地修正為+/-1毫秒。有趣的是,這個(gè)10毫秒的下降是相當(dāng)穩(wěn)定的,并且在每次重啟后都會(huì)出現(xiàn)。
Chrony測(cè)量
這看起來(lái)與chrony后臺(tái)程序的估算非常相似,它比ntpd好10到100倍。
Chrony的硬件時(shí)間戳
Chrony極大地改善了偏移量,這可以從1PPS的估算結(jié)果和實(shí)驗(yàn)室設(shè)備值中看出。不過(guò)Chrony還支持硬件時(shí)間戳。根據(jù)文檔,Chrony聲稱可以將精度提高到幾百納秒以內(nèi)。
讓我們來(lái)看看網(wǎng)絡(luò)上NTP客戶機(jī)-服務(wù)器通信中的NTP包結(jié)構(gòu)。初始客戶端的NTP包包含傳輸時(shí)間戳字段。
服務(wù)器填充其余的字段(例如,接收時(shí)間戳),將客戶機(jī)的傳輸時(shí)間戳保存為原始時(shí)間戳,并將其發(fā)送回客戶機(jī)。
可以使用tcpdump驗(yàn)證此行為:
08:37:31.489921 IP6 (hlim 127, next-header UDP (17) payload length: 56) client.36915 > time1.facebook.com.ntp: [bad udp cksum 0xf5d2 -> 0x595e!] NTPv4, length 48
Client, Leap indicator: clock unsynchronized (192), Stratum 0 (unspecified), poll 3 (8s), precision -6
Root Delay: 1.000000, Root dispersion: 1.000000, Reference-ID: (unspec)
Reference Timestamp: 0.000000000
Originator Timestamp: 0.000000000
Receive Timestamp: 0.000000000
Transmit Timestamp: 3783170251.489887309 (2019/11/19 08:37:31)
Originator - Receive Timestamp: 0.000000000
Originator - Transmit Timestamp: 3783170251.489887309 (2019/11/19 08:37:31)
...
08:37:31.490923 IP6 (hlim 52, next-header UDP (17) payload length: 56) time1.facebook.com.ntp > server.36915: [udp sum ok] NTPv4, length 48
Server, Leap indicator: (0), Stratum 1 (primary reference), poll 3 (8s), precision -32
Root Delay: 0.000000, Root dispersion: 0.000152, Reference-ID: FB
Reference Timestamp: 3783169800.000000000 (2019/11/19 08:30:00)
Originator Timestamp: 3783170251.489887309 (2019/11/19 08:37:31)
Receive Timestamp: 3783170251.490613035 (2019/11/19 08:37:31)
Transmit Timestamp: 3783170251.490631213 (2019/11/19 08:37:31)
Originator - Receive Timestamp: +0.000725725
Originator - Transmit Timestamp: +0.000743903
...
客戶端會(huì)獲得數(shù)據(jù)包,附加另一個(gè)接收時(shí)間戳,并使用下面這個(gè)NTP RFC#958中的公式計(jì)算偏移量:
c=(t2-t1+t3-t4)/2
然而,Linux不是一個(gè)實(shí)時(shí)操作系統(tǒng),它要運(yùn)行的進(jìn)程不止一個(gè)。因此,當(dāng)傳輸時(shí)間戳被填滿并調(diào)用Write()時(shí),并不能保證立即通過(guò)網(wǎng)絡(luò)發(fā)送數(shù)據(jù):
另外,如果機(jī)器沒(méi)有足夠的流量,在發(fā)送NTP包之前可能需要一個(gè)ARP請(qǐng)求,ARP請(qǐng)求是不可靠的,這會(huì)導(dǎo)致估算錯(cuò)誤。但chrony支持硬件時(shí)間戳,使用這些方法,另一端的chrony可以高精度地確定數(shù)據(jù)包何時(shí)被網(wǎng)絡(luò)接口處理。雖然從網(wǎng)卡戳記數(shù)據(jù)包到它實(shí)際離開數(shù)據(jù)包之間仍然有一個(gè)延遲,但小于10ns。
還記得之前這個(gè)chronyc sources的輸出形式嗎?
^+server4 2 6 377 60+11ns[-3913ns]+/-193us
Chrony報(bào)告偏移量為11 ns。這是因?yàn)閱⒂昧擞布r(shí)間戳的結(jié)果。然而,估計(jì)誤差在幾百微秒的范圍內(nèi)。雖然不是所有的網(wǎng)卡都支持硬件時(shí)間戳,但是隨著它越來(lái)越受歡迎,網(wǎng)卡會(huì)慢慢支持這個(gè)特性。要驗(yàn)證對(duì)硬件時(shí)間戳的支持,只需運(yùn)行ethtool檢查,然后就可以看到硬件傳輸和硬件接收功能。
ethtool-T eth0
Time stamping parameters for eth0:
Capabilities:
hardware-transmit(SOF_TIMESTAMPING_TX_HARDWARE)
hardware-receive(SOF_TIMESTAMPING_RX_HARDWARE)
hardware-raw-clock(SOF_TIMESTAMPING_RAW_HARDWARE)
通過(guò)使用實(shí)驗(yàn)室設(shè)備測(cè)試相同的硬件,我們就可以得到不同的結(jié)果了,ntpd誤差顯示在-10毫秒和3毫秒之間(13毫秒的差異),chrony誤差顯示在-200微秒和200微秒之間,而且啟用硬件時(shí)間戳后,在大多數(shù)情況下chrony誤差都顯示在-100微秒和100微秒之間。這也證實(shí)了之前后臺(tái)程序的估算可能是不準(zhǔn)確的。
公共服務(wù)
現(xiàn)在,所有測(cè)量都在我們內(nèi)部控制的數(shù)據(jù)中心網(wǎng)絡(luò)中進(jìn)行。下面,我們看看當(dāng)我們?cè)诠睳TP服務(wù)或者其他一些著名的公共NTP服務(wù)提供商上測(cè)試時(shí),情況是什么樣的:
測(cè)量的結(jié)果好壞在很大程度上取決于網(wǎng)絡(luò)路徑以及網(wǎng)絡(luò)連接的速度和質(zhì)量。這些測(cè)量并沒(méi)有受到Facebook網(wǎng)絡(luò)的影響,針對(duì)的是來(lái)自不同地點(diǎn)、不同Wi-Fi和LAN網(wǎng)絡(luò)的服務(wù)進(jìn)行的多次測(cè)試。我們可以看到,我們的公共NTP服務(wù)不僅與其他主流的供應(yīng)相比有競(jìng)爭(zhēng)優(yōu)勢(shì),而且在某些情況下,它的性能也更優(yōu)。
公共NTP設(shè)計(jì)方案
在我們成功地將內(nèi)部精度提升到亞毫秒級(jí)別之后,我們就啟動(dòng)了一個(gè)公共NTP服務(wù),它可以通過(guò)設(shè)置time.facebook.com作為NTP服務(wù)器來(lái)使用。我們?cè)谖覀兊木W(wǎng)絡(luò)入網(wǎng)點(diǎn)(PoP)上運(yùn)行這個(gè)公共NTP服務(wù)。為保障私隱,我們不會(huì)按IP地址為設(shè)備設(shè)定指紋。為了在即使請(qǐng)求網(wǎng)絡(luò)路徑失敗的情況下也能提供更好的服務(wù),我們?cè)谖鍌€(gè)不同的地理位置都設(shè)置了端點(diǎn)。我們的五個(gè)端點(diǎn)如下:
·time1.facebook.com
·time2.facebook.com
·time3.facebook.com
·time4.facebook.com
·time5.facebook.com
每個(gè)端點(diǎn)都在不同的地理位置上,這對(duì)可靠性和時(shí)間精度都有積極的影響。
time2.facebook.com的網(wǎng)絡(luò)路徑如下:
time3.facebook.com的網(wǎng)絡(luò)路徑如下:
抹掉閏秒
Ntpd一直使用一種預(yù)發(fā)布的閏秒列表文件。有了這個(gè)文件,Ntpd就可以提前進(jìn)行時(shí)間修正,當(dāng)閏秒實(shí)際發(fā)生時(shí),也能保證時(shí)間是正確的。
Chrony依賴于GNSS提前幾小時(shí)發(fā)布的閏秒指示器。當(dāng)閏秒事件在UTC 00:00實(shí)際發(fā)生時(shí),在指定的時(shí)間段內(nèi)它就會(huì)被抹去。有了Facebook公共NTP服務(wù),我們決定采用更精確的方法,在事件結(jié)束后的大約18個(gè)小時(shí)內(nèi)抹去閏秒。
因?yàn)橥磕ú僮饕趯?的許多服務(wù)器上同時(shí)進(jìn)行,所以保持操作盡可能的相似是很重要的。按照平滑的正弦曲線規(guī)則進(jìn)行操作對(duì)應(yīng)用程序來(lái)說(shuō)是安全的選擇。
經(jīng)驗(yàn)總結(jié)
測(cè)量時(shí)間是非常具有挑戰(zhàn)性的。ntpd和chrony提供的估算方法在一定程度上都是正確的。一般來(lái)說(shuō),如果您想要監(jiān)控真實(shí)的偏移量,我們建議使用1PPS或帶有GNSS接收器和原子鐘的外部設(shè)備。
在比較ntpd和chrony時(shí),我們的測(cè)量結(jié)果表明chrony要精確得多,這就是我們將基礎(chǔ)設(shè)施遷移到chrony并啟動(dòng)公共NTP服務(wù)的原因。結(jié)果證明,將精度從幾十毫秒提高到幾百微秒是值得的。
使用硬件時(shí)間戳可以進(jìn)一步將精度提高兩個(gè)數(shù)量級(jí)。盡管NTP已經(jīng)有所改善,但它也有自己的局限性,因此對(duì)PTP的研究使用才有可能將您的精度提升到下一個(gè)級(jí)別。
英文原文:
https://engineering.fb.com/production-engineering/ntp-service/