×
Community Blog An Introduction to RSocket: Servlet vs. RSocket

An Introduction to RSocket: Servlet vs. RSocket

This article explains some basic knowledge of RSocket by comparing Servlet and RSocket.

By Leijuan

This article explains some basic knowledge of RSocket by comparing Servlet and RSocket. Note: RSocket and Servlet are not similar products. Everyone is very familiar with Servlet, so the function comparison is relatively convenient.

Before reading this article, you need to familiarize yourself with Java. Kotlin may be involved, and C++ and Python (not required in this article) are also partially involved. It would also be better if you knew Spring Boot.

What Is Servlet?

The explanation from Wikipedia says, "Servlet, or Java Servlet, is a server-side program written in Java. Its main function is to browse and modify data interactively and generate dynamic Web content."

The code below is more helpful for Java programmers to understand this concept:

public abstract class HttpServlet extends Servlet {
    protected abstract void doGet(HttpServletRequest req,HttpServletResponse resp)
        throws ServletException, IOException;

    protected abstract void doPost(HttpServletRequest req,HttpServletResponse resp)
       throws ServletException, IOException;
}

Therefore, Servlet provides HTTP requests. After processing, it calls HTTP Response for output. Yes, that's it. Don't underestimate this class. Almost all the first Java classes of Servlet-compliant web frameworks start here, including Struts, Spring MVC, and Alibaba's internal WebX. Many developers write Web frameworks based on this class to solve different problems.

What Is RSocket?

rsocket.io explains, "RSocket is a binary protocol that provides four peer-to-peer interaction models by using asynchronous messages and runs in transport layers, such as TCP, WebSockets, and Aeron as byte streams."

You can have a basic understanding through this definition: binary protocol, asynchronous message, seven-layer protocol, and operation in TCP, WebSocket, and Aeron. The code below can explain this concept:

public interface RSocket extends Availability, Closeable {

  Mono<Payload> requestResponse(Payload payload);

  Mono<Void> fireAndForget(Payload payload);

  Flux<Payload> requestStream(Payload payload);

  Flux<Payload> requestChannel(Publisher<Payload> payloads);

  Mono<Void> metadataPush(Payload payload);

  default double availability() {
  return isDisposed() ? 0.0 : 1.0;
}

Four Models:

requestResponse, fireAndForget, requestStream, and requestChannel. They are the same as doGet and doPost.

Parameters:

Payload: As mentioned earlier, message-based communication means receiving and returning messages. Why isn't it called Message? Just regard them as synonyms for the time being. A message is composed of two parts: metadata and data. Metadata refers to routing information, such as the service to be called and the mime type of your data. Data refers to the values of called parameters and the results returned.

metadataPush:

It pushes metadata that can be told to the other party. You can define the content. If it is a cluster, I can give you the cluster information and let you connect to each working node.

availability:

This can be understood as a health check. If the value is 0, it indicates it is not available, which is very practical for load balancing. Servlet lacks this, so we have to add the Health URL, such as /ok.jsp :). Why isn't it a Boolean value? In my view, the double value can be used as the weight. For example, 1.0 indicates very good processing abilities, and 0.8 indicates average processing abilities.

Mono and Flux:

This is required by Reactive programming and improves the processing capability of the system through asynchronous means. There is an asynchronous keyword in the definition of RSocket. Mono and Flux are used to handle asynchronous operations.

Differences between Servlet and RSocket

The two are very similar. Servlet is a Java API specification based on the HTTP protocol, while RSocket is also an API specification (supporting multiple languages) based on the custom binary protocol. You can directly implement the interface and write code without caring about the details of the protocol. Then, the function will be ready. Here, I still want to introduce the major differences between the two.

Protocol Layer:

Servlet is based on HTTP, while RSocket is based on the custom protocol. In terms of standardization, HTTP does well. The custom binary protocol for RSocket provides excellent performance and is easy to parse. HTTP is very simple for HTTP 1.1 but a bit complicated for HTTP 2.0. Here, we can understand that RSocket focuses on high-performance communication, which is much better than HTTP. It is declared to be ten times better. Note: RSocket does not naturally have ultimate high performance. If you want to achieve ultimate high performance, you must optimize it according to your business scenarios.

Commands and Communication Mode:

HTTP commands include get, post, head, put, delete, and options. Servlet 2.0 adds stream support, but these commands are all designed for browsers rather than service communication. Moreover, they are all in request/response mode, so they are also called request commands. Others are not supported by Servlet 2.0, such as stream push, fireAndForget, and two-way communication. HTTP uses the request/response communication mode. This may be controversial because HTTP also has polling and websocket, but these designs are for attack and efficient communication, rather than the built-in communication mode.

message:

HTTP 1.1 is text-based communication, and 2.0 is message-based communication. What are the benefits of messages? The benefit is asynchronization. Each message must have an ID. After one message is sent, other messages can be sent without waiting for the first message to be returned immediately. Then, the returned message ID is used to match the sent message ID. If messages are not used, after the content is sent, it has to wait for the returned results to match before sending the next message. This is why many people complain and say www stands for World Wide Wait.

Reactive Programming Model:

RSocket is based on the Reactive programming model. For Java, especially Reactor and RxJava, Spring contributes a lot to RSocket, and RSocket Java SDK is based on Netty-Reactor. Therefore, the default interface is Reactor API. Asynchronization is challenging for programming. For example, callback, Future, and Promise are not friendly compared with the traditional programming model. Therefore, Reactive provides the Reactive programming model based on tradition and asynchronization, which is a consideration. If Functional Programming is acceptable, Reactive mode is no problem.

Peer-to-Peer Communication:

Our traditional understanding is the Client → Server mode. For example, write a Servlet to run on the server and then write a Servlet with JS to run on the browser so the server can call the browser in reverse. When the order status changes, you need to refresh the order details. However, RSocket knows nothing about this. Everyone is equal and can be on the server side. they can call each other's services. We will have a detailed Demo of this usage scenario later, such as providing services externally without listening ports and accessing internal services from the Internet in reverse mode. RSocket Broker is implemented based on peer-to-peer communication.

Singleton & Prototype Scopes:

Here, we use Singleton scope and Prototype scope of Spring to understand the difference between Servlet and RSocket. Singleton scope indicates that the JVM is unique, whereas Prototype scope indicates that the JVM needs to be created with each call. In analogy, classes of Servlet are basically Singleton, but it may be different for RSocket. The main reason is the peer-to-peer communication mentioned above. If you want to send a request to the other party of the connection, you need to hold the peer RSocket of the connection. Therefore, this handler can't be Singleton. If it's only unilateral communication, you don't have to care about setup payload, and it does not matter if the RSocket handler is Singleton.

There is also a small difference, which will not be introduced. In view of my ability, I may not understand it thoroughly enough and miss a major difference. After you understand and use it, you are welcome to give feedback. Let's use the following figure to demonstrate the differences between the two:

1

RSocket Demo

The Demo of RSocket is given below. There is no client → server communication model. Therefore, we use requester and responder for explanation. The roles are interchangeable. Requester can be used as responder. During the coding process, requester is changed to responder by default.

The responder code:

RSocketFactory.receive()
            .acceptor(new SocketAcceptor() {
                @Override
                public Mono<RSocket> accept(ConnectionSetupPayload setup, RSocket sendingSocket) {
                    return Mono.just(new RSocketHandlerImpl());
                }
            })
            .transport(TcpServerTransport.create("0.0.0.0", 42252))
            .start()
            .subscribe();

Responder is mainly represented by RSocketFactory.receive() to receive external connections. Next, you only need to implement it for acceptor through an RSocket interface. Here, let's take a look at the SocketAcceptor interface. Responder needs to verify whether requester can be connected. This is useful. For example, once the authentication passes and the connection is established, subsequent verification is not required for initial authentication. ConnectionSetupPayload is the data sent by requester to responder for connection creation. This is not available in Servlet. We will provide more practice in the future. The first article only verifies whether it can be connected.

The requester code:

RSocketFactory.connect()
                    .acceptor(new Function<RSocket, RSocket>() {
                        @Override
                        public RSocket apply(RSocket peerRsocket) {
                            return Mono.just(new RSocketHandlerImpl()) ;
                        }
                    })
                    .transport(TcpClientTransport.create("localhost", 42252))
                    .start()
                    .block();

RSocketFactory.connect() indicates that the target responder must be connected. There is also RSocket implementation for the acceptor to receive call requests from the other party. The best block() method is to wait synchronously for responder to return a response. This is necessary. For example, if the target service is down or does not exist, the application can quickly discover the problem by itself. However, in the case of load balance, we use Mono instead of block for automatic reconnection and new address pushing.

If Spring Boot is used, 1-2 Beans, SocketAcceptor, and RSocket Bean may be needed, and the rest are done by injection without writing too much duplicate code.The development of rsocket-spring-boot-starter is almost completed, so there is no need to worry about the complexity of the code.

0 0 0
Share on

Alibaba Cloud Community

873 posts | 198 followers

You may also like

Comments