Generator/dystrybutor reaktywnych strumieni Java™

This is the translation. The original web-page (oryginalna strona): http://www.coopsoft.com/ar/ReactiveArticle.html

Programowanie reaktywne jest głównym nurtem. Nawet Java9 zawiera interfejsy wspierające reaktywnego strumieni publikowania-subskrybowania ramy (JEP 266). Programowanie reaktywne programuje się za pomocą asynchronicznych strumieni danych. To wprowadzenie nie dotyczy podstawowej kwestii tworzenia/dystrybucji strumienia zdarzeń. Po utworzeniu strumienia dostępne są wszechobecne programy do obsługi strumienia. Tworzenie/dystrybucja strumienia jest przedmiotem tego artykułu. (1100 słów)

Edward Harned (eh at coopsoft dot com@ed_harned)
Starszy programista, Cooperative Software Systems, Inc.
Październik 2015 [zaktualizowany styczeń 2018]

Przedmowa

  1. Prosty problem wymaga prostego rozwiązania.
    W przypadku pojedynczego subskrybenta wymagającego wypychania pojedynczy wydawca może obsłużyć tego pojedynczego subskrybenta. Jeden wydawca może również obsługiwać wielu subskrybentów, z tym samym wymaganiem push.

    single subscriber/publisher  single subscriber/publisher … single subscriber/publisher multiple subscriber/publisher
  2. Złożony problem wymaga więcej przemyślenia.

Gdy wielu subskrybentów o różnych wymaganiach (powiedzmy różne wymagania dotyczące filtrowania) potrzebuje tego samego asynchronicznego strumienia, wówczas pojedynczy wydawca z wieloma wątkami roboczymi może obsłużyć tych subskrybentów.

single subscriber/publisher with multiple threads

Jednak gdy jest wielu (dziesiątki/setki) subskrybentów, istnieje potrzeba lepszego rozwiązania.

  1. Odległy, złożony problem wymaga jeszcze więcej przemyślenia.

Gdy wielu subskrybentów przebywa w różnych lokalizacjach, a wydawca przebywa osobno od reszty, jest to zupełnie nowa gra.

remote subscriber/publisher with multiple threads

Każdy subskrybent i wydawca przebywają we własnej JVM. Im więcej wydawców, tym więcej JVM. Gdy jest wielu (dziesiątki/setki) wydawców, istnieje potrzeba lepszego rozwiązania.

  1. Problem złożony wymaga najwięcej przemyślenia.

Kiedy istnieje połączenie pojedynczego subskrybenta, wielu subskrybentów, złożonych i zdalnych subskrybentów, a istnieje wielu (dziesiątki/setki) tych subskrybentów i wydawców, wówczas potrzebne jest unikalne rozwiązanie.

single subscriber/publishersingle subscriber/publisher … single subscriber/publisher multiple subscriber/publisher multiple subscriber/publisher with threads remote subscriber/publisher with multiple threads

Problem

Wielu wydawców oznacza wiele maszyn JVM. Posiadanie relacji jeden do jednego, gdy są setki wydawców, może doprowadzić do stanu braku zasobów.

Wielu wydawców mieszkających w tym samym JVM wymaga metody śledzenia tych wydawców. Gdy każdy wydawca potrzebuje wątku, może to doprowadzić do stanu braku zasobów.

Ramy Java9 przepływu (JEP 266) z klasy SubmissionPublisher jest niezwykle skuteczny w wypluwa Przedmioty do zadań konsumpcyjnych, ale jego nadmierne Object() może spowodować tworzenie Out Of błędów pamięci. (Można pobrać kod źródłowy demo, który wykorzystuje SubmissionPublisher: DemoOut.java poniżej.)

Jakkolwiek na to nie spojrzysz, głośność zmienia wszystko.

Rozwiązanie

Kluczem do sukcesu jest utworzenie półstałego Zadania dla każdego Subskrybenta (subskrybenta-obiektu). Wydawca przekazuje operację bezpośrednio do kolejki subskrybenta-obiektu; nie ma potrzeby tworzenia nowego zadania. Obiekt subskrybenta wysyła następnie wypychane elementy do subskrybenta, lokalnie lub zdalnie. Każde zadanie wykonuje się w wydajnej wielozadaniowej mikrousługi z dobrze zarządzanymi wątkami. Obraz jest wart tysiąca słów.

Tymeac do generowania Reactive Stream to rozwiązanie do śledzenia wielu operacji wypychania z dowolnej liczby wydawców z najmniejszą liczbą wątków.

Tymeac jest

  1. Wydajna usługa wielozadaniowa, która pozwala wielu aplikacjom wymagającym dużych zasobów współistnieć w jednej mikrousługi.

  2. Wydajny silnik wypychający umożliwiający (Reactive Stream) wydawcom generowanie asynchronicznych strumieni do routingu do subskrybentów. Tymeac nie jest „wydawcą”. Ponieważ jednak Wydawca eksportuje pracę subskrypcji (filtr itp.) Do Zadań, Wydawca może działać jako samo zadanie Tymeac i nie musi wiązać wątku.

  3. W 100% czysty silnik Java. Tymeac nie polega na zewnętrznych pakietach do wielozadaniowości. Bez preprocesorów, bez środowisk uruchomieniowych, bez ograniczeń sprzętowych. Jeśli twoja aplikacja działa w Java SE, działa bez żadnych modyfikacji ani dodatkowych pobrań za pomocą Tymeac.

  4. Elastyczny silnik pchający, który obsługuje nieblokujące przeciwciśnienie. Możesz anulować (bez podania przyczyny), wstrzymać/wznowić i zmienić dowolną aplikację w dowolnym momencie.

  5. Odporny silnik wypychający, który obsługuje wiele scenariuszy przekroczenia limitu czasu w celu obsługi niereagujących aplikacji.

  6. Skalowalny silnik wypychający, ponieważ zadania są oddzielne od wątków.

  7. W pełni funkcjonalny silnik pchający. Tymeac jest wyposażony w dziewiętnaście interfejsów graficznych JavaFX i dostęp do programu klienckiego, dzięki czemu można monitorować/zmieniać żądanie wykonania i serwer. I jeszcze pięć GUI JavaFX do konfiguracji zaplecza.

    Tymeac Menu

  8. Regulowany silnik pchający. Każda kolejka i wątek ma strukturę zarządzania ułatwiającą dostrajanie.

  9. Wszechstronny silnik push z obsługą lokalnego dostępu (ta sama JVM) i zdalnego dostępu (RMI.)

  10. Dobrze udokumentowany silnik pchający. Podczas gdy JavaDoc jest przyjemny dla API, profesjonalna mikrousługa wymaga profesjonalnej dokumentacji.


Tymeac obsługuje zarówno przetwarzanie komunalne, jak i odrębne.

Jak działa przetwarzanie komunalne:

Społeczność to wspólnota. W społeczności gracze grają ze sobą dobrze. Ci, którzy nie bawią się dobrze, psują go wszystkim. Jeśli gracz nie będzie grać ładnie, wtedy gracz należący do „wyraźnego” placu zabaw.

Zadanie jest sercem przetwarzania. Zadanie zawiera zmienne/metody, które Tymeac potrzebuje do wielozadaniowych żądań. Wszystkie klasy użytkowników muszą rozszerzyć tę klasę. Zadanie może być

  • aktywne obliczanie strumienia lub
  • czasowe oczekiwanie na zasób (dostęp do bazy danych/plików, dostęp do Internetu lub inny dostęp do usługi) Limit czasu jest sposobem na obsługę dostępu bez odpowiedzi,
  • oczekiwanie na zakończenie wysyłania (onNext itp.)

Podczas gdy to zadanie na coś czeka, Tymeac może zawiesić zadanie, zwalniając wątek do innej pracy. Jest to proste zarządzanie zadaniami, z którego korzysta większość systemów operacyjnych do planowania pracy na procesorach. Tymeac nie może zmienić kontekstu. Tymeac polega na Zadaniu współpracującym przez ustawienie Zadanie oczekujące na działanie (potrzebujesz wysłania, potrzebujesz zasobu) i powraca z wywołania metody, a nie blokuje.

Tymeac używa trzech kolejek: Aktywnej, Wysyłającej i Zawieszonej. Każda kolejka ma dedykowaną pulę wątków.

Active Queue Sending Queue Suspended Queue

Aktywny Kolejka jest dla wątków do pobrania zadania [niski procesora Wydawcy użytkowania i obiektów abonenta] więc Zadania mogą obliczyć to, co robią. Gdy zadanie wymaga zasobu Zadanie będzie uruchamiane asynchronicznego dostępu, ustawia szacowany czas opóźnienia to uważa, że może mieć dostęp (oczekująca działania o to opóźnienie w oczekiwaniu na zakończenie) i wraca, chyba że też musi wysłać dane. Gdy zadanie musi wysłać strumień (onNext itd) ustawia Zadanie Send-pending (oczekujący akcję) i zwraca. Jeśli istnieje wyślij do opatentowania, Tymeac przenosi zadanie do Wysyłanie kolejkiJeśli nie ma wyślij do opatentowania ale występuje opóźnienie w oczekiwaniu Tymeac przenosi zadanie do Zawieszone kolejki.

Wysyłanie Kolejka jest dla wątków do pobrania zadania i korzystać Abonenta <T>, aby wysłać asynchroniczny strumień (onNext/Błąd/Zakończone). Po wyślij zakończeniu Tymeac przenosi zadanie z powrotem do Aktywnego kolejce, lub, jeśli nie jest jeszcze opóźnienie wybitne, Tymeac przenosi zadanie do Zawieszone kolejki.

Kolejka zawieszony jest na oczekiwanie na zdarzenie, aby zakończyć (opóźnienie upłynąć lub jeden z tych asynchroniczny dostęp do ukończenia). Po zakończeniu imprezy, Tymeac przenosi zadanie z powrotem do Aktywny/odrębny kolejki.

W ten sposób Zadania współpracują z innymi Zadaniami, nie wiążąc wątku z blokowaniem połączeń. Oblicz, czego potrzebujesz. Zrezygnuj z wątku, gdy musisz poczekać. System może obsługiwać setki/tysiące aktywnych żądań za pomocą zaledwie kilku wątków.

Jak działa odrębne przetwarzanie:

Tymeac wykorzystuje jedną kolejkę: Odrębny. Kolejka posiada dedykowany puli wątków.

Odrębny kolejka służy do zadań [wysokie zużycie procesora Wydawca], aby zrobić wszystko, co robią; dostęp do zasobów, poczekaj na te zasoby. Zadania nie mogą zostać wysłane przy użyciu kolejki wysyłania. Zadania z pewnością mogą realizować dowolną potrzebną komunikację, po prostu nie korzystając z kolejki wysyłania, czyli tylko do zadań komunalnych. Raz tu pozostają, dopóki prośba się nie zakończy. Różnica między ogólną pulą wątków a przetwarzaniem Distinct polega na tym, że Tymeac zarządza trwałością, przesyłaniem wiadomości, kolejkowaniem, wątkami, wykrywaniem i odzyskiwaniem utknięcia, rekurencją, rejestrowaniem, statystykami, interfejsem użytkownika i wiele więcej.

Zdjęcie z rozwiązania, powyżej:

Legenda

SubscriberSubscriberSubscriber Subskrybenci
subscriber-objectsubscriber-objectsubscriber-object Obiekty subskrybenta działające jako Zadania w Tymeac.
 Kod, którego subskrybenci używają, aby zadzwonić do Publishers lub bezpośrednio do Tymeac.
PublisherPublishers działający jako zadania w Tymeac.
TymeacTymeac
CommunalKolejka żądań/wątki komunalne w Tymeac.
DistinctWyraźna kolejka żądań/wątki w Tymeac.

Obrazek

local JVMRemote JVM
Lokalna JVM                                               Zdalne JVM

Wniosek

Jeśli potrzebujesz bezpiecznego, niezawodnego, łatwego w zarządzaniu i odpornego na awarie Asynchroniczny Konstruktor/Dystrybucja strumienia do dowolnego celu i nie chcesz zaczynać od początku projektowania i testowania go samodzielnie, potrzebujesz Tymeac.

Bibliografia

Pobierz kod źródłowy artykułu tutaj.

Pobierz projekt ze SourceForge.net, projekt: TymeacRSE

JEP 266
http://openjdk.java.net/jeps/266

Wprowadzenie do programowania reaktywnego
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

Reaktywne strumienie org
http://www.reactive-streams.org/

O autorze

Ed Harned jest programistą z ponad trzydziestoletnim doświadczeniem w branży. Najpierw kierował projektami jako pracownik w głównych branżach, a następnie pracował jako niezależny konsultant. Dziś Ed jest starszym programistą w Cooperative Software Systems, Inc., gdzie przez ostatnie osiemnaście lat korzystał z programowania Java™, aby wprowadzać równoległe rozwiązania dla szerokiego zakresu zadań.

© 2015 – 2017  E.P. Harned  All rights reserved