Advanced Marchew-Qróliq Protocol

Konfiguracja poczty (przekazywanie, autoresponder) była zdecydowanie za długo na naszej liście rzeczy do zrobienia, ale w końcu udało się. Zadanie jest trywialne -- wygenerować prosty plik konfiguracyjny w znanym formacie. Tylko że zgodnie z zasadą perspektywy z bliska nic nie wygląda tak ładnie, jak wyglądało z daleka. Problem polega na tym, że panel administracyjny dla kont pocztowych mamy jeden, a serwerów, na których znajdują się owe konta całe stado.

Stąd tam

Jasne było, że potrzebujemy jakiegoś mechanizmu RPC do komunikacji serwerów z panelem. W grę wchodziło zaadaptowanie i rozszerzenie używanego już przez nas tajnego-przez-poufne RPC w Perlu, ale szybko tę opcję odrzuciliśmy. Dawno temu to (po dziś dzień bezimienne) RPC pozwoliło nam szybko uruchomić i obsłużyć rozproszone środowisko, ale czasy swojej świetności ma już za sobą i należy mu się raczej zasłużony odpoczynek niż dokładanie nowych zadań, do których niespecjalnie pasuje. Dlatego też szukaliśmy takiego rozwiązania, na którym będziemy mogli oprzeć całość komunikacji między komponentami MegiTeam.

Przede wszystkim musieliśmy wybrać protokół komunikacji. Im bardziej standardowy i popularny, tym lepiej. A jeszcze lepiej by było, gdybyśmy nie musieli pisać ani linijki kodu, żeby z niego skorzystać. Aż tak dobrze niestety nie było, ale o tym za chwilę.

Pierwszym poważnym kandydatem był func. SSL, HTTP, XMLRPC, całkiem przyjemne API do tworzenia nowych modułów -- czego chcieć więcej? func nadawał się idealnie jako tradycyjne RPC, ale potrzebowaliśmy czegoś lżejszego i bardziej elastycznego (wyobrażacie sobie sysloga po XMLRPC?). Poza tym, próbowaliście znaleźć coś w sieci na temat funca? Google go wybitnie nie lubi.

W międzyczasie zetknęliśmy się z takim wynalazkiem jak kolejki komunikatów. Pewnie wielu z Was ich używa do odraczania jakichś zadań na później (przetwarzanie plików wideo czy chociażby generowanie miniaturek w dużych ilościach) i do rozkładania obciążenia na kilka serwerów. Sama idea jest jednak o wiele bardziej uniwersalna i pozwala na bardzo szybką wymianę komunikatów oraz elastyczny routing komunikatów, gdyż producenci i konsumenci nie muszą zbyt wiele wiedzieć o sobie nawzajem. Ponieważ jeden obraz wart jest tysiąc słów, odsyłam do 87000 słów prezentacji Paolo Negri z RuPy 2009:

Ale miało być RPC

OK, mamy szybkość, mamy elastyczność, ale gdzie tu RPC? Protokół AMQP jest wybitnie jednostronny (odbiorca może jedynie potwierdzić otrzymanie wiadomości) i nie definiuje żadnego formatu przesyłanych danych. Musieliśmy czymś go przykryć. Żaden z gotowych frameworków RPC-po-AMQP nie przypadł nam szczególnie do gustu (najbliżej był qam), ale na scenę wkroczył dzielnie Janek Kaliszewski i dokonał niemożliwego -- dostarczył kod nie dość że działający, to jeszcze w terminie. Zanim całość ujrzy światło dzienne jako projekt OpenSource (parę drobiazgów musimy jeszcze dopieścić i udokumentować), na zaostrzenie apetytu kawałek kodu przykładowego serwera:

import re

__rpc_methods__ = '*', 're.*'

# tu różne metody testowe

Dokładnie tyle trzeba, żeby ze zwykłego modułu pythonowego zrobić moduł dostępny przez RPC! Samo opublikowanie modułu w drzewie metod RPC jest równie proste (jedna linijka w JSONowym pliku konfiguracyjnym) i już możemy wywołać mtrpc_client.example.re.split(':', 'a:b:c') na dowolnym serwerze.

Tam, gdzie model RPC się nie sprawdza, możemy użyć bezpośrednio AMQP. W odróżnieniu od np. HTTP (którego też w zasadzie mogliśmy użyć bezpośrednio), załatwia nam to problem uwierzytelniania (uprawnienia określamy w jednym dobrze wybranym miejscu, zamiast na każdym serwerze z osobna) oraz kolejkowania (jeżeli np. dana usługa chwilowo nie działa). Wbudowane kolejkowanie wiadomości pozwala nam również na uruchamianie niektórych usług (nie wymagających ani odpowiedzi, ani szybkiego przetwarzania) z crona zamiast trzymać je cały czas w pamięci. Bo możemy. Spróbujcie tego z HTTP :)

Dodał: Grzegorz Nosek

23 maja 2010



blog comments powered by Disqus