Zastosowanie tzw reaktywności w aplikacjach. Reactive Zastosowanie tzw reaktywności w aplikacjach.
No to zróbmy coś Zrób to !!!
W oczekiwaniu na wynik
Aplikacja web
Przetwarzanie żądań Pula wątków odbierających żądania
Czasami nasze niektóre zadania… są cięższe niż wyświetlenie buźki na ekranie….
… i potrafią przytkać system… Pula połączeń
… lub wyżreć całą pamięć…
Co można poradzić dołożyć sprzętu? dołożyć pamięci?
Jeszcze jeden przypadek gdzieś w odległej Galaktyce
A może… …ograniczyć żarłoczność naszej aplikacji? ale jak skoro już zoptymalizowaliśmy wszystko? ;) Ha… można uruchamiać obciążające zadania cyklicznie w nocy kiedy użytkownicy śpią i nam nie będą przeszkadzać…
Wielowątkowe przetwarzanie zadań pula wątków pula wątków pozwala na sterowanie zużyciem pamięci, zasobów itp
Zdarzenia tymczasowa prywatna kolejka publiczna kolejka z odpowiedziami
Wątki blokujące
Opóźnienia gdzieś w odległej Galaktyce
Wątki blokujące
Koszt połączenia
Koszt połączenia
To może…
To może…
Czyli wątek przyjmujący żądania wątek przetwarzający żądanie wątek wysyłający odpowiedź opcjonalnie
Z czego skorzystać Pule wątków (java.io.concurrency) JMS RabbitMQ Wsparcie frameworków (JEE 6, Spring) Inne TIMEOUT!!!!
ThreadPool pula wątków Potraktujmy pulę wątków jak pulę połączeń. Spowodujemy iż określone zadanie będzie przeprowadzane tylko przez określoną ilość wątków. Dzięki temu zapanujemy np. nad zużyciem pamięci i zablokujemy nadmierną pazerność aplikacji (jeśli takowa istnieje).
Executor ExecutorService executorService = Executors.newFixedThreadPool(10); ExecutorService executorService = Executors.newCachedThreadPool( new ThreadFactory() { @Override public Thread newThread(Runnable r) { return ….. ; } });
Callable<V> i Future<V> public interface Callable<V> { V call() throws Exception; } public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
Wywołanie zadania ExecutorService executorService = Executors.newFixedThreadPool(10); Future<String> future = executorService.submit( new Callable<String>() { @Override public String call() throws Exception { executorService.invoke(); return "TEST"; } }); <T> List<Future<T>> invokeAll( Collection<? extends Callable<T>> tasks) throws InterruptedException;
Zbieranie wyników ExecutorService executorService = Executors.newFixedThreadPool(5); CompletionService completion = new ExecutorCompletionService(executorService); for(;;){ completion.take(); } Future<V> take() throws InterruptedException;
Hmmmm Programowanie synchroniczne jest proste. Asynchroniczność dramatycznie podnosi poziom skomplikowania.
Wyzwania Obsługa błędów Łańcuch wywołań Kiedy użytkownik już nie czeka na odpowiedź Przełączanie wątków np do aktualizacji UI Unikanie blokad Wielu odbiorców Złożone funkcje Backpressure
Aplikacje reaktywne Dane są procesowane w postaci strumieni Sterowanie poprzez zdarzenia Utrzymują “życie” pomimo błędów Są odporne na zbyt duże obciążenie
Reactive Reactive Streams http://www.reactive-streams.com https://github.com/reactive-streams/reactive-streams-jvm Reactive Extensions https://reactivex.io/
Jak skorzystać? RxJava (i odmiany dla innych języków) Spring Reactor JVM 9+
Podstawowe interfejsy public interface Publisher<T> { public void subscribe(Subscriber<? super T> s); } public interface Subscriber<T> { public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete();
Podstawowe interfejsy public interface Subscription { public void request(long n); public void cancel(); } public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
RX Observable lub Flowable Observer lub Subsciber Subject lub Processor Operator Scheduler