Building reactive rest API with Java - kalpa Senanayake

Jiedao jdon 2021-05-04 04:45:02
building reactive rest api java


The focus of this article is to use Java structure RESTFul API, And benefit from the reactive programming model . But unlike most other articles on the subject , This article will not rush to write code directly . It will guide you through the backbone of this programming paradigm , So that you can have a full understanding of it . And then use that knowledge to build API.

The series consists of two parts . The first part introduces the reaction system and reactive programming , And clear the confusion between these terms .

Then it introduces the basic knowledge of reactive programming , And combine the traditional concurrency model with message / Event driven concurrency is compared .

The second part is about using Spring WebFlux To dirty and build RESTFul API, And introduce the fourth generation reaction framework to readers .

Reaction system

Reactive system architecture is the architectural style of building responsive systems . This is defined in the declaration of responsiveness , We will briefly introduce each of the key items in the declaration , At the same time, use daily system behavior to explain its meaning .

The reaction system responds quickly : The system responds in time , Provide consistent quality of service .

This means that the system runs in a consistent way when the load is high and low . As a result, users begin to build confidence in your system , And continue to do business with systems .

The reaction system is elastic : The system remains responsive in the event of a failure .

This means that the system can isolate faults , Include failures and use replication if necessary to mitigate failures and continue to serve users .

Things often go wrong . however , If we have a flexible system , So it can be so agile .

The reaction system is elastic : The system remains responsive under different workloads .

This means that the system can respond to changes in load . This again links to responsiveness , Because you can see that responsiveness cannot be achieved without elasticity and elasticity .

The reaction system is message driven : The system relies on asynchronous messaging . It passes failure as a message . And it applies backpressure to control the flow of messages when necessary .

This means that the system responds to events / Respond to the news , And consume resources only when they are active .

Reactive systems and reactive programming are two different things . One is architecture style , The other is programming paradigm , It can be used to realize some characteristics of reaction system , But not all .

Reactive programming

Now? , We have a good understanding of the reaction system . It's time to take a deeper look at the concept of reactive programming .

Reactive programming is a branch of the asynchronous programming paradigm , It allows information to drive logic instead of relying on the thread of execution

Now? , It sounds like Wikipedia or some academic research paper . The terminology it throws out seems a little scary . In simple language :

Reactive programming allows applications to be message based / The event occurs at any time and the operation , Instead of execution driven threads .

Now you can see that message driven and responsive features can benefit from responsive programming . But not all , To achieve all these goals , We need a broader range of tools . These are beyond the scope of this article .

event 、 event 、 Or events

Different types of events :

  • Click stream : Click on different points on the timeline , It's a series of events . When it happens , There's no guarantee it's properly spaced .
  • Notification of news application : News items will be displayed on the phone screen at any time as push notifications . No one knows when the breaking news will happen .
  • From a remote endpoint HTTP Respond to : The Internet has its own problems , Such as delay and connection failure , So the response arrives at any time interval .

Reactive programming and events

The common factor in these types of events is that they happen at any time , So if we have an execution thread in the program , Those threads have to wait for these events to complete .

If the system has more clients waiting for the results of these operations , So we need more threads to server clients .

That's where reactive programming stands out . It's not waiting for these events to complete , It provides a mechanism similar to an observer , Let these events drive execution .

The result is a reduction in the number of threads and resources that handle a large number of these events .

The most important fact we need to understand is :

Reactive programming doesn't make applications faster , But it allows applications to serve more clients with fewer resources .

If we need to expand , We can scale out ( Use fewer resources ), This makes it a perfect example of building modern microservices . This is how reactive programming enhances the elastic properties of reactive systems .

The characteristics of the reactive programming library

Understanding the characteristics of reactive programming is the key to unraveling the possibilities :

  1. Execution is asynchronous and non blocking . This means that the calling thread does not block I / O Event and wait for it to complete . We'll discuss this in detail later in this article .
  2. Non blocking back pressure . Nonblocking backpressure is a mechanism that allows event subscribers to control event flow rate in a nonblocking way . In the case of congestion , Will block publishers , Forcing publishers to wait for consumers to recover from congestion .
  3. This allows slow publishers to / Quick recipients and quick publishers / In the slow receiver's scenario .
  4. Support reaction flow : An unlimited event / Message flow , Passing elements asynchronously between components , With mandatory non blocking pressure .

Combined with all of the above , We have a good understanding of applications developed using reactive programming principles .

These applications support handling an unlimited number of events , Event driven and understanding of the environment they are dealing with , And can react to changes in these environments .

Why is it important , What are the benefits , It's not clear ?

Let's go into more details and discuss .

I remember one time I talked to other developers about reactive programming for coffee , His problem is .

“ What are the benefits of using it ?”

“ Compared to what we use today , What benefits does it bring to the desktop ?”

These are all questions about the full effectiveness of any new technology . To answer these questions , We need to step back and think about how we use Java Tools for building applications .

use Java Compiling Web API Usually deployed to places like Tomcat,WebSphere etc. servlet In the container . These containers use Servlet API To operate , These operations provide blocking I / O.  So popular frameworks like Spring,Spring Web MVC Also inherited this blocking behavior .

Database operations prevent I / O call ,JPA,JDBC They all work in this way .

These blocking operations block the requesting thread , Until the operation is complete . therefore , More requests cause more blocked threads to wait I / O Operation is completed . give the result as follows .

  1. Pay more for context switching between threads CPU Time .
  2. The system has to allocate more memory to support more and more threads and their execution stacks .
  3. More memory means more GC Time and CPU Upper GC expenses .

It's not just I / O operation ,Java Ordinary citizens of concurrent tools also have blocking behavior :

  1. java.util.concurrent.Future, We can use Future To represent the result of asynchronous computation .
    FutureTask<String> future =       new FutureTask<String>(new Callable<String>() {         public String call() {           return searcher.search(target);       }});     executor.execute(future);
    
    But when you need results, we have to call :
    //Waits if necessary for the computation to complete, and then retrieves its result.String result = future.get();
    
  2. Sync synchronized  Method also forces the thread to stop and check before entering the logical block .

Blocking I / O The problem with the method is , Use block API, We can't support the reaction system . It's executive driven , Synchronized threads . These two reasons make the resource consumption very large . The next step will be to find a way to find a more efficient way to perform operations asynchronously and nonblocking .

Java 8 brought CompletableFuture, It's a truly asynchronous non blocking feature of asynchronous programming . But if you want to write more results and stream them , The code becomes hard to read , And lack of smooth operation API.

Non blocking method

Java Later introduced java.nio package , Call... By introducing a concept Selector To solve this blocking behavior , It can monitor multiple channels .

This allows a single thread to monitor many input channels . And loading data into ByteBuffers Instead of blocking Streams Key concepts of . therefore ,ByteBuffers Available data will be provided .

Here are the USES NIO Function of the server demonstration . It's using NIO Realized echo A simple implementation of the server , But enough examples to get the basics of non blocking methods .

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class NIOServer {
    private static final int PORT = 8888;
    private static final int BUFFER_SIZE = 1024;
    private static Selector selector = null;
    public static void main(String[] args) {
        logger("Starting NIOServer");
        try {
            InetAddress hostIP = InetAddress.getLocalHost();
            logger(String.format("Trying to accept connections on %s:%d", hostIP.getHostAddress(), PORT));
            // create selector via open();
            selector = Selector.open();
            // create a server socket channel
            ServerSocketChannel server = ServerSocketChannel.open();
            // get the server socket
            ServerSocket serverSocket = server.socket();
            InetSocketAddress address = new InetSocketAddress(hostIP, PORT);
            // bind the server socket to address
            serverSocket.bind(address);
            // configure socket to be non-blocking
            server.configureBlocking(false);
            // register selector interest for accept event.
            server.register(selector, SelectionKey.OP_ACCEPT);
            while (true) {
                // get a channel from selector, this will block until a channel get selected
                selector.select();
                // get keys for that channel
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> i = selectedKeys.iterator();
                // go through selection keys one by one and see any of those events are ready
                // if ready process that
                while (i.hasNext()) {
                    SelectionKey key = i.next();
                    if (key.isAcceptable()) {
                        processAcceptEvent(server, key);
                    } else if (key.isReadable()) {
                        processReadEvent(key);
                    }
                    i.remove();
                }
            }
        } catch (IOException e) {
            logger(e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * Handle the accept event
     *
     * @param socket    Server socket channel
     * @param key       Selection key
     * @throws IOException  In case of error while accept the connection
     */
    private static void processAcceptEvent(ServerSocketChannel socket, SelectionKey key) throws IOException {
        logger("Connection Accepted");
        // Accept the connection and make it non-blocking
        SocketChannel socketChannel = socket.accept();
        socketChannel.configureBlocking(false);
        // Register interest in reading this channel
        socketChannel.register(selector, SelectionKey.OP_READ);
    }
    /**
     * Handle the read event
     *
     * @param key    Selection key for the channel.
     * @throws IOException
     */
    private static void processReadEvent(SelectionKey key) throws IOException {
        logger("Handling ReadEvent");
        // create a ServerSocketChannel to read the request
        SocketChannel client = (SocketChannel) key.channel();

The basic principle behind this approach is ,Selector You can register its interests in multiple channels , When these things happen , The main thread responds to these events by calling matching processing logic .

The only blocking code is number 39 That's ok :

// Get a channel from the selector , This will block until a channel is selected 
selector.select();

select() Methods block , Until you choose a channel . for example , Until a new connection happens .

The event loop

The pattern above is that we are in JavaScript It's called the cycle of events in the world event loop The pattern of .Javascript It's a single threaded runtime , So it has to find ways to support multiple tasks , Instead of having to create multiple threads .

When NodeJS Appear and start with less memory footprint and CPU Time to deal with heavy load ,Java The community realizes that this is a more scalable way to solve this set of problems . as everyone knows , Multithreaded applications are difficult to develop , Difficult to maintain .

Reactive library package

Now we have a good understanding of the old Java Synchronous blocking behavior of the world and a new way to use event loops for non blocking , We can start to get into Reactive The world .

First ,Microsoft by .NET The framework creates reactive extensions . And pass JavaScript Follow up single thread , Non blocking , Asynchronous language , It has a real need for a reaction Library , therefore RxJ There is a .

You can find it in most popular programming languages Rx library . The current library for reactive programming provides the following .

  1. When data is available , Complete pipeline for non blocking operation .
  2. A rich set of operators to manipulate these event flows .
  3. Back pressure , The ability to control producer event emission rates .
  4. Be able to arrange multiple asynchronous tasks in code with good readability .

版权声明
本文为[Jiedao jdon]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/05/20210504044315693m.html

  1. 21. Object oriented foundation "problems and solutions of object traversal"
  2. Discussion on hot micro front end: Google AdWords is a real micro front end
  3. Usecallback and usememo for real performance optimization
  4. 【前端圭臬】十一:从规范看 JavaScript 执行上下文(下)
  5. [front end standard] 11: Javascript execution context from the perspective of specification (2)
  6. Hexagonal六角形架构ReactJS的实现方式 - Janos Pasztor
  7. Transaction of spring's reactive / imperative relational database
  8. The implementation of hexagonal hexagonal reactjs Janos pasztor
  9. HTTP状态码:402 Payment Required需要付款 - mozilla
  10. HTTP status code: 402 payment required - Mozilla
  11. Factory mode, constructor mode and prototype mode
  12. Build the scaffold of react project from scratch (Series 1: encapsulating a request method with cache function based on Axios)
  13. Cocos Quick Start Guide
  14. Comparison of three default configurations of webpack5 modes
  15. A case study of the combination of flutter WebView and Vue
  16. CSS: BFC and IFC
  17. A common error report and solution in Vue combat
  18. JS: this point
  19. JS: prototype chain
  20. JavaScript series -- promise, generator, async and await
  21. JS: event flow
  22. Front end performance optimization: rearrangement and redrawing
  23. JS - deep and shallow copy
  24. JavaScript异步编程3——Promise的链式使用
  25. JavaScript asynchronous programming 3 -- chain use of promise
  26. Vue.js组件的使用
  27. The use of vue.js component
  28. How to judge whether a linked list has links
  29. Element UI custom theme configuration
  30. Text image parallax effect HTML + CSS + JS
  31. Spring的nohttp宣言:消灭http://
  32. Vue3 intermediate guide - composition API
  33. Analysis of URL
  34. These 10 widgets that every developer must know
  35. Spring's nohttp Manifesto: eliminate http://
  36. Learn more about JS prototypes
  37. Refer to await to JS to write an await error handling
  38. A short article will directly let you understand what the event loop mechanism is
  39. Vue3 uses mitt for component communication
  40. Characteristics and thinking of ES6 symbol
  41. Two way linked list: I'm no longer one-way driving
  42. Vue event and form processing
  43. Reactive TraderCloud实时外汇开源交易平台
  44. Reactive tradercloud real time foreign exchange open source trading platform
  45. Node.js REST API的10个最佳实践
  46. Ten best practices of node.js rest API
  47. Fiddler advanced usage
  48. Process from Vue template to render
  49. Promise up (asynchronous or synchronous)
  50. Principle and implementation of promise
  51. Vs code plug in sharing - run code
  52. Vue practical notes (1) introduction of Ant Design
  53. Vue actual combat notes (2) introduction of element plus
  54. Introduction to webpack
  55. Webpack construction process
  56. Vue notes
  57. The experience and lessons of moving from ruby megalith architecture to go microservice
  58. Using leancloud to add artitalk module to hexo blog
  59. Implementation of chrome request filtering extension
  60. Detailed introduction of beer import declaration elements and label quarantine [import knowledge]