Wprowadzenie nowej technologii do stacku projektowego – success story w zespole produktowym

Opublikowano

Byliście zespołem, który wdrożył Rusta w naszym produkcie. Opowiedzcie więcej o obszarze Piwik PRO Analytics Suite (PPAS), za który wówczas odpowiadaliście.

Adam Tulejko, Rust Developer/Tech Lead: Odpowiadaliśmy za starą, wywodzącą się z open-source’owego Piwika część PPAS stworzoną z użyciem PHP i MySQL. Kilka lat temu firma podjęła decyzję, żeby przepisać część analityczną platformy. Wraz z upływem czasu poszczególne części PPAS były reimplementowane przez inne zespoły. Kod, którym się opiekowaliśmy, został sprowadzony do roli trackera — części odpowiedzialnej za przyjmowanie danych z serwisów z podpiętą analityką.


Skąd pojawiła się potrzeba włączenia do stacku nowej technologii?

AT: Kod był mocno ‘legacy’, staraliśmy się go usprawniać w miarę możliwości, jednak stawało się to coraz trudniejsze. Zdawaliśmy sobie też sprawę, że stack technologiczny, na którym opiera się stary Piwik nie jest odpowiedni w sytuacji, gdy mieliśmy do obsłużenia coraz większy ruch. Wiele rzeczy działało wolno, często się psuło. Nie mieliśmy czasu na jego rozwijanie, bo ciągle rozwiązywaliśmy generowane przez niego problemy. Stawało się jasne, że prędzej czy później i ta część powinna zostać stworzona na nowo.

Bartek Nowak, Product Manager: Nasz produkt od początku kierowany był do wymagających klientów, często z bardzo dużym ruchem. Jego stara wersja, która była “podkręconą” wersją komercyjną rozwiązania open source w pewnym momencie stała się zbyt kosztowna w utrzymaniu, nie dawała też perspektywy na dalszy rozwój. 
Po zbudowaniu nowego silnika Analytics przyszedł czas na nowy moduł zasilający Piwik PRO w dane i procesujący je w lot. Z pomysłem na budowę przyszedł sam zespół, który jak nikt inny znał wszystkie problemy związane z utrzymaniem legacy. Poza zapewnieniem ciągłości biznesowej i dostarczeniem właściwego zestawu funkcjonalności, znanych z poprzedniej wersji, zespół mocno skupił się na niefunkcjonalnych wymaganiach związanych z wydajnością, skalowalnością, łatwością w utrzymaniu, czy bezpieczeństwem.

Czy już na tym etapie wiedzieliście, że technologie, w których dotychczas tworzyliśmy produkt, nie podołają temu wyzwaniu?

AT: Mając na co dzień do czynienia z problemem wydajności starego stacka technologicznego, uznaliśmy, że potrzebny jest nowy. Tandem PHP i MySQL zdecydowanie lepiej sprawdza się w przypadku workloadu transakcyjnego (jak e-commerce), natomiast zadaniem trackera jest przyjęcie jak największego ruchu. Transakcje nie są do tego potrzebne. Dodatkowo w tamtym okresie firma podjęła decyzję o migracji z PHP na Pythona. Zaczynanie nowego projektu w PHP nie miało więc sensu.

Jak przebiegał proces researchu?

AT: Niestandardowo :). Nie było odgórnej decyzji, że zastępujemy starego trackera nowym projektem. Skoro jednak spodziewaliśmy się, że to nastąpi, zaczęliśmy wieloosobowy pet project, którego celem było zaimplementowanie prostego trackera w różnych technologiach. Z różnych zespołów zgłosiły się osoby chętne to zaimplementowania go w Pythonie, Elixirze, Clojure. Ja sam od pół roku uczyłem się Rusta. Wraz z dwiema innymi osobami zaimplementowaliśmy tracker w tym języku. Zorganizowaliśmy benchmark zaimplementowanych trackerów: każdy w firmie mógł oglądać na żywo ich wyniki. Tracker w Ruscie okazał się najwydajniejszy. To zapoczątkowało drogę do decyzji o rozpoczęciu projektu nowego trackera i zaimplementowaniu go właśnie w tym języku.

BN: Czas pokazał, że był to świetny wybór. A my możemy się pochwalić tym, że obok takich gigantów jak Facebook, Google, czy Microsoft, Piwik PRO korzysta produkcyjnie z mocy Rusta. Obecnie jest to u nas druga technologia pod względem liczebności developerów, tuż za Pythonem.  

Co ostatecznie zadecydowało o wyborze Rusta?

AT: Zadecydowało wiele czynników. Mając już pewne doświadczenie zebrane podczas pet projectu wiedzieliśmy, że chcemy użyć właśnie tego języka. Nie tylko ze względu na szybkość i mniejsze zapotrzebowanie na zasoby, ale także dużą satysfakcję płynącą z pisania w nim. Po prostu jest to przyjemne, a system typów w tym języku bardzo sprzyja tworzeniu poprawnego kodu. Tak naprawdę jednak ostateczna decyzja nie była podejmowana przez nas. Do wprowadzenia nowego języka do stacka technologicznego firmy potrzebowaliśmy zgody managementu. Zgoda nie była czymś oczywistym. W 2019 roku Rust był uważany za język niszowy i niezbyt znany. Wdrożenie go wiązało się z wieloma ryzykami: co, jeśli nie stanie się popularny? Co z rekrutacją kolejnych developerów, skoro na rynku jest ich niewielu? Zaadresować te ryzyka oraz przekonać management pomógł nam nasz PM, Bartek. Uwierzył w nas i nasz odrobinę szalony pomysł. Do dzisiaj do końca nie wiem, jak to zrobił, ale w końcu dostaliśmy zielone światło.

 Jak wyglądały początki pracy z technologią, z którą wcześniej nie mieliście komercyjnego doświadczenia? Czym różni się nauka programowania początkującego developera od zgłębiania tajników nowej technologii przez doświadczone osoby?

AT: Doświadczenie zdobywaliśmy po prostu podczas pisania nowego trackera. Dodatkową trudnością było to, że nie wszyscy członkowie zespołu trackera uczestniczyli w pet projeckcie i uczyli się zatem Rusta od zera. Opracowaliśmy dla nich zestaw zadań, które oparte były o oficjalny podręcznik do Rusta. Dodatkowo serwisy, które implementowaliśmy na początku nie korzystały ze składni async/await, która nie była dostępna w stabilnym wydaniu Rusta. Nie było to łatwe, podejrzewam, że część chłopaków przeklinała pod nosem, ale z czasem było lepiej.
Początkujący developer nie ma przyzwyczajeń z poprzednich języków. W przypadku Rusta takie przyzwyczajenia u doświadczonych osób stanowią często problem. Rust nie jest językiem takim jak Python czy Go, w przypadku których wystarczy poznać, czym różni się ich składnia od tego, co już znamy, aby być choć trochę produktywnym. W Ruscie nie jesteśmy w stanie programować od ręki, starą wiedzę należy odsunąć na bok i zacząć od zrozumienia, jakie panują w nim zasady.

Czy pojawiły się problemy, których wcześniej nie przewidzieliście?

AT: Mieliśmy świadomość, że ekosystem Rusta nie jest zbyt dojrzały, ale w praktyce okazało się to większym problemem, niż sądziliśmy. Czasami brakowało crate’ów do integracji z zewnętrznymi technologiami, czasami mieliśmy szczęście, bo nadchodziły one dosłownie w momencie, gdy ich potrzebowaliśmy. Kod asynchroniczny bez async/await był momentami uciążliwy. Rozwiązywanie problemów z nim na etapie uczenia się samego języka potrafiło zajmować wiele godzin. Na szczęście obecnie ekosystem jest zdecydowanie bardziej rozwinięty, brak async/await to już też przeszłość.

Przemku, na jakim etapie Ty dołączyłeś do zespołu? Kod był już wtedy napisany w Ruscie czy dołączyłeś na samym początku prac? Jak wspominasz ten okres?

Przemek Kukulski, Backend Developer: Dołączyłem, kiedy dwa z czterech mikroserwisów składających się na tracker były w większości napisane i zespół zaczynał pracować nad trzecim, największym. Nie używałem wcześniej Rusta profesjonalnie, dlatego spora część bibliotek w projekcie była dla mnie nowością. Podobało mi się, jak wewnątrz zespołu dzieliliśmy się znaleziskami w przeróżnych API. Widać było, że zespół cały czas uczy się języka i wypracowuje swoje praktyki. Jedne po czasie odrzuciliśmy, inne zostały z nami do teraz.

Ile czasu minęło odkąd zaczęliście używać Rusta produkcyjnie?

AT: Trochę ponad dwa lata od rozpoczęcia projektu nowego trackera.

Jaki wpływ na inne moduły i pozostałe zespoły produktowe miało wprowadzenie nowej technologii?

PK: Na pewno wzbudziliśmy zainteresowanie w firmie. Od rozpoczęcia prac nad trackerem, dwie osoby przeniosły się do zespołów rustowych. Myślę też, że sam język zyskał w oczach wielu osób. Pokazaliśmy, że Rust to nie przejściowa moda, ale poważny język do pisania oprogramowania gotowego na produkcję.

Tracker w Ruscie jest już rzeczywistością, tymczasem Wy wzięliście pod swoje skrzydła moduł Customer Data Platform (CDP). Nadal jednak pozostaliście wierni Rustowi. Dlaczego?

PK:Nie było wątpliwości, że kluczowe komponenty CDP powinny być napisane w Ruscie. Serwisy napisane w tym języku zużywają najmniej zasobów w produkcie i bez problemu obsługują ruch sięgający kilku tysięcy zapytań na sekundę. Kwestią dyskusji był język, w którym mieliśmy napisać usługi do manipulacji (odczyt, tworzenie, edycja, usuwanie) prostych modeli w bazie relacyjnej. Wczesne wersje CDP używały do tego Pythona, ale ponieważ nie wszyscy w teamie byli w nim biegli, przepisaliśmy te serwisy na Rusta. Przekonaliśmy się, że utrzymanie rustowych serwisów od CRUDu nie jest problemem, a nawet pozwala współdzielić typy i logikę z pozostałymi serwisami.

AT: No właśnie, okazało się, że nasza produktywność w rozwijaniu dużego codebase’u w Ruscie nie odbiega od produktywności w PHP. Podobnie wypada to w porównaniu z Pythonem. Kompilator Rusta zapobiega wielu błędom, nie tylko formalnym, ale także, jeśli umiejętnie korzystamy z jego systemu typów, także domenowych. To pozwala zaoszczędzić sporo czasu. Ponadto mikroserwisy w Ruscie mają niskie zapotrzebowanie na CPU i RAM. Gdy pojedynczy rustowy serwis potrzebuje kilkadziesiąt megabajtów RAM, implementujący podobne funkcjonalności serwis w języku skryptowym zabiera nawet ponad jeden gigabajt. W związku z tym, że dostarczamy nasz produkt także na infrastruktury klientów, taka oszczędność ma znaczenie.

Od momentu, gdy do Piwik PRO dołączył Przemek jako pierwszy Rust Developer minęły trzy lata. W międzyczasie zdołaliście zrekrutować specjalistów i przekonwertować na Rusta kilka osób wewnątrz. Obecnie poszukujemy kolejnego Rust Developera. Czy Wasze oczekiwania i podejście do rekrutacji się zmieniło? 

BN: Od samego początku jednym z ważnych czynników, które wzięliśmy pod uwagę przy wprowadzeniu Rusta, było zadbanie o przestrzeń na rozwój w tej technologii. Zespół złożony był z senior devów PHP i ekipa ambitnie dążyła do uzyskania odpowiednio wysokiego poziomu także w Rust. Na początku postawiliśmy na rekrutację Senior Rust Developera, który mógłby nam w tym pomóc. To się jednak nie sprawdziło, dlatego Adam stworzył autorski program rozwoju dla całego zespołu. Zmieniliśmy też oczekiwania, szukając zawodników będących na przyzwoitym poziomie w innych językach, a chcących przejść na Rusta. To w połączeniu z programem wdrożeniowych nam zadziałało. Obecnie ze względu na potrzebę większej specjalizacji wróciliśmy do rekrutacji seniorów. Minęło trochę czasu i społeczność rustowa nieco urosła i dojrzała, dlatego jest łatwiej znaleźć bardziej wykwalifikowanych ludzi. 

Jakimi wnioskami z procesu wdrażania Rusta do produktu moglibyście z perspektywy czasu się podzielić?

PK: Na pewno Rust wymaga więcej uwagi przy konfiguracji środowisk developerskich, ale też CI. Kompilacja projektów rustowych od zera trwa długo, dlatego sporo uwagi trzeba poświęcić na optymalizację buildów (np. poprzez cache’owanie artefaktów).

AT: Myślę, że najważniejszym wnioskiem jest to, że po prostu warto wdrażać Rusta :). Co nas zaskoczyło na plus, to fakt, że nie mieliśmy problemów z brakiem kandydatów na Rust Developera. Pozytywny wizerunek tego języka sprawia, że zawsze jest zainteresowanie pracą w nim. Jeśli ktoś chce przekonać swojego managera do używania tego języka, warto zacząć od pet projectu lub drobnej funkcjonalności, którą można przetestować na produkcji i łatwo się z niej wycofać. Na pewno takie ryzyko jest łatwiejsze do zaakceptowania i kosztuje mniej stresu niż pełnoskalowy projekt, taki jak w naszym przypadku.