Meetup#5_reactive_spring.pptx
- Количество слайдов: 44
Reactive Spring June 14, 2017 PUBLIC 1
Agenda • Servlet API • Reactive Systems (Reactive Programming) • Project Reactor • Spring Web. Flux • Questions PUBLIC 2
A long time ago, in a galaxy far, far away… SERVLET API 2. 5 PUBLIC 3
Servlet API 2. 5 @Web. Servlet("/Blocking. Servlet") public class Blocking. Servlet extends Http. Servlet { private Slow. Service slow. Service; protected void service(Http. Servlet. Request request, Http. Servlet. Response response) { long process. Time = 6000; long start. Time = System. current. Time. Millis(); // print start time slow. Service. process(process. Time); long end. Time = System. current. Time. Millis(); // print end time } } Blocking. Servlet Start: Thread. Name=http-bio-8080 -exec-21; Thread. Id=17; Time Taken=6004 PUBLIC 4
Servlet API 2. 5 Client PUBLIC Server Service 5
Servlet API 2. 5 • Thread Starvation • Staleness • Not standard implementations – Tomcat: Comet – Jetty: Continuations – Web. Logic: Future. Response. Servlet – Web. Sphere: Asynchronous Request Dispatcher • Blocking wait – – Thread stack memory Local variables Thread. Locals Etc. PUBLIC 6
A long time ago, in a galaxy far, far away… SERVLET API 3. 0 PUBLIC 7
Servlet API 3. 0 @Web. Servlet(url. Patterns = "/Async. Servlet", async. Supported = true) public class Async. Servlet extends Http. Servlet { private Slow. Service slow. Service; private Thread. Pool. Executor executor; protected void service(Http. Servlet. Request request, Http. Servlet. Response response) { long process. Time = 6000; long start. Time = System. current. Time. Millis(); final Async. Context async. Context = request. start. Async(); executor. execute(() -> { slow. Service. process(process. Time); async. Context. complete(); }); long end. Time = System. current. Time. Millis(); } } PUBLIC 8
Servlet API 3. 0 Scheduled. Executor. Service executor. Service = Executors. new. Scheduled. Thread. Pool(1); Blocking. Queue<Async. Context> queue = new Array. Blocking. Queue<>(10000); { executor. Service. schedule. At. Fixed. Rate(this: : new. Message, 0, 6, Time. Unit. SECONDS); } protected void service(Http. Servlet. Request request, Http. Servlet. Response response) { add. To. Waiting. List(request. start. Async()); } private void new. Message() { Array. List<Async. Context> clients = new Array. List<>(queue. size()); queue. drain. To(clients); clients. parallel. Stream(). for. Each((Async. Context async. Context) -> { process(async. Context. get. Response()); async. Context. complete(); } private void add. To. Waiting. List(Async. Context context) { queue. add(context); } PUBLIC 9
Servlet API 3. 0 Client PUBLIC Server Service 10
Servlet API 3. 0 Client PUBLIC Server Service 1 Service 2 11
Servlet API 3. 0 Client Server Service Client PUBLIC 12
Servlet API 3. 0 • The same thread can serve multiple clients • Latency improvement by performing tasks concurrently with less resources • Async waits can increase performance PUBLIC 13
Servlet API 3. 0 @Web. Servlet("/Blocking. IOServlet") public class Blocking. IOServlet extends Http. Servlet { protected void service(Http. Servlet. Request request, Http. Servlet. Response response) { Servlet. Input. Stream input = request. get. Input. Stream(); byte[] b = new byte[1024]; int len = -1; while ((len = input. read(b)) != -1) { // do something What if the incoming data is blocking? } } Or streamed slower than the server can read? } Reje c ted PUBLIC 14
A long time ago, in a galaxy far, far away… SERVLET API 3. 1 PUBLIC 15
Servlet API 3. 1 protected void service(Http. Servlet. Request request, Http. Servlet. Response response) { final Async. Context async. Context = request. start. Async(); Servlet. Output. Stream output. Stream = response. get. Output. Stream(); output. Stream. set. Write. Listener(new Write. Listener() { @Override public void on. Write. Possible() throws IOException { while (output. Stream. is. Ready()) { int length = file. read(); if (length < 0) { async. Context. complete(); For fast IO return; } output. Stream. write(byte. Buffer, 0, length); } } }); For slow IO } PUBLIC 16
Servlet API 3. 1 output. Stream. set. Write. Listener(new Write. Listener() { @Override public void on. Write. Possible() throws IOException { if (output. Stream. is. Ready()) { output. Stream. print("<span>Hello, </span>"); output. Stream. print("<span>world!</span>"); Exception! The first print may be pending } } @Override public void on. Error(Throwable t) { } }); PUBLIC 17
Servlet API 3. 1 output. Stream. set. Write. Listener(new Write. Listener() { @Override public void on. Write. Possible() throws IOException { if (output. Stream. is. Ready()) { output. Stream. print("<span>Hello, </span>"); May be written multiple times! if (output. Stream. is. Ready()) { output. Stream. print("<span>world!</span>"); } } } @Override public void on. Error(Throwable t) { } }); PUBLIC 18
Servlet API 3. 1 output. Stream. set. Write. Listener(new Write. Listener() { @Override public void on. Write. Possible() throws IOException { if (output. Stream. is. Ready()) { output. Stream. print("<span>Hello, </span>"); logger. log("{}", output. Stream. is. Ready()); false -> call on. Write. Possible again } } @Override public void on. Error(Throwable t) { } }); PUBLIC 19
This is a new day, a new beginning REACTIVE SYSTEMS PUBLIC 20
Reactive Systems PUBLIC 21
Reactive Systems • Responsive – The system responds in a timely manner • Resilient – The system stays responsive in the face of failure • Elastic – The system stays responsive under varying workload • Message Driven – The system relies on asynchronous message passing PUBLIC 22
Why Reactive Programming? • Simpler code, making it more readable. • Abstracts away from boiler plate code to focus on business logic. • Abstracts away from low-level threading, synchronization, and concurrency issues. • Stream processing implies memory efficient • The model can be applied almost everywhere to solve almost any kind of problem. java. util. concurrent. Flow PUBLIC 23
Project Reactor • Efficient Message Passing • Friendly Adoption • Guardian of the Latency PUBLIC 24
Project Reactor Flux PUBLIC 25
Project Reactor Mono PUBLIC 26
Project Reactor Flux<Integer> seq 1 = Flux. just(1, 2, 3); List<Integer> iterable = Arrays. as. List(1, 2, 3); Flux<Integer> seq 2 = Flux. from. Iterable(iterable); Flux<Integer> seq 3 = Flux. range(1, 3); Mono<Integer> empty. Mono = Mono. empty(); Mono<Integer> not. Empty = Mono. just(1); Flux<Integer> merged = empty. Mono. merge. With(not. Empty); PUBLIC 27
Project Reactor Flux<Integer> seq = Flux. range(1, 3); seq. subscribe(new Base. Subscriber<Integer>() { @Override protected void hook. On. Next(Integer value) { System. out. println(value); } }); // 1 // 2 // 3 PUBLIC 28
Project Reactor Flux<Integer> source 1 = Flux. range(1, 10); Flux<Integer> source 2 = Flux. range(20, 30); Flux. merge(source 1, source 2). subscribe(new Base. Subscriber<Integer>() { @Override protected void hook. On. Next(Integer value) { System. out. println(value); } }); // // // 1 20 2 3 21 … PUBLIC 29
Reactive Anakin Skywalker PUBLIC 30
Reactive Anakin Skywalker Flux<Padawan> padawan. Flux = Flux. combine. Latest(young. Flux, advice. Flux, Padawan: : new); Flux<Knight> knight. Flux = padawan. Flux. filter(this: : is. Jedy. Training. Completed). map(Knight: : new); Flux<Damaged> damaged. Flux = Flux. zip(knight. Flux, damage. Flux, Tuples: : of). map(this: : to. Damaged. Anakin); Flux<Darth. Vader> darth. Vader. Flux = damaged. Flux. map(this: : wear. Helmet); PUBLIC 31
Reactive Anakin Skywalker Flux. combine. Latest(young. Flux, advice. Flux, Padawan: : new). filter(this: : is. Jedy. Training. Completed). map(Knight: : new). zip. With(damage. Flux, Tuples: : of). map(this: : to. Damaged. Anakin). map(this: : wear. Helmet); PUBLIC 32
Merge PUBLIC 33
Distinct PUBLIC 34
Distinct PUBLIC 35
Project Reactor Backpressure source. subscribe(new Base. Subscriber<Integer>() { @Override protected void hook. On. Subscribe(Subscription subscription) { request(2); } @Override protected void hook. On. Next(Integer value) { slow. Service. process(value); request(2); } }); PUBLIC 36
Project Reactor Backpressure PUBLIC 37
What’s new in SPRING 5 PUBLIC 38
Spring 5 • JDK 8+ • Commons Logging bridge out of the box • Spring Web. Flux • Kotlin 1. 1+ support • JUnit 5 support PUBLIC 39
SPRING WEBFLUX PUBLIC 40
Spring Web. Flux @Rest. Controller public class Reactive. Service. Application { @Get. Mapping("/events/{id}") Mono<Event> event. By. Id(@Path. Variable long id) { return Mono. just(new Event(id, new Date())); } @Get. Mapping(produces = Media. Type. TEXT_EVENT_STREAM_VALUE, value = "/events") Flux<Event> events() { Flux<Event> event. Flux = Flux. from. Stream(Stream. generate(() -> new Event(System. current. Time. Millis(), new Date()))); Flux<Long> duration. Flux = Flux. interval(Duration. of. Seconds(1)); return Flux. zip(event. Flux, duration. Flux). map(Tuple 2: : get. T 1); } } PUBLIC 41
Spring Web. Flux Router. Function<? > route = route(GET("/events/{id}"), request -> { Mono<Event> event = Mono. just. Or. Empty(request. path. Variable("id")). map(Integer: : value. Of). then(event. DAO: : get. Event); return Server. Response. ok(). body(from. Publisher(event, Event. class)); }). and(route(GET("/events"), request -> { Flux<Event> people = event. DAO. all. Events(); return Server. Response. ok(). body(from. Publisher(people, Event. class)); })); PUBLIC 42
Spring Web. Flux • Access database Few async clients • NIO calls • REST calls • JSON Async processing Few implementations PUBLIC 43
QUESTIONS? PUBLIC 44
Meetup#5_reactive_spring.pptx