Erlang spisuje się nie tylko w fazie prototypowania. Historia Michała Zajda
Michał Zajda zauroczył się Doliną Krzemową. – To było miejsce, gdzie wszystko się działo – mówi. Gdy dostał propozycję pracy w startupie, który robił komunikator i chciał konkurować z największymi, od razu na nią przystał. – Miałem już doświadczenie ze współpracy z firmami z zachodniego wybrzeża, wiedziałem, że tam robi się produkty z rozmachem – dodaje.
Jak pracuje się w Dolinie Krzemowej? Jak wygląda rekrutacja? I najważniejsze, dlaczego Michał tak bardzo wierzy w Erlanga? Tego wszystkiego dowiecie się z poniższej rozmowy Michałem Zajdą, Engineer, Architect oraz Team Lead w aeternity.
Kiedy pierwszy raz usłyszałeś o Erlangu?
Na pierwszy raz z Erlangiem złożyło się parę zdarzeń. Po pierwsze, na początku studiów na AGH mieliśmy zajęcia ze współbieżności i korzystaliśmy z Erlanga. Druga rzecz to organizowana w tamtym czasie konferencja w Krakowie, na którą przyjechał jeden z twórców Erlanga, Joe Armstrong. Trzecia to świeżo wydana książka Joe. Zarówno książka, jak i sam autor były bardzo inspirujące.
Jakie miałeś wówczas zdanie na temat tego języka?
Na pierwszy rzut oka język nieco odrzuca, gdyż ma dziwną składnię. Jednak drugie spojrzenie na jego możliwości, czyli przetwarzanie równoległe i praca w sieci, już nie pozwala się od niego oderwać. W tamtym czasie mieliśmy pierwsze tanie komputery z wieloma cora’mi. Do tego alternatywy do oprogramowania sieci z Javy czy C były drogą przez mękę. Maszyna wirtualna Erlanga wprowadzała abstrakcję i rozwiązanie tych wszystkich problemów.
Co zmieniło się od tego czasu?
Wiele i niewiele. Team utrzymujący Erlanga optymalizuje go co kilka miesięcy. Mamy szybsze i mniej blokujące się struktury danych. Szczególnie ciekawe zmiany zaszły za to w całym ekosystemie erlangowym. Erlang zyskiwał coraz większą sławę z powodu skalowalności w komunikatorach internetowych. eJabberd było dwa rzędy wielkości bardziej wydajne niż alternatywa. Nie mówiąc o customowych implementacjach, typu tej w WhatsAppie. Powstały bazy danych w Erlangu. Poza tym zaczęły powstawać nowe języki na VMce Erlanga, takie jak Elixir, które są już bardzo przyjemne nawet do patrzenia.
Powstało wiele książek, stron, dokumentacji. Konferencje o Erlangu odbywały się już na całym świecie. Myślę, że zbudował się duży fan base Erlanga i Elixira (tego drugiego pewnie nawet większy).
Dlaczego Twoim zdaniem warto używać Erlanga i gdzie sprawdzi się najlepiej?
Erlang jest kompletnym językiem funkcyjnym i sprawdzi się w każdym systemie. Takie systemy o wiele łatwiej utrzymać i przetestować. W systemach rozproszonych Erlang sprawdzi się bez pudła. Znacznie uprości myślenie o sieci i wszystkich szczególnych warunkach w niej zachodzących. Z własnych doświadczeń dodam, że utrzymywanie setek tysięcy połączeń na jednym hoście jest bezproblemowe w Erlangu, a komunikacja setek takich hostów też jest OK.
Musimy również patrzeć na technologię z punktu widzenia zarządzania projektem. Z powodu bardzo zwięzłej i czystej składni, Erlang sprawdza się tam, gdzie mamy dużo prototypowania. Ten właśnie przypadek zaszedł w moim obecnym projekcie, platformie blockchain napisanej od zera. Nie wszystkie rozwiązania są dobrze zdefiniowane, bo to bardzo młoda klasa systemów. Możemy szybko iterować się przez zmiany. Mamy dostępny jeden z bardziej zaawansowanych frameworków do testowania. Takie rzeczy bardzo obniżają ryzyko w projekcie.
Korzystasz z Erlang Distributed?
W projekcie blokchainowym Aeternity nie korzystamy z Erlang Distributed. Naszą sieć p2p odwiedziło kilkanaście tysięcy węzłów. Teraz jest zbudowana z kilkuset. Dla jasności: Erlang Distributed jest trybem uruchamiania systemu, który pozwala pracować wielu osobnym maszynom wirtualnym, bardzo możliwe, że na różnych odległych hostach, w sposób umożliwiający bezpośrednią komunikację między procesami.
Na początku lat 2000 był to bardzo popularny tryb. Bardzo dobrze wspierał architekturę np. komunikatorów internetowych. Sesja każdego użytkownika była reprezentowana przez jeden lekki proces. Mogliśmy mieć ich kilkaset tysięcy na jednej VMce. Następnie wszystkie VMki były uruchomione w Distributed Erlang i wiadomości między użytkownikami były wiadomościami między procesami. Były zatem bardzo tanie i bardzo szybkie. Odbywało się to w czasach uruchamiania systemów na własnym sprzęcie, we własnych kolokacjach.
Trzeba jednak zaznaczyć, że wtedy Erlang VM nie działał optymalnie. Osobiście deployowałem klastry erlanga do 50-60 nodów dla jednej warstwy, testowe nawet większe, przez co w szczycie ruchu pojawiały się problemy ze spójnością klastra. Dlatego też uważamy grupy po 8-12 nodów za optymalne i tworzymy tzw. federacje klastrów. To dość ważne założenie, bo często potrzebujemy kilkuset nodów, żeby obsłużyć ruch.
Gdzie zatem Erlang Distributed sprawdzi się lepiej?
Erlang Distributed sprawdzi się świetnie w wyizolowanym, zaufanym środowisku (gdyż połączenie VMek daje dostęp innym węzłom do całej pamięci). Dobrym przykładem są systemy obsługujące np. fabrykę, linie montażowe itp.
Aktualnie widzę zastosowania takiej konfiguracji w systemach bazodanowych, które opierają się o niewielką liczbę nodów master. Korzystamy tutaj z zalet wspólnej pamięci, dostępu do niezależnego sprzętu i nie odczuwamy wad, jakie powoduje obsługa dziesiątek czy setek węzłów w jednym klastrze.
Drugim dobrym zastosowaniem Erlang Distributed są systemy na krawędzi naszej chmury, służące do trzymania sesji, kojarzenia cięższego procesu na backendzie z przychodzącym requestem. Takie systemy będą bardzo lekkie w komunikowaniu zewnętrznego świata z instancją usera w głębszej warstwie systemu. Taka architektura ogranicza koszty i ułatwia debuggowanie.
Gdzie się nie sprawdzi?
W warunkach niestabilnej sieci, wywłaszczanych hostów itp., czyli codzienności w taniej chmurze. Tutaj będzie potrzebny bardziej bezstanowy protokół do komunikacji, a Erlang pomoże nam w reprezentacji procesów już wewnątrz VMki.
Erlang na pewno pomógł Wam w kwestiach związanych ze skalowalnością. Jakie napotkaliście problemy wydajnościowe?
Erlang przez długi czas był bezkonkurencyjny w skalowaniu połączeń z zewnętrznego świata. Niezależnie od protokołu; HTTP, XMPP, AMQP, ten sam kod mógł obsłużyć zarówno kilka, jak i kilkaset tysięcy połączeń na jednym serwerze.
Dość powszechnym problemem była konfiguracja systemu operacyjnego. Np. timeouty i długości kolejek w kernelu. Przy dużych ilościach użytkowników musieliśmy patrzeć na pamięć, usprawniać popularne frameworki. Ale mówimy tu już o systemach, które mają kilkadziesiąt milionów użytkowników.
Erlang kupował dużo czasu startupom, które na początku mają problemy z każdym aspektem rozwoju produktu. Izolacja procesów bardzo pomaga rozwijać projekt.
Jakie masz uwagi i wskazówki dla osób, które muszą radzić sobie z podobną klasą problemów?
Mam chyba standardowe rady: po pierwsze wiedzieć co się chce zrobić. Jasno wyznaczyć cele i potencjalne problemy. Wtedy możemy projektować system; dobrze poczytać, jak podobne problemy rozwiązały inne zespoły. Które gotowe produkty rozwiążą nasze problemy. Warto wiedzieć, gdzie jest potrzebna niezawodność, a gdzie np. szybkość reakcji systemu.
Ja, żeby ułatwić sobie życie, staram się projektować system z jak najbardziej bezstanowych i wyizolowanych komponentów. W celu podniesienia „dziewiątek” w niezawodności, mogę użyć replikacji o wiele łatwiej. Przy takiej replikacji bez wysiłku uzyskujemy również wydajność.
W jakich sytuacjach napotkałeś problemy, w których Erlang nie sprawdzał się zbyt dobrze? Jak sobie z nimi poradziliście?
Myślę, że należy tu wymienić popularny błąd stosowania klastrów erlangowych
w niestabilnej sieci. O ile Erlang dobrze sobie ze wszystkim radzi, reportuje problemy z siecią i procesami na odległych węzłach, to presja na bazę danych, która ma być spójna w warunkach szczytowego ruchu, prowadzi do problemów.
Najpowszechniejsze problemy powodują – z uwagi na niszowość Erlanga – że zawsze trzeba sprawdzić dostępność bibliotek do parsowania czy rozmawiania z różnymi backendami.
Gdybyś miał do dyspozycji inny tech-stack, to czy osiągnąłby rezultat w tym samym czasie?
Bardzo trudno porównać rozwój oprogramowania w dwóch różnych stackach. Zauważyłem, że Erlang dobrze się spisuje w fazie prototypowania systemu. Również, patrząc z innej strony, systemy napisane z myślą o pracy na nich przez dziesiątki lat dobrze tworzy się w Erlangu. Średni horyzont czasowy jest zapewne dobrze wspierany przez technologie takie jak Java. Tam wsparcie dla produktów typu enterprise może być większe. Dostępność programistów również jest większa.
Czy osiągnąłbym ten sam rezultat? Oczywiście, ale inną drogą. JVM już jest jedną z najlepszych maszyn wirtualnych, dobrze wspiera przetwarzanie równoległe, jednak pozostawia bardzo dużo pracy programiście. Taka sytuacja generuje bugi, z reguły najcięższe do wykrycia i naprawy.
Częstym przypadkiem z którym się spotykam, jest pisanie wczesnych wersji w Erlangu, a ostatecznie, gdy nie jesteśmy w stanie rozwijać zespołu i inwestować w tę technologię, migrujemy na coś mainstreamowego. Nie przez przypadek użyłem słowa „wczesne” zamiast pierwsze, gdyż te pierwsze zawiodły pod względem wydajności. Tym sposobem, Erlang został sprowadzony do projektu na ratunek.
Zauważyłem też popularność Erlanga nie tylko w prototypowaniu produktu, lecz także w prototypowaniu nowych protokołów. Zdarzyło się to z XMPP (czyli eJabberd), naszym blockchainem, czy na przykład jedną z pierwszych implementacji bazy Amazon Dynamo.
Podsumowując, zawsze za coś zapłacimy. Im dłużej zajmuję się technologią, tym mniejszą wagę przykładam do konkretnego rozwiązania.
Jak Erlang sprawdza się na produkcji? W szczególności od strony utrzymania, debugowania i walki z problemami?
Erlang wyznaczył tutaj nowe standardy. Szczególnie przyjemna jest możliwość interakcji przez erlangowy shell z produkcyjną maszyną wirtualną. Pozwala to stosować bezpośrednio na produkcji debuggery, napisane konkretnie z myślą o wielkich systemach, działających pod dużą presją.
Pamiętajmy, że dokładnie w tym celu Ericsson zaprojektował i stworzył Erlang. Możemy w nim zbadać problemy, których odtworzenie w warunkach testowych byłoby dużym wyzwaniem.
Z ciekawostek dodam, że w Erlangu można zmieniać działający kod “w locie”. W większych systemach trzeba być ostrożnym, ale w kryzysowych sytuacjach szybki fix może zaważyć o stabilności systemu.
Nie brakuje Ci czasem statycznego typowania? W jaki sposób radzisz sobie
z większymi refaktorami bez statycznego typowania?
Rzeczywiście, statyczne typowanie daje poczucie komfortu. Nie brakuje mi go, więc chyba to stawia mnie po stronie fanów dynamicznych języków. Bezpieczeństwo kodu staram się zapewnić testami w różnych warstwach. Unit testy lokalnie, testy integracyjne i systemowe. Do tego property-based testing w świetnym framework’u QuickCheck. Generuje on ogromne ilości losowych argumentów do funkcji i w razie błędu stara się odnaleźć najmniejsze wejście, które powoduje błąd. QuickCheck też jest napisany w Erlangu!
Reasumując, bardziej cenię sobie możliwość lekkiego i częstego refaktoringu, niż pozorne bezpieczeństwo statycznego typowania. Oczywiście zwiększa się wtedy presja na testy i na infrastrukturę do ich działania (jak automatyzacja continuous integration i continuous deployment), ale to akurat dobry efekt uboczny.
Które cechy Erlanga sprawiają, że nadaje się do Blockchaina?
Ciekawe pytanie. Blockchain to system, który żyje w sieci. Komunikacja z zewnętrznym światem jest tu kluczowa. To pierwszy obszar, gdzie Erlang nam pomaga, ze wszystkimi narzędziami z biblioteki wspomagającymi współpracę z komunikacją przez sieć. Erlang jest funkcyjny, dzięki temu łatwiej testować nam sam kod. Z niskopoziomowych rzeczy muszę wymienić wygodną możliwość do przeskoczenia do pracy na bitach. Tzw. Bitsyntax upraszcza pracę z protokołami kryptograficznymi, które budują strukturę sieci, np. Noise protocol.
Kolejny obszar to wsparcie równoległego przetwarzania. Węzeł blokchain robi wiele rzeczy naraz: zarządza mempoolem, przygotowuje bloki, odbiera i waliduje bloki, sprawdza czy ma klucze, czasem kopie Proof of Work. Dzięki lekkim procesom możemy dobrze rozgraniczyć te funkcjonalności i mieć pewność, że się nie blokują. Tu, przy PoW, od razu wychodzi nam kolejna zaleta: jako wysokopoziomowy język, Erlang nie byłby dobry do kopania Proof of Work. Dzięki temu, że mamy kilka gotowych technik komunikacji z zewnętrznymi procesami systemu operacyjnego, możemy prosto i bezpiecznie wydelegować tę pracę do niskopoziomowych języków jak C.
Do tego długiego spisu dodam dwa dodatkowe obszary, jeden ogólny, jeden dość techniczny.
Ok.
W blockchainach istnieje pojęcie tzw. Drugiej Warstwy (Layer-2). Są to rozwiązania, które traktują blockchain jako platformę i implementują produkty w oparciu o maszynę wirtualną, wspieraną przez tę platformę. Jednym z bardzo oczekiwanych rozwiązań są State Channele. Jest to system połączeń point-to-point, wsparty przez blockchain, który jest jego arbitrem. State Channele otwierają wiele biznesowych i technicznych możliwości.
Niestety, pomimo wielu lat pracy nad nimi, z powodu gigantycznej ilości szczególnych przypadków, ich implementacja nie jest łatwa. Tutaj chciałbym zareklamować nie tylko Erlanga, lecz także nasz zespół od State Channeli, który dostarczył jedną z działających implementacji, właśnie dzięki Erlangowi. Szczególnie pomocne były wzorce Finite State Machine z biblioteki standardowej i wiele możliwości testowania funkcyjnego kodu.
Drugi obiecany obszar to zarządzanie projektem. Znów wracam tu do prototypowania samego produktu, jak i technologii. Blockchain jest tak młodą klasą systemów, że Erlang daje mu tutaj dużą dźwignię. Prostota refaktoringu, bardzo szybkie wdrożenie i obserwacja pomagają zespołowi wybrać dobrą drogę rozwoju produktu.
Dlaczego Twoim zdaniem Erlang nie odniósł komercyjnego sukcesu, takiego jak np. Node.js?
Myślę, że Node.js był skazany na sukces po tym, jak go odkryli programiści frontendu. Node to wrapper na libev, więc rozwiązuje ważny problem wydajności. Jest napisany w JS, więc cały stack mogą obsłużyć programiści jednej technologii. Nie tracimy czasu na context switching.
Erlang chyba nigdy nie miał tego przywileju posiadania dużej liczby programistów w tym samym czasie. Nawet po sukcesie Whatsappa (napisanego w całości w Erlangu), nie zbudowaliśmy masy krytycznej ekosystemu. Cała nadzieja w Eliksirze i innych językach napisanych na Erlang VM.
Myślisz, że gdybyś zainteresował się innym językiem, twoja kariera potoczyłaby się inaczej?
Na pewno. Gdy w połowie studiów związałem się z firmą konsultingową Erlanga, była to nauka na sterydach. Używanie Erlanga zmusza do poznania niskopoziomowego działania sieci czy systemu operacyjnego. Przez to, że Erlanga używa się tam, gdzie jest bardzo duży ruch, poznałem zupełnie inne systemy, niż gdybym pisał systemy webowe czy bazodanowe. To nie jest popularny rodzaj zastosowań.
Praca w Erlangu spowodowała, że dużo podróżowałem i osobiście widziałem, jak buduje się i zarządza firmami oraz startupami. One zderzyły się z początkową fazą wzrostu i pomagaliśmy im przetrwać. Myślę że właśnie Erlang spowodował, że zacząłem interesować się rozwojem produktów i powodami ich sukcesu czy porażki.
Gdzie znalazłeś pierwszą pracę i czego się w niej nauczyłeś?
Jak wspomniałem, zostałem przyjęty na praktyki letnie w największej firmie konsultingowej Erlanga, Erlang Solutions. Przez te parę miesięcy z kolegami budowaliśmy framework MVC w Erlangu. Już wtedy zdarzało się nam doświadczać rozwiązywania prawdziwych problemów z bardziej doświadczonymi członkami zespołu.
Dlaczego zmieniłeś miejsce zatrudnienia?
W ESL spędziłem kilka lat, ukończyłem studia na AGH w Krakowie i po kolejnym roku pracy postanowiłem, że czas na zmiany. Był to wtedy czas komunikatorów i nowych baz danych NoSQL. Pamiętam również nowy w tamtym okresie Paper Reading Club – każdego miesiąca powstawało tam coś nowego. To był na pewno formujący czas w moim życiu.
Przeniosłeś się do Doliny Krzemowej. Dlaczego?
Dolina Krzemowa to było miejsce, gdzie to wszystko się działo. Gdy dostałem propozycję pracy w startupie, który robił komunikator i chciał konkurować z największymi, od razu się zgodziłem. Miałem już doświadczenie ze współpracy z firmami z zachodniego wybrzeża, wiedziałem, że tam robi się produkty z rozmachem.
Polecasz wszystkim pracę w startupach? Masz ich kilka na koncie.
Mam ich kilka na koncie, ale paradoksalnie odpowiem: nie polecam. A na pewno nie na początku kariery. Praca w startupie jest zorientowana na produkt i na użytkownika, a nie na programistę. W wielu startupach robi się duże skróty w pisaniu systemów, żeby po prostu zdążyć.
Polecam pracę, która zapewni możliwość dobrego nauczenia się technologii i procesu tworzenia poprawnego systemu. Mówię tu o testowaniu, utrzymywaniu wersji, automatyzacji, pracy w grupie, czystym kodzie.
Trafiłem kiedyś na świetny argument za pracą w korporacjach na początku kariery. Nie dość, że tam te procesy są doszlifowane, to spędzamy tam kilka lat i awansujemy z dużą grupą znajomych. Po kilku latach mamy znajomości na poziomie menadżerskim i to bardzo dobra baza do odejścia do startupu lub założenia swojego biznesu.
Co z perspektywy czasu uważasz za najważniejsze doświadczenie w karierze?
Prawdopodobnie była to przeprowadzka do Doliny Krzemowej i uczestniczenie w szalonym wzroście komunikatora Tango. Gdy dołączyłem, mieliśmy nieco ponad milion użytkowników. Dość szybko było to 5, 10, 50… 100. Po czterech latach, gdy odchodziłem, na liczniku było 250M. Miałem jednak niesamowite szczęście do kolegów, którzy byli świetnymi specjalistami. Uczyłem się cały czas.
Pamiętam jak przez mgłę pierwsze miesiące, w czasie których spędzałem w biurze po kilkanaście godzin. Produkcja płonęła, musieliśmy pisać nowe feature’y, musieliśmy rekrutować i rozszerzać zespół. Pisaliśmy bardzo dużo automatyzacji; były to pierwsze lata, a nawet miesiące puppeta czy chefa. Nie było dockera!
Biznesowo, było to zaskoczenie realiami inwestycyjnymi Doliny Krzemowej. Gdy dołączyłem, Tango było zaraz po rundzie A wartej 10M USD, rok później 40M, następnie 45M, na koniec 200M… Wtedy zrozumienie możliwości, jakie dawała Dolina, wytłumaczyło mi w jakimś stopniu świat, który nas otacza.
Z kolejnymi latami poznawania sceny startupowej zobaczyłem też różnicę w fundingu na poziomie seed. Niestety, nawet po 10 latach fundusze w naszej części świata nie prezentują się najlepiej pod względem kapitału, ani też potencjalnej pomocy startupom.
Michał Zajda. Engineer, Architect, Team Lead w æternity blockchain. Programista, architekt, team lead, zespołów zbudowanych w jednych z najciekawszych projektów IT w Europie i Dolinie Krzemowej. Na co dzień działalność prowadzi z małym zespołem firmy Sennui, którą stworzył z myślą o consultingu technologicznym i R&D. Szczególnie interesuje się organizacją pracy zespołów i kontrolowaniem ryzyka w projektach. Obecnie uczestniczy w budowie blockchainu Aeternity, który jest całkowicie otwarty i zarysowuje nowe granice możliwości platform p2p. Historycznie zawsze zajmował się skalowalnością systemów rozproszonych w dziedzinach chatów internetowych, Internet of Things czy Real Time Bidding. Prywatnie pasjonat kawy i architektury.