Reactor
Table of Contents
Purpose
WebFlux provides developers with the Reactor interface to use Netty, so it is important to understand related concepts.
What is Reactive Stream?
A standardized interface for processing asynchronous streams using non-blocking back pressure. Reactor implements the reactive stream specification.
https://www.reactive-streams.org/
Structure
Traditional Observer Pattern
Publisher
- Registers subscribers
- Delivers data to subscribers
Subscriber
- Provides an update() callback function to execute logic, which is called by the publisher
Similarity to Reactive Stream Interface
Function | Observer Pattern Method | Reactive Stream Method |
---|---|---|
Subscribe | Publisher.subscribe(Subscriber) | Publisher.subscribe(Subscriber) |
Data Transfer | Publisher.notifiySubscribers()\n - Subscriber.update(context) | ? How is it called\n• There must be an interface that calls Subscriber.onNext(T) callback. (→ Using Subscription) |
Adding Subscription
- Subscriber.onSubscribe(Subscription)
- Callback function called at the time of subscription by the publisher
- Passes the Subscription
- Subscription
- Called by the subscriber for back pressure
- request(long)
- Determines the amount of data to request. The publisher calls the subscriber’s onNext as many times as requested.
- cancel()
- Function to cancel further data processing
Flow of Operation
- Register subscription relationship
- Publisher.subscribe(Subscriber)
- A subscription is established when the subscriber subscribes to the publisher.
- Pass Subscription
- Publisher calls Subscriber.onSubscribe(Subscription) and passes the subscription
- Data Request
- When onSubscribe is called, the subscriber calls request() to request data
- Data Delivery
- The publisher calls the subscriber’s onNext() to deliver data
- Request More After Processing
- After processing data, the subscriber requests more data with request()
- Completion of Data Delivery
- When the publisher has delivered all data, it calls the subscriber’s onComplete
Implementation Example
Specification: https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.4/README.md#specification
Subscriber
- Requests data at the time of subscription
- Calls request() after onNext to request the next data
|
|
Publisher
- Calls onNext as many times as data is requested
- Stops sending data if canceled
- Technically, the Subscription object sends data to the subscriber, but we say the publisher sends data to the subscriber (since the logic is implemented in the publisher)
|
|
Result
Operator
- All operators such as map, filter, etc. are operators. This is the most important part.
- Operator is also a Publisher
|
|
Result
LifeCycle
https://spring.io/blog/2019/03/06/flight-of-the-flux-1-assembly-vs-subscription
Assembly Time
- The time when the pipeline is built
- Data does not actually flow yet. In other words, the pipeline is not executed yet
Subscription Time
- The time when subscription occurs
- The publisher calls subscribe from downstream to upstream
- In the example above, MapOperator.subscribe is called from the main thread, then IterablePublisher.subscribe is called
- Therefore, subscriberContext should be placed at the bottom
Execution time
- The time when the publisher emits data via onNext
- Data flows in the order built at AssemblyTime (opposite direction of Subscription)
Debugging Difficulty
- Assembly Time and Execution time are different
- The data flow is understood as the pipeline defined at Assembly Time
- But the actual stack trace is left by Execution time calls
- Difficult to understand because it is implemented as a functional interface
Simple Implementation of Flux Interface
Implementing JFlux, which mimics the Flux interface
JFlux
- API part
- Returns the previously implemented object every time a function is called
- Since the previously created Flux calls the function, only the parameters needed for each function are received, implementing a fluent API
|
|
Subscriber Receiving Lambda
- Receives a function to execute on onNext
|
|
Publisher
- Only changed to generic from the previous example
|
|
MapOperator
- Only changed to generic interface
- JFlux
emits data of type JFlux by the mapper
|
|