Zredukowanie ilości połączeń do serwerów memcache
Napisał: Patryk Krawaczyński
30/01/2014 w Administracja 1 komentarz. (artykuł nr 433, ilość słów: 1323)
T
wemproxy (wymawiane “two-em-proxy”) lub nutcracker jest szybkim i lekkim proxy dla protokołów memcached (ascii) oraz redis. Został zbudowany przez programistów z firmy Twitter w celu zredukowania ilości połączeń do serwerów cache znajdujących się w backendzie. Przy dużej ilości serwerów frontowych łączność z warstwą cache lub systemem sesji za pomocą normalnej komunikacji może być bardzo kosztowny.
Twemproxy potrafi zapewnić nam stałe połączenia z serwerami memcache, których ilość jest utrzymywana w niskiej wartości (przy standardowej konfiguracji zazwyczaj jedno per serwer) oraz potokowe przetwarzanie żądań i odpowiedzi. Jeśli zależy nam na wykorzystaniu tego proxy do obsługi sesji lub warstwy cache przez kilka serwerów memcache – możemy bez problemu użyć jednego z kilku algorytmów hashingu i rozkładu komunikacji, które potrafią nam zapewnić sharding danych pomiędzy różne serwery. Poniżej znajduje się skromny test przeprowadzony za pomocą narzędzia memcslap na maszynie wirtualnej o parametrach 4vCPU/4GB RAM bez żadnego tuningu stosu TCP/IP, a cała komunikacja odbywała się po lokalnym interfejsie:
Konfiguracja:
test: listen: 127.0.0.1:60666 hash: fnv1a_64 distribution: ketama timeout: 1000 backlog: 1024 preconnect: true server_connections: 5 auto_eject_hosts: true server_retry_timeout: 30000 server_failure_limit: 2 servers: - 127.0.0.1:11219:1 - 127.0.0.1:11220:1 - 127.0.0.1:11221:1 - 127.0.0.1:11222:1
Ilość serwerów memcache: 1
root@stardust:~# memcslap -s 127.0.0.1:60666 -c 100 -x 10000 servers : 127.0.0.1:60666 threads count: 1 concurrency: 100 execute number: 10000 windows size: 10k set proportion: set_prop=0.10 get proportion: get_prop=0.90 cmd_get: 9000 cmd_set: 1000 get_misses: 0 written_bytes: 1735000 read_bytes: 9998000 object_bytes: 1088000 Run time: 0.4s Ops: 10000 TPS: 26076 Net_rate: 29.2M/s
Ilość serwerów memcache: 2
root@stardust:~# memcslap -s 127.0.0.1:60666 -c 100 -x 10000 servers : 127.0.0.1:60666 threads count: 1 concurrency: 100 execute number: 10000 windows size: 10k set proportion: set_prop=0.10 get proportion: get_prop=0.90 cmd_get: 9000 cmd_set: 1000 get_misses: 0 written_bytes: 1735000 read_bytes: 9998000 object_bytes: 1088000 Run time: 0.4s Ops: 10000 TPS: 24734 Net_rate: 27.7M/s
Ilość serwerów memcache: 3
root@stardust:~# memcslap -s 127.0.0.1:60666 -c 100 -x 10000 servers : 127.0.0.1:60666 threads count: 1 concurrency: 100 execute number: 10000 windows size: 10k set proportion: set_prop=0.10 get proportion: get_prop=0.90 cmd_get: 9000 cmd_set: 1000 get_misses: 0 written_bytes: 1735000 read_bytes: 9998000 object_bytes: 1088000 Run time: 0.7s Ops: 10000 TPS: 17439 Net_rate: 16.2M/s
Ilość serwerów memcache: 4
root@stardust:~# memcslap -s 127.0.0.1:60666 -c 100 -x 10000 servers : 127.0.0.1:60666 threads count: 1 concurrency: 100 execute number: 10000 windows size: 10k set proportion: set_prop=0.10 get proportion: get_prop=0.90 cmd_get: 9000 cmd_set: 1000 get_misses: 0 written_bytes: 1735000 read_bytes: 9998000 object_bytes: 1088000 Run time: 0.9s Ops: 10000 TPS: 14647 Net_rate: 13.0M/s
Utrzymywanie stałych połączeń:
root@stardust:~# netstat -tapn | grep nutcracker tcp 0 0 0.0.0.0:22222 0.0.0.0:* LISTEN nutcracker tcp 0 0 127.0.0.1:60666 0.0.0.0:* LISTEN nutcracker tcp 0 0 127.0.0.1:39970 127.0.0.1:11221 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:50482 127.0.0.1:11219 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:60032 127.0.0.1:11222 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:39968 127.0.0.1:11221 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:39963 127.0.0.1:11221 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:39969 127.0.0.1:11221 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:56093 127.0.0.1:11220 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:50483 127.0.0.1:11219 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:50339 127.0.0.1:11219 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:56090 127.0.0.1:11220 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:50473 127.0.0.1:11219 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:60161 127.0.0.1:11222 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:60166 127.0.0.1:11222 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:60167 127.0.0.1:11222 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:39830 127.0.0.1:11221 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:50468 127.0.0.1:11219 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:60168 127.0.0.1:11222 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:55961 127.0.0.1:11220 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:56096 127.0.0.1:11220 ESTABLISHED nutcracker tcp 0 0 127.0.0.1:56091 127.0.0.1:11220 ESTABLISHED nutcracker
Jak widzimy wydajność wraz z dokładaniem serwerów memcache nieznacznie spada – jednak wszystko zależy od środowiska testowego (tutaj maszyna wirtualna łącząca się sama ze sobą) i użytych algorytmów do hashingu i podziału komunikacji. Twemproxy posiada możliwość automatycznego odłączania problematycznych serwerów po ustalonej liczbie prób – ale jest jeden problem z tym mechanizmem (przynajmniej w wersji 0.3.0) – po ustalonym czasie np. 30 sekund – podłącza je ponownie, aby ponownie je odłączyć po tym, jak połączenia od klienta nie powiedzą się daną ilość razy. Proces ponawia się, co 30 sekund dopóki problem z serwerem memcache nie ustąpi. Oznacza to, że w przypadku awarii, co najmniej jednego serwera, co najmniej dwie operacje przeznaczone do tego serwera memcache w przedziale 30 sekund będą kończyły się niepowodzeniem. Obejściem tego problemu może być ustawienie tak dużej wartości timeout, aby awaria takiego serwera lub komunikacji do niego została zauważona i naprawiona.
Więcej informacji: Twemproxy, Nutcracker
Na pewno warto obserwować ten projekt pod kątem dalszego rozwoju, ponieważ w zakładce branches widnieją już “binary_memcache”, czyli obsługa binarnego protokołu oraz “twemproxy_heartbeat” – usunięcie wyżej opisanego problemu z połączaniem i odłączaniem serwerów bez inteligentnego sprawdzania, czy serwer może zostać przywrócony do komunikacji.