Czym jest programowanie reaktywne?

Nie programujemy dla samego programowania. To oczywiste. Zawsze na końcu tego procesu jest użytkownik wytworu naszej pracy. Możemy być z siebie dumni, rozpływać się w “achach” nad swoją robotą, ale… To o pozytywne wrażenia użytkownika właśnie nam chodzi. A tych możemy się spodziewać tylko wtedy, gdy w aplikacji, którą u nas zamówił, obsługa głównego wątku będzie płynna. Aby tak się stało, musimy podczas naszej pracy, programowania, wykonać wiele skomplikowanych operacji w tle. Do tego by otrzymać oczekiwany przez wszystkich efekt końcowy potrzebne jest właśnie programowanie reaktywne – nieblokujące i asynchroniczne.   

Przetwarzanie strumieniowe

Programowanie reaktywne
Programowanie reaktywne jest również nieblokujące i asynchroniczne.

Programowanie reaktywne (Reactive Programming) jest paradygmatem programowania, zbudowanym wokół przetwarzania strumieniowego. Dane są obsługiwane jako strumień punktów danych przechodzących przez potok funkcji lub operatorów. Każdy operator może przekształcać i manipulować danymi, zanim zostaną one przekazane do następnego operatora. Operatorami mogą być mapa, kolekcja, ale i inne elementy. Operacje te są łańcuchowo wykonywane do momentu zwrócenia przekształconych danych. Reactive programming w przeciwieństwie do imperatywnego, nie utrzymuje stanu, tylko go zmienia. 

Programowanie nieblokujące i asynchroniczne 

Programowanie reaktywne jest również nieblokujące i asynchroniczne. Nieblokujący kod to kolejny obszerny temat, ale upraszczając go: jest to kod, który się ‘nie zatrzymuje’, i ‘nie czeka’ aż coś się skończy (np. odczyt z dysku, lub wywołanie sieciowe). W idealnej sytuacji pozwala to na uzyskanie super wysokiej wydajności, ponieważ serwer może wykonać całą swoją pracę na jednym wątku. Jak w wielu jednak przypadkach, tak i w tym niezbędne stają się kompromisy.

Kod doskonały

Na przykład, kod nieblokujący był historycznie trudniejszy do wdrożenia, utrzymania i debugowania (wyszukaj w Internecie „callback hell”). Zmieniło się to do pewnego stopnia wraz z dojrzewaniem technologii. Świat jednak rzadko jest idealny. Nie wszystkie nieblokujące kody są nieblokujące, a jeden kawałek źle napisanego kodu w zależności, może zacząć blokować całą usługę sieciową, psując jej wydajność. Ale jeśli jest zrobiony dobrze, reaktywny kod nieblokujący może być świetnym narzędziem. Jednym z przypadków użycia, w których nieblokujący, reaktywny kod jest doskonały, jest obsługa strumieni.

Czym jest Spring WebFlux ?

Spring WebFlux jest reaktywnym, nieblokującym frameworkiem dla aplikacji Spring Boot. Został stworzony przez Project Reactor dla swojej reaktywnej, nieblokującej implementacji serwera WWW i  postawiony na serwerze Netty. WebFlux w rzeczywistości obsługuje inne implementacje serwera WWW, takie jak Tomcat, Jetty, Undertow i kontenery Servlet 3.1+. Dlaczego ktoś miałby używać Tomcat lub Jetty z Webflux (używając blokującego kontenera serwletów z reaktywnym, asynchronicznym frameworkiem)? Jest to otwarte pytanie, ale miło że też mamy taką opcję. Warto dodać że aplikacja może korzystać jednocześnie z Spring WebFlux oraz Spring Web MVC.

Jakie są różnice pomiędzy stosem serwletowym a reaktywnym?

ServletReactive
Modułem aplikacji webowych Springa jest spring-webmvcModuł aplikacji webowych Springa to spring-webflux
Spring MVC oparty na Servlet APISpring WebFlux oparty o podstawę do wykorzystania wielordzeniowych procesorów nowej generacji
Używa architektury synchronicznego blokowania I/OJest frameworkiem nieblokującym
Jedno żądanie na wątekPosiada zdolność do obsługi ogromnej ilości równoczesnych połączeń
Domyślnie używa serwletówDomyślnie używa Servlet 3.1+ i Netty
Używa Repozytoriów Danych Spring jako JDBC, JPA, NoSQLUżywa reaktywnych repozytoriów danych Spring Data jako Mongo, Cassandra, Redis, Couchbase, R2DBC
Model programowania wykorzystuje Servlet APIModel programowania wykorzystuje Adaptery strumieni reaktywnych
Spring SecuritySpring Security Reactive

Jak przebiega integracja z bazą danych ?

Bazy danych NoSQL takie jak MongoDB, Redis, czy Cassandra posiadają natywne wsparcie dla reaktywności jako część Spring Data. Co więcej, wiele relacyjnych baz danych takich jak Microsoft SQL Server, MySQL, H2, Postgres i Google Spanner posiada reaktywne wsparcie poprzez R2DBC.

Co to jest R2DBC ?

R2DBC to skrót od Reactive Relational Database Connectivity, oferuje integrację relacyjnych baz danych w reaktywnym stosie aplikacji. Jak na razie tylko bazy NoSQL mają natywne wsparcie reaktywne w Spring Data. R2DBC działa jak nakładka do integracji relacyjnych baz danych za pomocą reaktywnego sterownika. Spring Data R2DBC stosuje popularne abstrakcje Springa. Oferuje on łatwiejszy sposób budowania aplikacji opartych na Springu, które używają relacyjnych baz danych takich jak Microsoft SQL Server, MySQL, Postgres, H2 itp. w reaktywnym stosie aplikacji.

Czym jest WebClient?

WebClient to reaktywny klient sieci Web dla WebFlux zbudowany na podstawie dobrze znanego RestTemplate. Jest to interfejs, który reprezentuje główny punkt wejścia dla żądań internetowych i obsługuje zarówno operacje synchroniczne, jak i asynchroniczne. WebClient jest używany głównie do reaktywnej komunikacji backend-to-backend.

Reaktywne Stream API

Reactive Stream API to zaimportowany zbiór funkcji, które umożliwiają inteligentniejszy przepływ danych strumieniowych. Ma wbudowaną obsługę back-pressure i przetwarzania asynchronicznego, co zapewnia aplikacji najbardziej efektywne wykorzystanie zasobów.

W interfejsie Reactive Stream API istnieją cztery główne interfejsy:

  • Publisher: emituje zdarzenia do połączonych subskrybentów na podstawie ich wymagań. Działa jako centralny punkt łączący, który subskrybent może obserwować wydarzenia.
  • Subscriber: odbiera i przetwarza zdarzenia emitowane przez publishera. Wiele subskrybentów może łączyć się z jednym publisherem i inaczej reagować na to samo wydarzenie. Abonenci mogą być nastawieni na reagowanie:
    • onNext, kiedy otrzyma następne zdarzenie,
    • onSubscribe, gdy zostanie dodany nowy subskrybent,
    • onError, gdy wystąpi błąd u innego abonenta.