Reactive SSE as a lightweight replacement for WebSockets

Along with the heavyweight WebSocket, HTML 5 introduced a new way of creating static (in this case, half-duplex) connections, where the server is capable of pushing events. This technique solves similar problems to WebSocket. For example, we may declare a Server-sent events (SSE) stream using the same annotation-based programming model, but return an infinite stream of ServerSentEvent objects instead, as shown in the following example:

@RestController                                                    // (1)
@RequestMapping("/sse/stocks") //
class StocksController { //
final Map<String, StocksService> stocksServiceMap; //
...
@GetMapping // (2)
public Flux<ServerSentEvent<?>> streamStocks() { // (2.1)
return Flux //
.fromIterable(stocksServiceMap.values()) //
.flatMap(StocksService::stream) // (2.2)
.<ServerSentEvent<?>>map(item -> //
ServerSentEvent // (2.3)
.builder(item) // (2.4)
.event("StockItem") // (2.5)
.id(item.getId()) // (2.6)
.build() //
) //
.startWith( // (2.7)
ServerSentEvent //
.builder() //
.event("Stocks") // (2.8)
.data(stocksServiceMap.keySet()) // (2.9)
.build() //
); //
}
}

The numbers in the preceding code can be explained as follows:

  1. This is the declaration of the @RestController class. In order to simplify the code, we have skipped the constructor and field initialization parts.
  2. Here, we have the declaration of the handler method annotated by the familiar @GetMapping. As we can see at point (2.1), the streamStocks method returns the Flux of the ServerSentEvent, which means that the current handler enables event streaming. Then, we merge all available sources of stocks and stream changes to the client, as shown at point (2.2). After that, we apply mapping, which maps each StockItem to a ServerSentEvent, as shown at (2.3), using the static builder method at (2.4). In order to properly set up a ServerSentEvent instance, we provide, in the builder parameters, the event ID (2.6) and the event name (2.5), which allows the messages to be distinguished on the client side. In addition, at point (2.7), we start the Flux with the specific ServerSentEvent instance, shown at point (2.8), which declares the available stock channels to the client (2.9).

As we can see from the preceding example, Spring WebFlux allows to map the streaming nature of the Flux reactive type and send an infinite stream of stock events to the client. In addition, SSE streaming does not require us to change the API or use additional abstractions. It simply requires us to declare a specific return type to help the framework figure out how to deal with the response. We do not have to declare the Flux of the ServerSentEvent either; we can instead provide the content type directly, as shown in the following example:

@GetMapping(produces = "text/event-stream")
public Flux<StockItem> streamStocks() {
...
}

In this case, the WebFlux framework wraps each element of the streams into the ServerSentEvent internally.

As we can see, the central benefit behind the ServerSentEvent technique is that the configuration of such a streaming model does not require additional boilerplate code, which we have with WebSocket adoption in WebFlux. This is because SSE is a simple abstraction over HTTP that does not need protocol switching and does not require specific server configuration. As we can see from the preceding example, SSE may be configured using the traditional combination of the @RestController and @XXXMapping annotations. In the case of WebSocket, however, we need a custom message conversion configuration, such as manually choosing a particular messaging protocol. By contrast, for SSE, Spring WebFlux offers the same message converter configurations as for a typical REST controller.

On the other hand, SSE does not support binary encoding and limits events to UTF-8 encoding. This means that WebSocket may be useful for a smaller message size and for transferring less traffic between the client and the server, therefore having a lower latency.

To summarize, SSE is generally a good alternative to WebSocket. Since SSE is an abstraction over the HTTP protocol, WebFlux supports the same declarative and functional endpoint configurations and message conversion as for typical REST controllers.

To learn more about the advantages and disadvantages of SSE and how it compares to WebSocket, please see the following post: https://stackoverflow.com/a/5326159/4891253.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.104.124