Annak idején írtam róla, hogy egy cégnél a web szerverek és a mögöttük levő webszervizek közötti kommunikációban jelen van egy 200ms-os plusz késleltetés, amire nem találtunk racionális magyarázatot.
Semmilyen eddig bevált eszköz, profilerek, WinDebug, Dynatrace, logok elemézése nem adott magyarázatot a jelenségre.
A Google a Nagle és a Delayed Ack irányába tolta a vizsgálódást.
Végül wiresharkkal alaposan kielemezve a forgalmat kiderült, hogy a protokoll leírással szemben csak 200ms késleltetéssel küldtek Acknowledge-et egymásnak a felek, ez adott késleltetést minden híváshoz. Miután a delayed ackot kikapcsoltuk mindkét oldalon, a jelenség megoldódott. A megoldás szerintem csak workaround, mivel a tcp protokol rfcje alapján nem így kellene működni a hálózatnak, vagy a Windows vagy a VMWare network card driver a bugos.
Röviden, mi zajlik itt le. A kliens (web app) TCP kommunikációt kezdeményez a webszerviz felé. A TCP protokollban minden csomag vételét meg kell erősíteni a másik oldalnak. Esetünkben olyan kicsi kérések mentek a szerviz felé, hogy belefértek egy hálózati csomagba. A Nagle algoritmus már eleve bufferelhetné a hívó oldalon a csomag kiküldését, de ezt úgy néz ki a generált webszerviz proxy kikapcsolja a Naglét, így ez nem okozott problémát.
Átmegy a kérés a szervizbe. Onnan egy acknowledgenek kell visszamenni a kliensre, jelezve, hogy a szerviz megkapta a csomagot. Ezt nem akarja visszaküldeni a szerviz azon mód, pár bájt miatt nem akar egy teljes csomagot visszaküldeni. A protokol alapján vár arra, amíg amúgy is küldene valamit vissza a kliensnek, és annak a hátára rakná rá az acknowledget (piggybacking).
Esetünkben volt sok kérés, lett volna alkalma visszaküldeni gyorsan a megerősítést, de nem tette. A protokollban van egy másik elem is. Ha eltelik 200ms, akkor ha eddig nem volt alkalmunk visszaküldeni a választ, legalább 200ms múlva meg kell tenni. Ez a delayed ack. Meg is tette a szerver, de ezzel minden egyes kérésre az ackot 200ms múlva küldte csak vissza. A kikapcsolással pazarló módon minden egyes csomagot azonnal visszajelez a szerver, azaz kikapcsoltuk ezt az optimalizálást, de cserébe a bugos késleltetés kiesett.
Összegezve, a válasznak vissza kellett volna menni más kérésekre adott válaszok hátán, de nem mentek vissza, ezért állítom, hogy ez bug, a delayed ack kikapcsolás csak workaround, de legalább megoldotta a késleltetést.
Két kép, ami szemlélteti a hibát.
Az első egy csatornán a kommunikáció lépéseit mutatja meg (a http keepalive miatt sok kérés meg át egy tcp csatornán). Látható, hogy nagyon sok kérésre csak 200ms múlva jön meg a válasz.
A második képen sok kérés ackjának maximuma látható. Jól megfigyelhető a “fék” hatása.
Sajnos nincs kéznél képem, de a delayed ack kikapcsolása után lemegy pár száz mikro!secre a válasz, mivel ilyenkor buzgó módon azonnal megy vissza az ack.
Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.
LEAVE A COMMENT
3 COMMENTS
Szép munka volt.
Köszi, nehéz, de szép munka volt.