#Microservices #API Gateway #Architecture #DevOps
Uber zaoszczędził 100 milionów dolarów na infrastrukturze w kwartale po zmianie podejścia do wersjonowania i wycięciu nieużywanych serwisów. Szymon podsumowuje temat kontraktów wprost: “To jest obszar, którego z reguły nikt nie chce dotykać, który bardzo mocno kopie i który jest znienawidzony przez większość użytkowników”.
Kontrakt z 130 polami, z czego 120 nullowalnych - to efekt latami stosowanego “nie wersjonujemy, tylko rozszerzamy”. Łukasz diagnozuje problem: “Ludzie patrzą na kontrakty jako na dodatkowy, niepotrzebny narzut”. Tymczasem Google stosuje “zamordyzm” - 3 miesiące na update, Facebook utrzymuje 8 wersji publicznie, a Microsoft eksperymentuje z wersjonowaniem przez daty zamiast numerów.
Komunikacja asynchroniczna vs synchroniczna, API Gateway z globalnym wersjonowaniem, breaking changes w topicach, poison message queue jako jedyny sposób wykrywania problemów. Prowadzący rozwiewają mity o autogenerowanych Swaggerach i tłumaczą, dlaczego kontrakty trzeba określać przed developmentem, nie po nim.
Czy mikroserwisy bez kontraktów to droga do katastrofy? I kiedy wersja 0.1 na produkcji jest akceptowalna?
Linki i ciekawe znaleziska
Transkrypcja
Szymon Warda: Cześć! Słuchacie Patoarchitektów. Prowadzą Szymon Warda…
Łukasz Kałużny: I Łukasz Kałużny. Wszystkie linki do tego odcinka znajdziecie na Patoarchitekci.io/30.
Szymon Warda: I oczywiście na Facebooku i Twitterze.
Łukasz Kałużny: Tak, witamy po dłuższej przerwie. W sumie ponad miesiąc od ostatniego nagrania.
Szymon Warda: Tak, ale już będzie teraz bardziej regularnie. Dobrze, Łukaszu, linki. Co wygrzebałeś?
Łukasz Kałużny: Bardzo fajny wpis od Google’a na temat w jaki sposób ustawić sobie SLO, czyli naszą podstawę do kontraktu i co mierzyć. I takim dla mnie plusem, pokazują to, ten proces krok po kroku w jaki sposób powinien wyglądać i są odniesienia, co mi się najbardziej podoba, do funkcjonalności biznesowych i do tych akcji biznesowych, które są. Więc oni tutaj nazywają to ładnie. Ta krytyczna ścieżka użytkownika razem z impaktem jaki ma i monitoring od tej strony. Potem oczywiście pokazują metryki, konfiguracje tych metryk od strony GCP, jak to zrobić, żeby sobie monitorować. Ale samym dużym plusem jest wytłumaczenie w jaki sposób się zestawia SLO SLI w praktyczny sposób, a nie tylko na sucho, że coś takiego jest.
Szymon Warda: To ja prowadząc moją krucjatę, żebyśmy nie używali skrótów, których nie tłumaczymy, to SLI - Service Level Indicator, SLO - Service Level Objective, czyli wewnętrzny cel zespołu. A SLA to jest to, co wystawiamy je w kontrakcie dla klienta, który klient podpisuje korzystając z naszej usługi oczywiście. Tak, zgodzę się, że faktycznie link jest fajny, ładnie opisany i pokazują to bardzo praktycznie, więc zgodziłbym się. Tak, warty chociażby rzucenia okiem.
Łukasz Kałużny: A u Ciebie co?
Szymon Warda: Ja, wpis dość ciekawy, trochę nawiązujący do tego co robiliśmy wcześniej. Mianowicie Twitter opublikował dość ciekawy wpis o metrykach, jak zbierają metryki. I żeby dać skalę tego, to Twitter zbiera pięć miliardów metryk na minutę, czyli to im tworzy około 1,5 petabajtów. Dużo. I gdyby to był sam taki wpis, gdzie się chwalą ile tego mają, to nie byłoby to bardzo interesujące, ale robią… Ten wpis jest o tyle ciekawy, że pokazują też schematy migracyjne, schematy między różnymi wersjami, jak zbierać w kontekście oczywiście bazy, którą teraz wypuszczają, właśnie bazy przeznaczonej głównie pod metryki, bo to jest baza time series. A bazy time series to jest, ich główne użycie to są właśnie metryki. Wpis dłuższy, ale naprawdę warty przeczytania, bo jeżeli ktokolwiek wejdzie do jakiejkolwiek metryki, za chwilę pojawi się problem migracji, zmiany schematów i właśnie problemy, które oni opisali, co z nimi sobie radzić? Na przykład między innymi to, czy dawać kolejkę do metryk. Tak że fajny wpis, też oczywiście trochę produktowy. Mimo wszystko warto.
Łukasz Kałużny: Tak, jedna dobra rzecz, jedna taka stamtąd cyfra, liczba od nich: kiedykolwiek zostaną przeczytane tylko 2% metryk na jakichkolwiek wykresach, innych rzeczach.
Szymon Warda: To jest bardzo realne. Z reguły metryki są przydatne tak naprawdę w takim post mortem albo w porównaniach tak naprawdę. Więc nigdy nie wiesz, kiedy Ci się przydadzą. Dobrze.
Łukasz Kałużny: Dobra, to ogólnie te liczby warto tam zobaczyć. To jest parę ciekawych rzeczy.
Szymon Warda: Przejdźmy do naszego tematu, bo temat jest kontynuacją naszej wielkiej myśli a propos, tfu, tfu, mikroserwisów.
Łukasz Kałużny: Tak, patologii.
Szymon Warda: Dokładnie. Co będzie dziś?
Łukasz Kałużny: Kontrakty i wersjonowanie, drogi Szymonie. Tak sobie ustawiliśmy.
Szymon Warda: I będzie ciekawie, bo to jest obszar, którego z reguły nikt nie chce dotykać, który bardzo mocno kopie i który jest znienawidzony przez większość użytkowników, bo: coś mi popsuli, albo jest nowa wersja, trzeba przepisać aplikację.
Łukasz Kałużny: Albo ja muszę być zgodny z tym, do czego się zobowiązałem.
Szymon Warda: Tak, dokładnie.
Łukasz Kałużny: Raczej czy wiesz co, to można nazwać nawet nie patologią mikroserwisów, tylko patologią usług.
Szymon Warda: Tak.
Łukasz Kałużny: Jak popatrzysz szerzej.
Szymon Warda: Tak, dokładnie. Bo jednak mamy takie dwie skrajności, że albo nie wersjonujemy albo wersjonujemy jak szaleni i trochę będziemy starali się to ułożyć. Ale to jak już zaczęliśmy porządkować, to wejdźmy sobie w nasze obszary analizy.
Łukasz Kałużny: Dobra, to jakie problemy, Szymonie?
Szymon Warda: Przede wszystkim musimy tutaj spojrzeć na to, że mamy różnice. Jak wyglądają różnice w komunikacji asynchronicznej i synchronicznej? Bo async jak zwykle jest trudniejszy, ale dalej będziemy radzili, żeby z asynca korzystać, bo to powoduje, że nasz cały serwis będzie bardziej rozproszony i będzie bardziej odporny na problemy.
Łukasz Kałużny: Tam, gdzie można.
Szymon Warda: Zgadzam się jak najbardziej.
Łukasz Kałużny: I ma to sens. Dobra. Następny.
Szymon Warda: Tak. Kolejna jest informacja w ogóle jak wygląda, który serwis z jakiego kontraktu korzysta tak naprawdę. Bo mamy, Swagger się już pojawił generalnie dla serwisów synchronicznych i to się stało już w sumie standardem, publikowanie kontraktów swagger’owych. Przy asyncu jest odrobinę trudniejsze tak naprawdę. Znowu, problem ostatni, który zdefiniowaliśmy, to jest z którą wersją serwisu rozmawiam tak naprawdę. Bo często widzimy takie zachowanie, że nie mamy, nie mamy numerku, wersji w URL-u albo w ogóle w nazwie endpointu i nie wiemy, z której wersji korzystamy. Tak.
Łukasz Kałużny: W zależności co tam sobie wybierzemy. Dobra, czyli to…
Szymon Warda: Czekaj, jeszcze wrócę do jednego, bo pytanie jest takie generalnie, poza tym, że z jaką wersją rozmawiamy, to jest pytanie jeszcze drugie, takie podrzędne, czy rozmawiamy z najnowszą? Bo to też przydałoby się wiedzieć. Wiadomo, że te najnowsze będą lepiej utrzymywane, będą bardziej rozwijane. Więc ogólnie problemy skupiają się wokół identyfikacji i rozszerzania się informacji w zespole i w systemie tak naprawdę.
Łukasz Kałużny: Dobra, to teraz nazwijmy to raczej w miarę i co będziemy przeglądać?
Szymon Warda: I to jest przede wszystkim generalnie tak, wchodzimy w to, że czemu w ogóle wersjonować tak naprawdę? Bo musimy mieć jakiś driver, żeby to w ogóle robić. Najprostszym driverem jest to, że to jest zarządzanie ryzykiem. Bo mamy, jeżeli mamy serwis, który nagle zmieniamy, to potencjalnie wchodzimy w regresję, nie mamy pewności, czy tam coś nie wybuchnie. A jeżeli stawiamy nowy serwis albo nowy endpoint obok, to w tym momencie to ryzyko przesuwamy albo nawet minimalizujemy. Czyli prosty myk, albo nie dotykamy i ten stary serwis żyje i dostawiamy cały czas nowe, albo go zmieniamy.
Łukasz Kałużny: Czyli cała kultura pracy wokół tego, to jest w sumie wszystko. Ten punkt odnośnie tego, jak chcemy zarządzać i jaką mieć kulturę w środku.
Szymon Warda: Tak, tu dodam generalnie, bo z tego co powiedziałem, to mogłoby wynikać od razu, że w takim razie to zawsze stawiamy nową wersję. Nie do końca, bo serwis, którego nie ruszaliśmy albo nie deploy’owaliśmy od jakiegoś czasu, im dłuższego, to nam się zaczyna tworzyć ryzyko, że my nie wiemy jak on działa, nikt go nie tykał i jest zagadką.
Łukasz Kałużny: To jest cała zabawa, którą tutaj można określić, to są te małe i duże zmiany, jak to określają, co z tym robimy.
Szymon Warda: Tak i cieszę się, że ruszyłeś do małych, dużych zmian. Bo takim drugim wymiarem jest to, że jak patrząc na to czysto z takiego punktu widzenia czasu time to market, to jak mamy małą zmianę, łatwiej jest dodawać te pola do istniejącego serwisu. Bo jedno pole, walidacja i lecimy. Tylko problem jest teraz taki, że te pola powinny być nullowalne cały czas i tak jest łatwiej. A tu nagle po kilku latach budzimy się z tym, że nasz kontrakt, naszego serwisu ma 130 pól, z czego 120 jest nullowalnych i walidowanych tylko logiką biznesową. Słabe.
Łukasz Kałużny: Dobra, a duża zmiana?
Szymon Warda: Natomiast jest taka opcja, że jak mamy dużą zmianę, to często taniej jest postawić serwis od nowa, a nie przepisywać stary serwis, a nie go mutować.
Łukasz Kałużny: Dobra, czyli jak w obu popatrzymy, to jest taki koszt time to market, raczej koszt dostarczenia versus koszt utrzymania, tak jak sobie na całość popatrzymy tych wymiarów.
Szymon Warda: Tak, dokładnie, bo teraz to mówiliśmy o takich kosztach krótkotrwałych, a te serwisy będą żyły na produkcji i nagle trzeba będzie je utrzymywać. Więc ten koszt wewnętrzny utrzymania, zachowania spójności i tak dalej, jak najbardziej nam wychodzi. Ten koszt w ogóle fajnie wyszedł przy Uberze, jak zaczął inaczej wersjonować, czyli ściął serwisy, które nie były używane, a oni nagle zaoszczędzili chyba koło 100 milionów na infrastrukturze w kwartale. Dużo.
Łukasz Kałużny: Tak, ale to unicorn, więc lećmy ten. Dobra, to lećmy sobie, przejdźmy sobie teraz może tak, podzielmy to synchroniczne, asynchroniczne, bo to są dwa, mimo że temat podobny, to są dwa światy, że tak powiem. Są dwa i różne techniki.
Szymon Warda: Które się przekładają, jak zobaczymy. Ale jednak async jak zwykle komplikuje dość wiele rzeczy. To jeżeli mówimy o synchronicznej, to jakie mamy rozwiązania? Trochę to jest to, o czym wspomnieliśmy tak naprawdę, czyli to, że tylko rozszerzamy kontrakty. Czyli, że jak nie trzeba, to nie dodajemy nowych endpointów, nie dodajemy wersji i wchodzimy w taki powolny, powolny marsz w kierunku nieutrzymywalności tego. Bo utrzymywalność systemu, w ogóle systemy powinny być jak najbardziej optymalizowane właśnie w kierunku łatwości utrzymania, bo większość czasu i większość nakładów finansowych w większości systemów idzie właśnie na jego utrzymanie, a wcale nie na development.
Łukasz Kałużny: Takiego bug fixing albo rozszerzenie. I to jest taka rzecz, jest to najbardziej wredna robota i potem kosztowna.
Szymon Warda: Tak, tym bardziej, że mało kto w swojej karierze chciałby mieć opis i zatrudnić się w firmie, gdzie tylko brownfield i my tylko utrzymujemy. Więc to też jest problematyczne w kontekście pozyskiwania ludzi. Znowu idziemy taką skrajnością, tutaj przesuwamy się trochę bardziej, to jest, że robimy takie, że nowe pole, to w tym momencie dodajemy nowy endpoint. I to zaczyna, to jest jak najbardziej logiczne i to też powinno być stosowane w ogóle w poprzedniej wersji. Tylko mamy pewien problem, że ta zasada, jeżeli ją aplikować na ślepo, każda zasada ma pewną taką komplikację, że na starcie życia serwisu nagle tych wersji będziemy z siebie wypluwali bardzo, bardzo dużo. Bo nie znamy domeny i ten development będzie dość dynamiczny. Potem ta usługa oczywiście się ustabilizuje i ona już będzie dużo łatwiej, mniej się zmieniała i będziemy mogli wersjonować nie codziennie.
Łukasz Kałużny: Wiesz, jak sobie popatrzymy na to, tak, to trochę gdzieś tam się sprowadza do tego, kto będzie korzystał z tej usługi? To jest taki cały problem utrzymywania tego kontraktu.
Szymon Warda: Tak i tu dotknąłeś właśnie bardzo fajnego tematu, mianowicie tego, że jeżeli na starcie najlepiej gdybyśmy mieli jednego konsumenta i z nim niejako doszlifowujemy, czego właściwie potrzebujemy. I wtedy możemy sobie spokojnie łamać nasz kontrakt. Ja bym zalecał i to jest taka… Mieliśmy o tym dyskusję przed nagrywaniem, żeby zaczynać od wersji zero. To samo co robią większość pakietów, prawie każdy…
Łukasz Kałużny: 01 tak naprawdę, pierwszy używany release to 01.
Szymon Warda: Tak, i to jest taki release, którym jawnie komunikujemy w wersji, że uwaga, to się będzie zmieniało. I tu możemy w pełni nie podpisywać się pod SemVera i tak dalej i tak dalej, że to po prostu może nie działać. I dla mnie to jest fajne, mimo że dziwnie wygląda.
Łukasz Kałużny: Raczej to jest, wiesz co, to jest trochę w ogóle dziwne… To ja widzę zawsze, że 01 nawet na produkcji, o tak, 01 na produkcji to jest w ogóle strach co to jest, przecież my to wydaliśmy, to jest 1.0.
Szymon Warda: Tak, ale w sumie generalnie doskonale wiemy, że jeżeli coś jest kiszone na developerce albo na teście i nikt tego nie korzysta na produkcji, to nie dowiemy się w ogóle jakie są tego potrzeby.
Łukasz Kałużny: Wiesz co, wracamy teraz do tematu, który chyba mieliśmy w ogóle na samym początku, Agile, że każdy sprint powinien coś wypuścić na produkcję.
Szymon Warda: Tak, generalnie kopniak na produkcję i lecimy tak naprawdę, o ile nie psujemy, to wywalamy tę produkcję.
Łukasz Kałużny: Czyli całość sobie tak, jeżeli sobie popatrzysz, to jest, dopóki możemy to utrzymywać, kontrakt, nowe pola, jeżeli nie zmieniamy logiki biznesowej… Jeżeli nie ma zmiany logiki biznesowej, to nie podbijamy wersji tak naprawdę, nie bawimy się. Dopóki nie potrzebujemy, to nie wersjonujemy.
Szymon Warda: Tak. Ja bym dodał taką uwagę, że żeby jakoś odciąć się od tego miliona cięć, żeby raz na jakiś czas robić taki clean up, czyli zacząć generalnie czy ok, czego potrzebujemy, że może ten kontrakt, który nagle nam obrósł w 130 pól, może to jakoś podzielić, a może coś z tym innego zrobić? Bo jeżeli mamy aż tyle pól nullowalnych, to to po prostu jest nieczytelne. Na koszt logiki biznesowej nagle staje się wręcz kolosalne w utrzymaniu.
Łukasz Kałużny: Tak, to cała zabawa, wypośrodkowanie pomiędzy breaking changes, które wprowadzamy i które chcemy obsłużyć versus te ciągłe IF-y i zmianę logiki biznesowej.
Szymon Warda: Tak, na pewno…
Łukasz Kałużny: Na pewno zmiana logiki biznesowej, jeżeli ma duży impact, to pewnie będzie to podbicie wersji.
Szymon Warda: Tak, to ja Łukasz, mam do Ciebie teraz takie pytanie, bo mówimy sobie o wewnętrznych, mówimy sobie o prostych rzeczach. A teraz mamy taką sytuację, mamy, jak to powiedzieliśmy nie raz generalnie, pierdolnik na backendzie, API Gateway na przedzie. To mamy sobie API Gateway i wystawiamy, nasz API Gateway wystawia serwisy, wiele serwisów jako jedno API. To teraz mamy dwie możliwości wersjonowania. Albo całe nasze API wersjonujemy w formie na przykład API.patoarchitekci.io/v1/odcinki. Albo wersjonujemy to, że generalnie każdy wewnętrzny serwis wersjonujemy bardziej jawnie. Czyli mamy odcinki/v1. Która wersja?
Łukasz Kałużny: Dla mnie jest bardzo prosta i najbardziej upierdliwa w developmencie, czyli API wersjonowanie globalne, jeżeli nazywamy to publicznym API. Nieważne czy to jest API wewnątrz, na zewnątrz organizacji, tylko że w dużej ilości przypadków, powiedzmy dla konsumenta, dla konsumenta ono będzie przyjemniejsze, jeżeli jest globalne, jeżeli API jest globalne.
Szymon Warda: Ja zaczynałem pisanie notatek do tego odcinka dokładnie odwrotnym zdaniu, ale stwierdzam, że tak, to jest ta słuszna droga, bo powinniśmy dostosować się bardziej do konsumenta. Ja dodam jedną rzecz, która tutaj ułatwi, że ja bym dla API publicznych zrobił release train. Bo ryzyko jakie jest takie, że podbijemy całość, to, że drobna zmiana w drobnym serwisie nagle podbija nam całe API i mamy taki spaghetti code przepięć, że w wersji naszego API na przykład 2.0 to ona korzysta z wersji 1.2 tego serwisu, 1.0 konkretnego i tak dalej. Mamy takie całe mapowanie. Więc ja bym po prostu robił takie, że sorry, podbijemy, zbieramy te wydania publiczne naszego API raz na jakiś czas i wydajemy tą zmianę… Inaczej, uwidaczniamy nasze API raz na jakiś czas, żeby to było w bulku, żeby też tych wersji nie było zbyt dużo tak naprawdę.
Łukasz Kałużny: Tak, to jest właśnie tam istotne, kto jest konsumentem tego, bo to jest zawsze… Jeżeli to jest, powiedzmy sobie wprost, jeżeli my odpowiadamy w naszym systemie za usługi, mamy wpływ w ramach jednostki organizacyjnej, czy to będzie zespół, czy grupa zespołów, które mają możliwość wspólnie zaplanowania, wprowadzenia jakiejś zmiany, innych rzeczy, to to wersjonowanie powiedzmy, że może być. Kontrakty muszą być zawsze i tego trzeba się trzymać.
Szymon Warda: Oczywiście.
Łukasz Kałużny: I publikowanie ich. Ale samo wersjonowanie, jeżeli robimy to w naszym pierdolniku, to nazwijmy, na który mamy jakikolwiek wpływ, to to wersjonowanie można sobie poluźnić.
Szymon Warda: Oczywiście, tak, łatwiej jest się dogadać niż być sztywnym. Większość problemów łatwiej rozwiązuje się międzyludzko niż technologicznie.
Łukasz Kałużny: Tak, to jest jedno. I teraz trzeba pamiętać, wchodząc teraz na obszar troszeczkę kultury i problemów wokół tego, jeżeli chcemy zachęcić ludzi do korzystania, do reużywalności, o tak, bo to jest modne pojęcie, żeby reużywać jakieś serwisy i inne rzeczy, to tutaj niestety trzeba im zapewnić to, że jakoś szybko nie zgasimy czy nie wprowadzimy breaking changes przy tym, jak skorzystają z naszej usługi.
Szymon Warda: Tak, to się zgadza i trochę już dotykasz problemu generalnie szybkości. Dotykasz tego, żeby dowiedzieć się jak, kto czego używa. Ale o tym jeszcze będziemy mówili. Bo teraz przechodzimy do drugiej części, mianowicie do części komunikacji asynchronicznej, która jest trochę bardziej upierdliwa i trochę trudniejsza oczywiście, jak to z nią bywa. I wchodzimy…
Łukasz Kałużny: Co będzie pierwsze? Bo kontrakt, on jest dość specyficzną rzeczą tak na prawdę przy asynchroniczności.
Szymon Warda: Tak i tu wchodzimy na podstawowy podział, bo wchodzimy w kto jest właścicielem kontraktu i przez to jakie wiadomości mamy. Bo jeżeli mówimy o zwykłym comnand’zie, czyli Ty mi zrób, to właścicielem w tym momencie staje się ten serwis odbierający, to my się zachowujemy jako nadawca. Więc tu wchodzimy we wszystkie wzorce komunikacji synchronicznej i tu się niewiele zmienia.
Łukasz Kałużny: Asynchronicznej.
Szymon Warda: Synchronicznej, to mówiliśmy…
Łukasz Kałużny: Przepraszam, tak, przy command’zie masz, porównujemy to do synchronicznej.
Szymon Warda: Tak, dokładnie. Czyli mamy endpointy, to bardzo niewiele się od siebie różni. Dużo ciekawiej jest przy topicach. Bo przy topicach oczywiście właścicielem tego staje się nadawca, a my tylko nasłuchujemy i może coś do nas trafi. I wchodzimy teraz, właśnie to, o czym powiedziałeś, w kontekście braku informacji. Bo skąd odbierający ma wiedzieć, że jest nowa wersja? On się tego nie dowie. Więc monitorowanie na, o ile, jak mówiliśmy o narzędziach do monitorowania i narzędziach do sprawdzania, to one pokazują, świetnie monitorują synchroniczną, asynchroniczną dużo gorzej. I wchodzimy…
Łukasz Kałużny: Wiesz co, zostaje tak naprawdę nam poison message i alerty z tego, że coś się zadziało.
Szymon Warda: Tak, dokładnie, co jest absolutnym must have, jeżeli mówimy o komunikacji asynchronicznej, to że poison message que musimy monitorować. Bez tego po prostu nie da rady. Ale teraz wchodzimy w pytanie podstawowe, w takim razie skoro mamy wersjonowanie kontraktów do topiców, to gdzie powinna być informacja o numerze wersji? Czy powinna to być nowy typ? Czy powinniśmy w metadanych umieszczać nową wersję? I jak do tego Łukaszu podchodzisz?
Łukasz Kałużny: Czy wiesz co, to teraz odpowiem po konsultancku i doradczo. To bardzo zależy. To znaczy jeżeli sobie popatrzysz, to w niektórych przypadkach sprawdza… Wszystko zależy kto i jak się do tego podłącza. Znowu to będzie ta zależność, kto i jak się do tego podłącza. Bo zobacz, że w niektórych przypadkach nie masz dostępu… Na przykład znam przypadki, gdzie eventy na przykład trafiają na HDFS-a, do analityki. To jest jeden z takich przypadków, gdzie wtedy wersja kontraktów w wiadomości jest bardzo spoko, bo jest sobie robiona na boku. Jak pracujemy na żywo, to tak naprawdę jak mamy topic, to mamy możliwość zapięcia się po query na konkretną wersję.
Szymon Warda: Niektóre [niesłyszalne 00:20:47], faktycznie, tak.
Łukasz Kałużny: Tak, tak, tam gdzie mamy smart brokery możemy zapiąć się na konkretną, typu RabbitMQ, Service Bus, możemy się Pub/Sub Google’owy, możemy się tam zapiąć po prostu na metadane na topicu, na query po metadanych…
Szymon Warda: Przy czym dodajmy, że to jest obsługiwane przez filtrowanie i o ile ta opcja jest, to często ona nie jest zalecana, bo ona faktycznie wymaga skanowania kolejki.
Łukasz Kałużny: Tak, to w zależności jak jest zaimplementowany ten silnik pod spodem naszej kolejki versus tak naprawdę nowy kontrakt, nowy topic.
Szymon Warda: Tak, bo tu wchodzimy w takie największe ryzyko jakie jest, to jest to, że nagle wydamy nowy kontrakt i nagle jest takie ryzyko, że serwis dostanie dwa razy tą samą wiadomość, tylko w innych kontraktach. O ile oczywiście mówimy, że wszystkie wiadomości mają być impotentne i serwis powinien sobie z tym poradzić, to jest to zwiększanie ryzyka tak naprawdę, że dorzucamy mu trochę roboty. Tak to wyglądało i z tego, ja bym idąc tą myślą, ja bym jednak skierował się w kierunku tego, żeby jednak wersjonowanie było na poziomie typu topicu, żeby serwis jawnie subskrybował się na konkretną wersję naszego topiku publikowaną.
Łukasz Kałużny: I tu wchodzimy w pierdolnik zarządzania potem kolejkami i tego jak to istnieje.
Szymon Warda: Ależ oczywiście, nikt nie powiedział, że będzie łatwo. A to teraz wchodzimy w pytanie kolejne: czy w takim razie, jeżeli wersjonujemy na poziomie jednego albo drugiego, to jest obojętne, to czy nadawca powinien wysyłać wiadomości w starych i w nowej wersji? Jak do tego podchodzisz?
Łukasz Kałużny: Wiesz co, powiem Ci tak, nie wierzę, że ktoś zaimplementuje to poprawnie i impotentnie.
Szymon Warda: To się zgadza.
Łukasz Kałużny: Na dłuższą skalę jest problem utrzymania. Wiesz, teraz jest to co powiedziałem, to tak jak kontrakt kontroluje odbierający, czyli zaczynając od commanda. To wymaga, jeżeli masz asynchroniczność, wymaga większej współpracy, że tak powiem, bo zazwyczaj wzorzec asynchroniczny, już kiedy masz kolejkę i inne takie rzeczy tak realnie, on jest robiony, nazwijmy to, jest robiony… Komunikacja poprzez kolejki jest raczej robiona wewnątrz. Bo jeżeli mówimy o asynchroniczności z perspektywy publicznej API, może sobie też to powiedzmy wprost, ona raczej jest robiona przez synchroniczny jakiś API Gateway, który ewentualnie potrafi wrzucić na kolejkę i zwrócić 204 plus jakiś ID…
Szymon Warda: I zwraca [niesłyszalne 00:23:28].
Łukasz Kałużny: Tak, tak, niż wystawiamy tak naprawdę, niż wystawiamy jawnie gdzieś naszą kolejkę. Więc to też jest rzecz, gdzie dogadujemy się raczej wewnątrz organizacji, niż wystawiamy to publicznie.
Szymon Warda: Zgadza się. Z reguły właśnie to przez webówki jest symulowane, przez jakieś subskrypcje i przez callbacki, bo faktycznie wystawianie kolejki publicznie jest bardzo ryzykowne i ja bym też tak nie robił.
Łukasz Kałużny: Tak, więc zawsze ją pakujemy. Więc jak sobie popatrzymy wewnątrz, to jest problem, że jeżeli mamy, znowu pójdziemy do problemu identyfikacji, bo musimy, jeżeli robimy nowa wersja kontraktu, nowa kolejka, nowy topic, nowa kolejka, to musimy poinformować ludzi, że od teraz… Przy odbieraniu jest to proste, bo można zostawić dwie wersje serwisu, tak przy odbieraniu jest to bardziej problematyczne dla odbiorcy jeżeli nasz serwis produkuje eventy, które informują o czymś, bo trzeba tak naprawdę zapewnić przepięcie, a potem wygaszenie starej kolejki.
Szymon Warda: Tak, bo pamiętajmy, właśnie dotknąłeś ważnego tematu, że te rzeczy trzeba wygaszać, tak samo jak trzeba wygaszać stare wersje synchronicznej, to tak samo przy asynchronicznej i przy commandach i przy topicach musimy to wygaszać, bo nie oszukujmy się, publikowanie tej wiadomości będzie obciążeniem naszego brokera.
Łukasz Kałużny: I teraz jest właśnie pytanie… Inaczej, to jest takie pytanie z serii kura czy jajko: kiedy to wygaszać i na jakiej zasadzie wygaszać? Jak szybko? W jaki sposób informować, że: hej, jest nowa wersja kontraktu i macie teraz pół roku na przykład od teraz czy kwartał od teraz na odpięcie się od tego.
Szymon Warda: Mówiąc “macie”, to zakładasz generalnie, że każdy system ma aktywny zespół developerów, który go utrzymuje. A często jest tak, że go nie ma.
Łukasz Kałużny: Właśnie, to zależy, o tak, to zależy czy jest to in-house, czy outsourcowany development. To jest zawsze tego problem.
Szymon Warda: Dobrze, więc jest trudno. To sobie rzućmy okiem, jak robią to inni, giganci i nie tylko giganci. W Google’u. Google ma zamordyzm po prostu. Takie to może brzydkie słowo, ale tak to po prostu wygląda.
Łukasz Kałużny: Ale zarządzają poprzez zamordyzm, co jest skuteczne.
Szymon Warda: Skuteczne i tanie, ja bym powiedział, że na to. I tam jest po prostu ma się 3 miesiące na update. Czyli utrzymują dwie wersje swojego serwisu, z reguły, mówimy o wewnętrznych rzeczach tak naprawdę. Chociaż Google też umie ubijać publiczne rzeczy, więc różnie z tym bywa. Facebook, tu jest już trochę inaczej, bo na produkcji są dwie wersje równolegle, bo to jest taka fala deployment’u. Jak się jedna kończy, to już druga się zaczyna. Ale…
Łukasz Kałużny: Oni się chwalą dwoma wersjami. Ale właśnie, powiedz ile jest na zewnątrz teraz.
Szymon Warda: Jest 8, jak sprawdzałeś generalnie. I to jest pokazanie, że faktycznie… To ja pamiętam jak na starcie, jak Facebook swoje API wystawiał, to oni popełnili karygodny błąd, że pierwsza wersja API była bez numerku wersji i tam było dużo breaking changes nagle, jak oni zmienili. Więc teraz wzięli się w karby i wystawiają osiem wersji wstecz. To jest dużo.
Łukasz Kałużny: Raczej jest pytanie ile na co się mapuje, bo teraz ta wersja jest też podyktowana zazwyczaj dużymi breaking changes, czyli gdzieś wygaszenie, zmiana, zmiany w logice, o tak.
Szymon Warda: Tak, bo pamiętajmy o tym, że właśnie wersjonowanie powinniśmy robić tylko w sytuacji breaking change albo takiej koniecznej, albo takiej, którą chcemy zrobić, czyli posprzątać. I dochodzimy do Ubera, który słynął z tego generalnie, że Uber nie robił przepisywania serwisów, refaktorów, tylko pisali serwisy na nowo.
Łukasz Kałużny: Copy, paste i lecimy.
Szymon Warda: Nawet czasami w ogóle bez copy paste. I oni tak żyli. I koszty utrzymania tych mikroserwisów, tych tysięcy repo nagle były ogromne. Bo jak doskonale wiemy Uber dość sporo kasy na infrastrukturę wydawał. Był chyba albo największym, albo jednym z większych konsumentów AWS, więc działo się. Natomiast…
Łukasz Kałużny: Teraz do Indii przenoszą development. Była gdzieś informacja, że będą do Indii przenosili, taka ciekawostka.
Szymon Warda: A to ciekawe, bo na przykład swój serwis w Indiach sprzedali. Nie operują już tam niczego. Wiadomo, stają się korporacją powoli i tną koszty.
Łukasz Kałużny: Dobra, a wejdźmy teraz zejdźmy na ziemię, Szymonie. Jak jest u Ciebie, przy twoich doświadczeniach? Zejdźmy na rynek pi razy drzwi lokalny, europejski.
Szymon Warda: Korporacji, powiedzmy sobie. I to jest ciekawe, bo faktycznie oryginalnie u nas to się działo w firmie, w której pomagam, to jest to, że właśnie to było rozszerzanie tego API i był monolit i ten kontrakt rósł, rósł i rósł. I on się staje coraz większym problemem tak naprawdę. Jeden, że po prostu jest zbyt duży i zbyt dużo pól jest nllowalnych, co obniża czytelność dla klientów. I nagle okazuje się, że czemu to jest problemem, to obniżenie czytelności dla klientów? Bo jak klienci chcą wykorzystywać i nagle mają dziwne błędy, to piszą do nas. Jak piszą do nas, to się przekłada na czas developmentu, gdzie my musimy to wyjaśniać, debugować, sprawdzać i tak dalej. I przekłada się niestety też dość wrednie w różne kombinacje tych parametrów. Bo jak dodajemy nowy parametr do naszego API, to pytanie pozostaje: jak on wpływa na pozostałe parametry? A wpływa dość wrednie, bo tworzy się macierz zależności tak naprawdę. Więc mnożymy te wszystkie rzeczy. Więc co się dzieje? Serwisy są odcinane i wystawiamy je spójnie na Gatewayu. Ale obecnie wchodzi potrzeba, żeby jednak te kontrakty posprzątać po prostu i stworzyć nową wersję. Ale na przykład klienci bardzo, szczególnie klienci bankowi, boją się nowych wersji i też niechętnie się na nie przepinają. Więc podsumowując it’s complicated bym powiedział.
Łukasz Kałużny: Raczej czy wiesz co, ja tam uczestniczę w różnych ciekawych dyskusjach na ten temat na rynku u różnych klientów. Problem jest taki, że w większości miejsc ten kontrakt nazwijmy ostatnio wygląda jak, zazwyczaj jest to autogenerowany jakiś swagger.
Szymon Warda: Tak.
Łukasz Kałużny: Zazwyczaj i się nikt tym nie przejmuje, że tak powiem, zazwyczaj. Jest problem, że ludzie patrzą inaczej na kontrakty. To dla mnie taka smutna rzeczywistość. Ludzie na kontrakty patrzą jako dodatkowy, niepotrzebny narzut.
Szymon Warda: Tak, często bardzo.
Łukasz Kałużny: W szczególności, powiedzmy, że dobrą praktyką powinno być tak naprawdę wpierw określenie kontraktu, a dopiero potem development. W zależności jak… Oczywiście ja wiem, że to jest już bardzo mocny zamordyzm.
Szymon Warda: I to jest problem kury i jajka, bo określając kontrakt znasz już domenę? No nie znasz za bardzo, ale znowu pisząc na pałę. Dla mnie ta wersja 0.x.
Łukasz Kałużny: Tak, tak, 0.x. Tylko, że jest pewien moment, kiedy już, jak weźmiesz się za refaktoring czy za coś, to już powinieneś to robić na bazie istniejącego na przykład kontraktu, testów integracyjnych, etc. Wiesz do czego dążę tak naprawdę, że…
Szymon Warda: Tak.
Łukasz Kałużny: Jest to gdzieś tam problem. Tak, jest ta wersja rozwojowa, ale w pewnym momencie powinieneś już zacząć pisać na bazie kontraktu ten kod, bo to jest ostatnia rzecz, implementacja logiki, że tak powiem, to powinna być taki creme de la creme, którego wszyscy nie lubią.
Szymon Warda: Tak, ale to przeszliśmy właściwie bardzo płynnie do opinii tips and tricksów. Jedno to właśnie jest, żeby ten kontrakt jednak nie był zawsze autogenerowany, a jeżeli jest, to żeby zadbać o niego. Ja bym dodał inną rzecz, że jeżeli wystawiamy endpoint, od razu wystawiajmy go z wersją, żebyśmy nie mieli endpointów bez wersji.
Łukasz Kałużny: Tak, to jest bardzo dobry protip. Czyli zaczynamy od 0.1 bądź 1.0 albo jakie wersjonowanie przyjmiemy. Jak jesteśmy przy wersjonowaniu, ten MS-owy pomysł w ich API, które są gdzieś tam wokół cloudu, czyli data zamiast wersji. On jest dziwny, ale ciekawy.
Szymon Warda: Ja pamiętam jak pierwszy raz go zobaczyłem, to było na zasadzie: ale o co chodzi? Tak się nie robi. Ale to naprawdę ma sens.
Łukasz Kałużny: Na przykład inaczej, jest łatwiejszy niż 0.1.
Szymon Warda: Zdecydowanie łatwiejszy.
Łukasz Kałużny: Tak, tak, dla ludzi mentalnie, bo zobaczą datę, jest ok.
Szymon Warda: I wiemy generalnie jak stare jest to API. Problem pojawia się, że MS też wystawia API, przyszłe wersje też wystawia w formie daty, to za chwilę powiesz, one mają tam -beta, zgadzam się, ale to jest takie, że czasami…
Łukasz Kałużny: Preview.
Szymon Warda: Albo tak, racja, preview. Czasami tego preview się użyje mimo wszystko. I potem nagle jak się zmieni to jest: o żesz kurcze.
Łukasz Kałużny: Tak, tylko, że na koniec dnia oni, potem preview po prostu, jak wychodzi GA, to oni stabilizują te preview. I preview po prostu jest przemapowane na GA-a, kiedy już GA-owa jest wersja wydana. Więc to jest u nich akurat dobre, że oni po prostu, nazwijmy to, kasują z nazwy preview, a reszta zachowuje się tak samo jak jest ustabilizowane. To jest dobra rzecz. No i teraz co? Zamordyzm niestety, to jest, oboje się tutaj zgadzamy.
Szymon Warda: Tak.
Łukasz Kałużny: Że przy kontraktach.
Szymon Warda: I to jest to, że lepiej nie mieć problemu z wersjami. Po prostu lepiej go unikać. I słowo zamordyzm jest bardzo brutalnym słowem. Ale tu bardziej właśnie o to chodzi, że dogadanie się z ludźmi i posiadanie twardego stanowiska w kontekście za ile wygaszamy wersję API i tak dalej, bo sorry, ale musimy minimalizować cost of ownership serwisów, bo inaczej po prostu będą nam pieniądze uciekały przez palce.
Łukasz Kałużny: I trzeba pamiętać, że mamy, to jest takie, będzie dla mnie najważniejsze, trzeba rozróżnić kontrakty i wersjonowanie, że są dwa światy. Czyli kontrakt i wersjonowanie w ramach mojego systemu, tam, gdzie mamy wpływ na otoczenie versus zewnętrzny konsument z punktu widzenia naszej jednostki organizacyjnej, naszego systemu, który jest zewnętrzny. Bo możemy mieć klienta, który jest dla firmy w ogóle zewnętrznym userem, na przykład B2B czy B2C, gdzie jest w ogóle zupełne API, tak jak tam wrzuciliśmy sobie Facebooka czy Google’a w niektórych miejscach versus drugi zespół, który korzysta z innego projektu, chce reużyć naszych rzeczy.
Szymon Warda: Jasne. Ja bym jeszcze dodał jedną rzecz w kontekście asynchronicznej komunikacji, bo często jest tak, że chcąc mieć zero downtime wprowadzamy kontrakty, a dobrze robiąc deployment taki trochę z odrobinką zamordyzmu możemy doprowadzić do tego, że nie będziemy mieli takiej sytuacji, że będziemy potrzebowali kontraktów. Jeżeli na przykład wpierw wygasimy publikującego, wygasimy publikującego, potem przepniemy odpowiednio konsumentów, to może być sytuacja, że będziemy mieli ładne, nawet z breaking changes nie będziemy potrzebowali nowej wersji kontraktów.
Łukasz Kałużny: Dobra, jedna taka opinia, bo to nie padło, to też bardzo podkreślić, wersjonowanie vs bazy danych. To jest zupełnie oddzielny temat. Model danych versus wersjonowanie, którego nie poruszyliśmy.
Szymon Warda: I specjalnie, bo mieliśmy o tym dyskusję, czy to poruszać, ale nie, bo to jest otworzenie puszki Pandory. O wersjonowaniu baz danych sobie powiemy jak najbardziej jak to robić, bo to też jest ciekawy temat, ale na razie kontrakty i łączenie tych dwóch rzeczy ze sobą nie zawsze jest słuszne, bym powiedział. Nawet często jest błędem, po prostu z definicji, logicznym.
Łukasz Kałużny: Dobra. Jest to i co jeszcze z usług zewnętrznych? Tak naprawdę o wersjonowaniu globalnie powiedzieliśmy i to trzeba przypomnieć, że niestety wersjonowanie patrzymy z perspektywy odbiorcy, a nam zostaje kompozycja na backendzie.
Szymon Warda: Dokładnie tak.
Łukasz Kałużny: Tak.
Szymon Warda: I wchodzimy w to, żeby minimalizować, wchodzimy w bardzo fajny wzorzec, o którym mówiliśmy właśnie, backend for frontends, czyli wystawianie osobnych Gatewayi, często osobnych API dla konkretnych urządzeń na przykład mobilnych i dla innych konsumentów. To działa i to minimalizuje naszą konieczność podbijania tego numerka wersji dla całego API.
Łukasz Kałużny: Trzeba po prostu popatrzeć, czy jest to usługa mikroserwis, usługa względem, które konsumuje jakiś frontend, czy jednak konsumuje, produkuje rzeczy względem tylko backendu. To jest takie ważne rozróżnienie.
Szymon Warda: Tak. Dobrze, chyba podsumowujemy powoli ten odcinek. Łukaszu, od Ciebie.
Łukasz Kałużny: To pierwsze, to będzie tylko znowu z opinii, tak, zamordyzm może spowalniać, ale się sprawdza. Zdrowy zamordyzm.
Szymon Warda: Zdrowy jak najbardziej. To ode mnie oczywiście napomknę o moim ulubionym temacie, czyli Service Mesh’e. Bo jeżeli chodzi o komunikację wewnętrzną to Service Mesh’e zostały stworzone właśnie do tego, właśnie do operowania na wersjach. I o ile często Ty wspominasz o tym, ja się z Tobą zgadzam, że masę rzeczy, które możemy zrobić w Service Mesh’ach są rozwiązaniami tymczasowymi i powinny być przemigrowane do kodu właściwego. To przepinanie, rootowanie, perwersje, ograniczenie wersji, to idealnie powinno być w Service Mesh’ach. One po prostu robią świetnie.
Łukasz Kałużny: To robią, jeżeli mówimy, w szczególności mówisz, że chcesz dostawić nową wersję. Czyli tak naprawdę nowa wersja API, to jest nowa wersja serwisu. To wtedy w ogóle sprawdzają się genialnie przy takich smart routing’ach.
Szymon Warda: Tak.
Łukasz Kałużny: Ale tylko do synchronicznych, to jest ważne. To jest taki silver bullet do, częściowy silver bullet do tych problemów synchronicznych.
Szymon Warda: Tak, chociaż tam są próby stworzenia meshy pod asynchroniczne, ale tam tych prób było już kilka, więc jestem ciekawy co z tego będzie.
Łukasz Kałużny: Dapr sobie idzie, ale to też jest inna perspektywa, bo to jest narzut na pisanie mikroserwisów, a nie tylko asynchroniczne, więc zobaczymy. Tak naprawdę przy asynchronicznej, to co możesz powiedzieć znowu? Tak samo utrzymywanie tych kontraktów i znalezienie u siebie złotego środka.
Szymon Warda: Zgadza się. I dla mnie w ogóle, jeżeli mówimy o wersjonowaniu, to krytyczne jest to, sorry, musimy mieć jakiś system do APM-u, czyli Application Performance Monitoring i musimy mieć application mapę. Mesh’e to dają. Jak nie mamy mesh’a, to generalnie wchodzimy w Application Insights, dowolny dobry system do trackowania, monitorowania pokażę na mapie kto z czego korzysta. Bez mapy korzystania nie będziemy wiedzieli czy możemy wygasić po prostu.
Łukasz Kałużny: Dobrze. I teraz właśnie to, co powiedziałeś, czyli metryki. Jak kto z czego korzysta, API, żeby wiedzieć, w szczególności wewnątrz, żeby skontaktować się z odbiorcą. Na zewnątrz, czy jest wykorzystywane, czy wygaszać, jak podjąć decyzję, że tak powiem, z perspektywy zewnętrznej. Wewnętrznie powinno być trochę prościej. Bywa to różnie. Przy tych APM-ach bym dorzucił, jeżeli robisz nadal lokalnie, w lokalnej infrastrukturze, to będzie drogo, o tak. Jeżeli chcesz mieć koniecznie tylko w lokalnej i nie możesz tych eventów wysłać na przykład do któregoś z cloudów, to lokalnie są to duże koszty.
Szymon Warda: Zgadza się, ale dla mnie to są koszty, które pozwalają nam monitorować koszty. Bo to jeżeli idziemy do managementu, robimy decyzje strategiczne, to musimy powiedzieć, że ok, na przykład wygaszenie tej wersji serwisu kosztuje nas tyle dolarów utrzymania miesięcznego, a tyle daje przychodu, bo…
Łukasz Kałużny: Ja bym nazwał to bardziej tak, API akurat będę nazywał poziomem taktycznym bardziej niż strategicznym, w zależności czy to jest zewnętrzne, czy wewnętrzne, o, znowu to jest to rozróżnienie. To jest chyba taka ważna miara, będzie.
Szymon Warda: Tak i dla mnie to jest to generalnie, kiedy wersjonować i zaczynać. Zamordyzm, powiedziałeś, jak najbardziej tak.
Łukasz Kałużny: Bardziej.
Szymon Warda: Wchodzimy w taką czasami sytuację, że nam się cykle wydawnicze rozjadą i musimy wydać wersję, bo jakieś tam rzeczy naprawiamy, a przy okazji wydajemy nową wersję serwisu, bo mamy nowe API. I w tym momencie ja bym zaczynał już wersjonowanie, bo…
Łukasz Kałużny: Tak.
Szymon Warda: Od tego nie uciekniemy.
Łukasz Kałużny: Czyli inaczej, wewnętrznie, powiedzmy sobie, dopóki możemy, nie wersjonujemy.
Szymon Warda: Tak, dokładnie.
Łukasz Kałużny: Ale coś w endpoint’cie mamy, żeby to rozróżnić, zostawiamy sobie furtkę na to od początku.
Szymon Warda: W razie czego generalnie wystawimy.
Łukasz Kałużny: Tak, tak, tak może być to nawet stare, znienawidzone v1.
Szymon Warda: Dokładnie. Dobrze, to w sumie chyba tyle. Kończymy.
Łukasz Kałużny: Tyle, na razie.
Szymon Warda: Dzięki.
Wypełnij poniższy formularz, aby być na bieżąco ze wszystkimi
odcinkami Patoarchitektów
i uzyskać dostęp do dodatkowych
materiałów.