Viser arkivet for stikkord lastbalansering

Nginx vs. HAProxy

Her på Origo har vi lenge kjørt Nginx, som i sin tid ble anbefalt av min kollega Johan Sørensen. Nginx er en super webserver, men vi har lenge slitt med at load-balanceren ikke duger.

Vi var tidlig ute med å bruke Grzegorz Noseks “fair load balancer”-modul finansiert av EngineYard; denne modulen hjalp veldig på ytelsen, men klarer ikke å fordele trafikken helt jevnt. Vi opplever også at den stadig slår krøll på halen og enten nekter å sende trafikk til aktive backends, eller plutselig begynner å spise minne og spytte ut gigabytes med loggdata.

Et vedvarende problem med servingen vår er at trafikken spiker når vi deployer en ny versjon, fordi requestene køes opp; siden Nginx slipper alt gjennom til mongrelene betyr det at de plutselig overlesses med trafikk. Etter en ny deploy får en del folk timeouts som gjerne utarter seg som “straks tilbake”-beskjeder, og det tar ofte flere minutter før tjenesten har stabilisert seg.

Etter å ha lest om HAProxy blant annet her tenkte jeg å sjekke ut produktet, og alt virker så langt ekstremt lovende:

  • HAProxy er kun en proxy—den kan ikke serve filer fra en katalog.
  • Den kan i prinsippet proxye alt av TCP, ikke bare HTTP.
  • Spesiell vekt på HTTP og lastbalansering.
  • Flere lastbalanseringsalgoritmer med vekting, bl.a. en fersk “leastconns”-algoritme som sender til backenden med kortest kø.
  • Kan kjøre logiske tester for å finne ut om en backend er oppe.
  • Flink til å skrive lesbare loggmeldinger når backends går opp og ned.
  • Har et super liten status-side som gir deg status, oppetid og metrics for tjenesten og alle front- og backends.
  • Kan logge ekstremt detaljerte data om trafikken.
  • Routing basert på alt mulig: cookies, deler av URL, klient-IP osv.

For å se om HAProxy duger har jeg nå gjort litt benchmarking for meg selv—ikke spesielt vitenskapelig, men det burde være av interesse for Railsere.

Jeg har kjørt 3 Origo-mongrels på en dedikert testmaskin proxyet med Nginx og HAProxy, og har kjørt Apaches benchmarkingverktøy, ab, mot en testside. Testsiden gjør minimalt med databasekall og som vanligvis tar under 20ms å rendre.

Jeg har konfigurert HAProxy med “leastconn”-algoritmen og maxconn 1 for hver mongrel, slik at hver mongrel får maks 1 connection samtidig. Sammenligningen er altså på ingen måte fair i forhold til Nginx—halve poenget her er å se hvordan HAProxy kan optimeres på en måte Nginx ikke kan. Denne konfigurasjonen betyr at connections blir sittende og vente i HAProxy i stedet for i Mongrel, og har den fordel at den ventende connectionen kan gå rett til en ledig backend i stedet for å måtte vente til når requesten foran i Mongrel-køen er ferdig.

De følgende grafene er klippet til 400ms slik at detaljene blir synlige.

Nginx med -n1000 -c3

HAProxy med -n1000 -c3

Nginx med -n1000 -c10

HAProxy med -n1000 -c10

Selv om HAProxy faktisk kommer bedre ut på requests/sekund uavhengig av belastning så er forskjellen mest merkbar i hvordan responstiden skalerer. Med 10 connections begynner Nginx å levere alle requestene ganske tregt, mens med HAProxy klarer å levere 95% av requestene innen omtrent samme tid som den raskeste requesten. HAProxy velger imidlertid å levere enkelte requests veldig sent.

For meg virker det som om HAProxy klarer å levere en mer stabil og forutsigbar tjeneste enn Nginx på bekostning av flere “blips”. I løpet av 1000 requests tok 0,16% over ett sekund, 0,1% over to sekunder, og 3 requests tok 10 sekunder hver. Her er en graf som viser disse pausene:

HAProxy med -n1000 -c10, ikke klippet

Det er interessant å se at selv med -c3 er Nginx litt ute å kjøre. Dette kan sees tydeligst i rådataene og visuelt i grafene. Det er umulig å si om dette er fordi “fair”-modulen som kjører flere requests mot samme backend, noe jeg vet den stadig vekk gjør på Origo. Det er også interessant å se at om jeg konfigurerer HAProxy med en høyere maxconn (f.eks. 100) så begynner den å oppføre seg mer som Nginx—dog ikke riktig like ille.

Dere finner rådataene her.