1) W ciągu ostatnich 4-5 lat eksperymentowałem z mnóstwem architektur aplikacji Solana i uznałem, że nadszedł czas, aby spisać moje odkrycia. Zaczynając od najmniej skomplikowanej i stopniowo dodając coraz więcej złożoności. Oto więc: Architektura aplikacji Solana, wątek.
2) Zacznijmy od trybu łatwego. To prawdopodobnie tak wygląda Twoja pierwsza aplikacja Solana. Prosty frontend w React, nawiązuje połączenie z RPC. Nie ma potrzeby posiadania serwera API. RPC jest Twoim serwerem. W początkowych dniach, były one zaśmiecone getAccountInfos, niestandardową logiką budowy transakcji itp. Później, gdy wydajność zaczyna cierpieć, dodajesz warstwy pamięci podręcznej i grupowania. Wchodzi getMultipleAccounts. Może dodasz również subskrypcje websocket + polling, aby na bieżąco aktualizować interfejs użytkownika. Ta architektura umożliwia niezwykle szybkie prototypowanie. Prawie nie ma devops. Znikome koszty serwera (po prostu wdrażaj na vercel itp). Ma jednak kilka poważnych wad.
3) Pierwszym problemem, na który natrafisz, są złożone zapytania. W tej architekturze masz tylko standardowe RPC Solana. Oznacza to, że musisz traktować Solanę tak, jak ją eksponuje RPC - jako bazę NoSQL z problemami z nastawieniem. Zapytania punktowe nie stanowią problemu. Możesz być nawet bardzo kreatywny z PDA, aby przeszukiwać dane programu, jakby to była baza danych grafowa. Ale jak tylko potrzebujesz wykonać swoje pierwsze gPA, czeka cię maksymalny ból. Interfejs wcale nie jest ergonomiczny. Jeśli masz jakiekolwiek dane o dynamicznej długości, nie mogą być w ogóle używane. W zależności od dostawcy RPC, może być niewiarygodnie wolny. Nawet bez gPA, to podejście zazwyczaj jest znacznie wolniejsze niż typowa aplikacja web2 z renderowaniem po stronie serwera i normalną bazą danych.
4) Drugim problemem, z którym się spotykasz, jest przenośność logiki budowy transakcji. Przy tym ustawieniu cała logika budowy transakcji znajduje się albo (a) w twoim kodzie frontendowym, albo (b) w bibliotekach, które twój kod importuje. W przypadku (a) każdy, kto chce budować transakcje poza twoim frontendem, napotyka ogromne trudności (dotyczy to również ciebie, gdy nieuchronnie będziesz potrzebować więcej aplikacji). W przypadku (b) wszelkie zmiany w logice budowy transakcji wymagają publikacji bibliotek, aktualizacji pakietów przez wszystkich, a następnie aktualizacji interfejsu użytkownika. Silne poleganie na narzędziach Anchor, takich jak rozwiązywanie kont, może zminimalizować ilość logiki, która musi być przenoszona -- ale problem pozostaje. To odbiera ci zwinność i utrudnia zmianę punktów końcowych inteligentnych kontraktów, zapewniając jednocześnie, że wszystkie wersje twojej logiki budowy TX nadal działają.
5) Trzecim problemem, na który natrafiasz, jest to, że interfejsy użytkownika zazwyczaj źle radzą sobie z przesyłaniem transakcji, szczególnie z logiką ponownego próbowania. Użytkownik może opuścić stronę, a TX przestaje ponownie próbować. Duże ilości transakcji mają tendencję do trudności w realizacji. Trudno jest zdalnie zdebugować, dlaczego rzeczy nie są realizowane.
6) Ostatecznym problemem jest to, że nie jesteś jedynym, który ma tę architekturę. RPC jest cenny, a w zasadzie musisz ujawnić swój adres URL RPC w swoim frontendzie. Teraz musisz brać udział w grze w kotka i myszkę, aby upewnić się, że nikt nie kradnie twojego RPC i nie podnosi twoich kosztów.
7) Co dalej? Zazwyczaj, nawet jeśli nie zajmujesz się przenośnością transakcji, kończysz na potrzebie obsługi zapytań listowych. gPA jest do niczego, i wszyscy to wiemy. Możesz więc zbudować architekturę hybrydową. W tej architekturze zachowujesz zdolność do szybkiego prototypowania, ale trudne, brzydkie zapytania przenosisz do API. Dobrym, konkretnym przykładem tego jest zarządzanie – masz propozycje, które są tworzone i mają zestaw tagów ("Ekonomiczne", "Techniczne" itd.). gPA nie potrafi filtrować według tagu.
8) Ta architektura nie rozwiązała problemu przenośności transakcji ani problemu z ludźmi, którzy wyciągają twój RPC. Ale na dużą skalę przynajmniej możesz rozwiązać problem wolnych/niemożliwych gPAs. Wprowadza to nowy problem -- indeksatory. Więcej na ten temat później.
9) W końcu masz to, co nazwałbym "przemysłowym" stosem Solana. Nie traktujesz już Solany jako bazy danych NoSQL. Zamiast tego traktujesz ją jak bus zdarzeń. Frontend nie wie nic o modelu danych Solany. Serwer konstruuje transakcje i przekazuje je do interfejsu użytkownika do podpisania, a następnie wysyła je do samej Solany. Traktuje to jako zdarzenie i czeka, aż rozpropaguje się z powrotem do indeksatorów, które zmienią podstawowe dane. Ta konfiguracja ma doskonałą przenośność transakcji - każdy może uderzyć w twoje API z czystymi parametrami i otrzymać z powrotem transakcje/instrukcje. Tworzy to niezwykle responsywny interfejs użytkownika - z perspektywy UI, to w zasadzie web2. Możesz w pełni wykorzystać SSR. RPC jest abstrahowane - nikt nie może ukraść twoich kredytów. Ale ta konfiguracja ma swoje problemy.
10) Pierwszym problemem, na który natkniesz się, jest ból związany z indeksowaniem. Chociaż w ciągu ostatnich kilku lat udało się to złagodzić (dzięki zespołom Triton, Helius i StreamingFast), wciąż regularnie biję nasz indeksator kluczem. Będziesz tracić wiadomości. Kiedy przegapisz wiadomość, twój interfejs użytkownika wchodzi w dziwny stan (przykład: wysłałem ci NFT, na łańcuchu je otrzymałeś, w mojej bazie danych nadal widnieje, że to ja je posiadam). Tego typu problemy są frustrujące do debugowania. Czy to twoja wina? Czy to wina twojego dostawcy danych? Kto wie! I tak mija twoje popołudnie.
11) Następnym problemem, z którym się spotkasz, jest czas. Kiedy bezpośrednio korzystasz z RPC do wszystkiego, pozwalają ci przekazywać zobowiązania i radzić sobie z najnowszymi danymi. Przy użyciu indeksatora wszystko to jest ręczne. Oznacza to, że podczas konstruowania transakcji możesz je konstruować na podstawie przestarzałych danych. Zwracasz transakcję, która jest skazana na niepowodzenie. Możesz rozwiązać problem przestarzałych danych, korzystając z dostawców danych, którzy oferują niezwykle szybkie dane (np. Helius laser stream). Ale wtedy musisz ręcznie radzić sobie z reorgami. Tzn. dane, które indeksujesz, muszą być wyindeksowane, jeśli ta transakcja faktycznie nie przeszła. To jest koszmar.
12) Możesz "oszukiwać" problemy z czasem, konstruując transakcje tylko na podstawie danych z RPC, a używając swoich zindeksowanych danych tylko do zasilania interfejsu użytkownika. Ale wtedy użytkownicy nadal będą mieli problemy z potencjalnymi niespójnościami między interfejsem a łańcuchem. Tzn. frontend mówi, że posiadam ten NFT i mogę go przenieść, a backend krzyczy na mnie i mówi, że nie mogę.
13) Ostatnim problemem, z którym się spotykasz w tej konfiguracji, są koszty, a jeśli mamy być melodramatyczni, to "śmierć decentralizacji." Marzeniem web3 było to, aby nie musieć wdrażać mnóstwa scentralizowanych serwerów. Teraz wdrożyłeś wystarczającą infrastrukturę, aby zdobyć pracę jako główny architekt w firmie web2. To kosztuje pieniądze. To kosztuje czas. I wszystko jest bardzo scentralizowane. Jak bardzo zdecentralizowany jest twój protokół, jeśli najlepszym sposobem interakcji z nim jest API web2? A jest około 72 deweloperów na Solanie, którzy wiedzieliby, jak z nim interagować bez tego API.
14) Ostatecznie nie zamierzam umierać na żadnych wzgórzach związanych z decentralizacją. To, co jest najlepsze dla użytkowników, zazwyczaj jest najlepszym wyborem. Ustawienie "enterprise" prowadzi do szybkich, nowoczesnych aplikacji internetowych i czystego podziału obowiązków. Z drugiej strony, zwiększa koszty devops i sprawia, że jesteś mniej zwinny. Zalecam, aby większość startupów zaczynała od metody direct-to-rpc, chyba że budujesz coś, co wyraźnie musi być szybkie lub mieć złożoną semantykę zapytań. Czas wprowadzenia na rynek jest kluczowy. Zawsze możesz później zatrudnić inżyniera na średnim poziomie i wrzucić go do lochu indeksowania.
15) Fin. Jeśli ktoś z was znalazł lepsze ustawienie, dajcie znać. To są wszystkie rzeczy, które próbowałem. Ostatnio całkiem dobrze się bawię, bawiąc się ustawieniami przedsiębiorstwa.
40,06K