A következő címkéjű bejegyzések mutatása: ntp. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: ntp. Összes bejegyzés megjelenítése

2012-12-28

NTP szinkron ellenőrzése

Kétségbeejtően sokat foglalkozom Linuxszal mostanában, szerencsére itt is utolér néha egy-egy érdekesebb hálózati feladat. Nemrég például arra kellett választ adnom, hogy mekkora differenciával jár tetszőleges két Linux szerver órája egymáshoz képest egy adott LAN egy adott subnetjében. Természetesen van kiépített belső NTP infrastruktúra, szóval akár csípőből megválaszolható egy ilyen kérdés azzal, hogy általában LAN esetén egy-két ms körül lehet ez az érték, annál nem valószínű, hogy több lenne az eltérés bármelyik két hoszt között, ha jól működik az NTP. Ez persze egyrészt nem pontos válasz, másrészt ha nem elég meggyőző az ember, és nincs ott a prompt válasz előkészítve, amikor mondjuk egy konferenciahívás alatt felmerül a kérdés, könnyen olyan helyzetben találhatja magát, hogy már meg is kapta az egészet feladatként.

Ebben az esetben a fókusz tehát nem azon volt, hogy mennyire pontosak az órák vmilyen abszolútnak tekinthető stratum 1-es forráshoz képest, hanem hogy az adott subnet linuxos szerverein egymáshoz képest mennyire megbízhatók a logokban és adatbázisokban található timestampek, amely feladat első lépése annak a kiderítése, hogy mennyire pontosak a rendszerórák egymáshoz képest. Az NTP implementációval érkező diagnosztikai eszközök, pl. az ntpq ezeket az adatokat csak NTP szerver - NTP kliens viszonylatban tudja megmondani, nekünk általánosabb megoldásra volt szükségünk.

Egy rövid kis megbeszélés után arra jutottunk az egyik kollégával, hogy a legegyszerűbb talán az lenne, ha valamilyen multicast programmal szórnánk az aktuális timestampet valamelyik hostról (a timestamp lenne a tartalma a multicast a UDP csomagoknak), a többi szerveren meg sniffelnénk a hálózati forgalmat ngreppel, a multicast csomagok beérkezésének timestampjét pedig a csomagban lévő timestamppel összehasonlítanánk. Utána már csak a szerepeket kell forgatni a hostok közt, ha egy teljes mátrixot szeretnénk feltölteni az eredményekkel. Persze az eredmények nem lesznek teljesen pontosak, hiszen nem az órák közti differenciát fogják mutatni, benne lesz a timestamp feldolgozási ideje, UDP + IP + Ethernet csomagolása, az Ethernet késleltetése, stb. de azért adhat egy jó közelítést az órák pontosságáról. Ha például azt találjuk majd, hogy átlagosan +10 ms körüli az eltérés az átküldött timestamp és annak sniffelési ideje között, akkor az nem lesz túl rózsás eredmény, míg mondjuk ha csak 1 ms az átlagos eltérés az imént felsorolt feldolgozási idők hozzáadódása ellenére is, akkor nyugodtan hátradőlhetünk, minden rendben (üzleti oldalról az 1 ms-os pontosság az elvárás). El is kezdtem ilyesmire alkalmas programokat keresgélni, aztán persze addig faragtam a paramétereken, míg kiderült, hogy semmilyen extra programra nincs szükség, az egész tesztet meg lehet oldani az alap Ubuntu telepítéssel érkező programokkal.

A teszthez használt "szerver", ami az aktuális időbélyeget kiteszi hálózatra, nem kell hogy bonyolultabb legyen, mint egy date és netcat parancs, multicastra sincs szükség, hiszen subneten belül ugyanúgy megteszi a broadcast is:

date +%Y/%m/%d\ %k\:%M\:%S.%N | nc -b -u 192.168.0.255 6666

A parancs az ngrep kimenetének megfelelően formázott timestamp stringet fog elküldeni a megadott broadcast cím megadott portjára. Ubuntu 10.04-ben ez működik is, a 12.04-esben viszont lecserélték a netcat csomagot az OpenBSD netcatjére, ami sajnos nem tud broadcastolni, így Precise alatt a "netcat-traditional" csomagot is telepítenünk kell. A "kliens" oldal, ami a subnet összes gépén akár párhuzamosan is futhat, az ngrep megfelelően paraméterezve:

root@betazed:~# ngrep -q -t -d eth0 port 6666
interface: eth0 (192.168.0.0/255.255.255.0)
filter: (ip or ip6) and ( port 6666 )

U 2012/12/27 23:17:54.698920 192.168.0.4:60071 -> 192.168.0.255:6666
  2012/12/27 23:17:54.698705783.


U 2012/12/27 23:18:09.858924 192.168.0.4:36778 -> 192.168.0.255:6666
  2012/12/27 23:18:09.858708142.


U 2012/12/27 23:18:13.428859 192.168.0.4:38310 -> 192.168.0.255:6666
  2012/12/27 23:18:13.428650913.


Az adatok értelmezésére érdemes némi időt fordítani, az ngrep timestamp mikroszekundumban értendő, a közvetlenül alatta lévő sor pedig az UDP payload, ahol a date parancs által a másik hoszton előállított timestamp szerepel nanoszekundumos pontossággal. Itt például látszik, hogy az időbélyeg teljes feldolgozása, hálózaton átküldése és kliens oldali feldolgozása átlagban 213 mikroszekundum volt három különböző "szerver" futtatás alkalmával. Pontosan ugyanezek a a "szerver" lefutások természetesen más eredményt adnak egy másik hosztról nézve:

root@trill:~# ngrep -q -t -d eth0 port 6666
interface: eth0 (192.168.0.0/255.255.255.0)
filter: (ip or ip6) and ( port 6666 )

U 2012/12/27 23:17:54.699099 192.168.0.4:60071 -> 192.168.0.255:6666
  2012/12/27 23:17:54.698705783.

U 2012/12/27 23:18:09.859099 192.168.0.4:36778 -> 192.168.0.255:6666
  2012/12/27 23:18:09.858708142.


U 2012/12/27 23:18:13.429031 192.168.0.4:38310 -> 192.168.0.255:6666
  2012/12/27 23:18:13.428650913. 


Itt 388 mikroszekundum az átlagos eltérés a "szerver" által küldött időpont és az UDP szegmens "kliensre" beérkezésének időpontja között. Megint más lesz az eredmény egy harmadik "kliensről" vizsgálódva, ami sok tényezőtől függhet, például attól is, hogy hány switchen keresztül vezet az UDP broadcast útja, hiszen minden egyes switch hozzáadja a maga késleltetését. Rosszul járó órára akkor gyanakodhatunk, ha valamelyik hostról a küldött és fogadott adatok eredményei szignifikánsan eltérnek a többieken mértektől. A konklúzió nálunk az volt, hogy az órák egymáshoz képest meglepően pontosan járnak abban a subnetben, ahol a vizsgálatot végeztem, és a Wikipédián említett 1ms-os LAN-on elérhető NTP pontosságot messze túlteljesítjük. 

2012-08-31

Mekkora egy switch késleltetése?

A napokban egy összetett alkalmazáskésleltetés-mérési projekt kapcsán felmerült a kérdés, hogy hol legyen az első mérési pont a rendszerben. Maga a rendszer egy több hostos elosztott alkalmazás, amiben mindenfelé létre lettek hozva mérési pontok. Nyilvánvaló, hogy az első mérési pont ott kell, hogy legyen, ahol bejutnak az adatok a rendszerbe, ezt történetesen egy Linux. A teljes elosztott alkalmazás késleltetési ideje sok milliszekundumos nagyságrendben mozog, nekem meg sem fordult a fejemben, hogy az említett első mérési pontot nem ezen a gateway Linux rendszeren kellene létrehozni, de egy kolléga felvetette, hogy van ám az előtt a Linux előtt egy switch is, és hogy gyakorlatilag az az első eszköz a teljes rendszerben, azon kellene egy monitor portot konfigurálni, hogy valóban a legkorábbi ponton kapjuk el a bejövő adatokat.

Ekkor kibújt belőlem a networkös, hiszen a switching, akár a gyorsabb cut-through de még a lassabb store-and-forward esetében is a milliszekundumos nagyságrend alatt, mikroszekundumos berkekben mozog. Arról nem is szólva, hogy az elosztott rendszer hostjai közötti NTP szinkronizációnak is vannak korlátai, sosem törtem ilyenen a fejem, de állítólag LAN-on az NTP szinkronizáció precizitása jó, ha megüti a 20 mikroszekundumos tartományt. Ergo felesleges vesződni a monitor porttal, ha nem is tudjuk olyan precízen jegyzetelni az adatokat, amennyit az egyetlen switcheléssel korábbi sniffing jelentene.

Ennek apropóján utánanéztem, hogy tulajdonképpen mennyi az annyi: mekkora manapság a switchek késleltetése? Átpörgettem pár adatlapot különböző gyártóktól, és arra jutottam, hogy az enterprise termékek esetében a mezei 100Mb/s-es eszközöktől a 10Gb/s-es Ethernet eszközökig nagyjából néhány tíz mikroszekundumos késleltetéssel lehet számolni. Persze nehéz ezeket az adatokat összehasonlítani, hiszen nem ugyanazokkal a módszerekkel dolgoznak a különböző műhelyek a mérések során, van ahol a beérkező keret első bitjétől megy a stopper a kimenő keret első bitjéig, máshol (store-and-forward méréseknél) a beérkező keret utolsó bitjétől a kimenő első bitjéig. Gyakran nincs feltüntetve, hogy mekkora Ethernet keretméret mellett végezték a mérést, máshol egész adatsorok vannak egészen jumbo frame méretig. De úgy körülbelül a néhány tíz mikroszekundum jó közelítést ad, és ez nagyjából a kilencvenes évek közepe, az ASIC áramkörök switchekben való megjelenése óta így van. Az alapok a cisco.com-on elolvashatók a "Cut-Through and Store-and-Forward Ethernet Switching for Low-Latency Environments" doksiban.

Persze vannak extrém igényeket kielégítő termékek is. Úgy tűnik, hogy mostanában a low latency switching piacot leginkább a tőzsdei rendszerek, illetve azoknak is egy speciális szegmense, a High-Frequency Trading rendszerek fűtik. Az egyik, erre a piacra szakosodott gyártó, az Arista például 600 nanoszekundumos késleltetésű cut-through switchekkel hergeli a vevőit már a tervezési dokumentumaiban is, így rackek között is már 2,4 mikroszekundomot képesek elérni.

No, ettől messze vannak azok az eszközök, amikhez én hozzáférek, de épp volt kéznél egy 3Com 5500-EI, gondoltam kipróbálom, hogy mekkora a késleltetése, nem éppen mai darab, de legalább enterprise cucc. Az adatlap pusztán annyit közöl, hogy "Store-and-forward switching; latency <10 μs". Lássuk. Elővettem a Systimax patchkábeleket, két egyforma laptopot, egyforma OS-szel (Ubuntu 12.04.1), és céleszköz híján ment a ping, először 1000 bájtos mérettel:


50 packets transmitted, 50 received, 0% packet loss, time 48998ms
rtt min/avg/max/mdev = 0.462/0.495/0.528/0.036 ms

Hm... 495μs átlagos RTT-re, annak a fele 247,5μs, igaz ebben benne van az is, hogy a switchtől független két OS-en át kell verekednie magát, valószínűleg maga a kapcsolás sokkal rövidebb ideig tart, mint amennyi idő alatt a két végen lévő TCP/IP stacken átjut az ICMP, de valahogy akkor is kevesebbre számítottam. Aztán kipróbáltam 32 bájtos mérettel is:


50 packets transmitted, 50 received, 0% packet loss, time 48998ms
rtt min/avg/max/mdev = 0.167/0.184/0.218/0.021 ms

Így már csak 184μs az átlagos RTT, azaz egy átlagos odaút már csak 92μs, úgy, hogy ebben a két Linux TCP/IP stackje is benne van, nem csak a kapcsolás. Ez valóban sokkal közelebb van az adatlap alapján megcélzott <10μs-hez, gyakorlatilag én ezt a a <10μs adatot már simán el is hiszem.