REST vs WebSockets

1. Übersicht

In diesem Tutorial werden wir die Grundlagen der Client-Server-Kommunikation durchgehen und dies anhand von zwei gängigen Optionen untersuchen, die heute verfügbar sind. Wir werden sehen, wie sich WebSocket, ein Neuzugang, gegen die populärere Wahl von RESTful HTTP schlägt.

2. Grundlagen der Netzwerkkommunikation

Bevor wir uns eingehend mit den Details der verschiedenen Optionen und ihren Vor- und Nachteilen befassen, möchten wir kurz die Landschaft der Netzwerkkommunikation auffrischen. Dies wird dazu beitragen, die Dinge ins rechte Licht zu rücken und dies besser zu verstehen.

Die Netzwerkkommunikation kann am besten anhand des Open Systems Interconnection (OSI) -Modells verstanden werden.

Das OSI-Modell unterteilt das Kommunikationssystem in sieben Abstraktionsebenen:

An der Spitze dieses Modells befindet sich die Anwendungsschicht, die für uns in diesem Lernprogramm von Interesse ist. Wir werden jedoch einige Aspekte in den oberen vier Ebenen diskutieren, während wir WebSocket und RESTful HTTP vergleichen.

Die Anwendungsschicht ist dem Endbenutzer am nächsten und ist für die Schnittstelle zu den an der Kommunikation beteiligten Anwendungen verantwortlich. In dieser Schicht werden mehrere gängige Protokolle verwendet, z. B. FTP, SMTP, SNMP, HTTP und WebSocket.

3. Beschreiben von WebSocket und RESTful HTTP

Während die Kommunikation zwischen einer beliebigen Anzahl von Systemen stattfinden kann, sind wir besonders an der Client-Server-Kommunikation interessiert. Insbesondere konzentrieren wir uns auf die Kommunikation zwischen einem Webbrowser und einem Webserver. Dies ist der Frame, mit dem wir WebSocket mit RESTful HTTP vergleichen.

Aber bevor wir fortfahren, warum nicht schnell verstehen, was sie sind!

3.1. WebSockets

Wie die formale Definition lautet , ist WebSocket ein Kommunikationsprotokoll, das bidirektionale Vollduplex-Kommunikation über eine dauerhafte TCP-Verbindung bietet. Jetzt werden wir jeden Teil dieser Aussage im weiteren Verlauf im Detail verstehen.

WebSocket wurde 2011 von der IETF als RFC 6455 als Kommunikationsprotokoll standardisiert. Die meisten modernen Webbrowser unterstützen heute das WebSocket-Protokoll.

3.2. RESTful HTTP

Obwohl wir alle HTTP aufgrund seiner allgegenwärtigen Präsenz im Internet kennen, handelt es sich auch um ein Kommunikationsprotokoll auf Anwendungsebene. HTTP ist ein Request-Response-basiertes Protokoll . Wir werden dies später in diesem Tutorial besser verstehen.

REST (Representational State Transfer) ist ein Architekturstil, der HTTP eine Reihe von Einschränkungen beim Erstellen von Webdiensten auferlegt.

4. WebSocket-Unterprotokoll

Während WebSocket ein Protokoll für die bidirektionale Kommunikation zwischen Client und Server definiert, stellt es keine Bedingung für die auszutauschende Nachricht . Dies bleibt den Parteien in der Mitteilung offen, um im Rahmen der Unterprotokollverhandlung zuzustimmen.

Es ist nicht bequem, ein Unterprotokoll für nicht triviale Anwendungen zu entwickeln. Glücklicherweise stehen viele beliebte Unterprotokolle wie STOMP zur Verfügung . STOMP steht für Simple Text Oriented Messaging Protocol und funktioniert über WebSocket. Spring Boot bietet erstklassige Unterstützung für STOMP, die wir in unserem Tutorial verwenden werden.

5. Schnelleinrichtung im Spring Boot

Es gibt nichts Besseres als ein funktionierendes Beispiel zu sehen. Daher werden wir einfache Anwendungsfälle sowohl in WebSocket als auch in RESTful HTTP erstellen, um sie weiter zu untersuchen und sie dann zu vergleichen. Lassen Sie uns eine einfache Server- und Client-Komponente für beide erstellen.

Wir erstellen einen einfachen Client mit JavaScript, der einen Namen sendet. Und wir werden einen Server mit Java erstellen, der mit einer Begrüßung antwortet.

5.1. WebSocket

Um WebSocket in Spring Boot verwenden zu können, benötigen wir den entsprechenden Starter:

 org.springframework.boot spring-boot-starter-websocket 

Wir werden jetzt die STOMP-Endpunkte konfigurieren:

@Configuration @EnableWebSocketMessageBroker public class WebSocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws"); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.setApplicationDestinationPrefixes("/app"); config.enableSimpleBroker("/topic"); } }

Definieren wir schnell einen einfachen WebSocket-Server, der einen Namen akzeptiert und mit einer Begrüßung antwortet:

@Controller public class WebSocketController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(Message message) throws Exception { return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); } }

Lassen Sie uns abschließend den Client für die Kommunikation mit diesem WebSocket-Server erstellen. Da wir uns auf die Kommunikation zwischen Browser und Server konzentrieren, erstellen wir einen Client in JavaScript:

var stompClient = null; function connect() { stompClient = Stomp.client('ws://localhost:8080/ws'); stompClient.connect({}, function (frame) { stompClient.subscribe('/topic/greetings', function (response) { showGreeting(JSON.parse(response.body).content); }); }); } function sendName() { stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); } function showGreeting(message) { $("#greetings").append("" + message + ""); }

Dies vervollständigt unser Arbeitsbeispiel für einen WebSocket-Server und -Client. Im Code-Repository befindet sich eine HTML-Seite, die eine einfache Benutzeroberfläche für die Interaktion bietet.

Während dies nur die Oberfläche zerkratzt, kann WebSocket mit Spring verwendet werden, um komplexe Chat-Clients und mehr zu erstellen.

5.2. RESTful HTTP

Wir werden jetzt eine ähnliche Einrichtung für den RESTful-Service durchlaufen. Unser einfacher Webservice akzeptiert eine GET-Anfrage mit einem Namen und antwortet mit einer Begrüßung.

Verwenden wir diesmal stattdessen den Webstarter von Spring Boot:

 org.springframework.boot spring-boot-starter-web 

Jetzt definieren wir einen REST-Endpunkt, der die leistungsstarke Annotation-Unterstützung nutzt, die im Frühjahr verfügbar ist:

@RestController @RequestMapping(path = "/rest") public class RestAPIController { @GetMapping(path="/{name}", produces = "application/json") public String getGreeting(@PathVariable("name") String name) { return "{\"greeting\" : \"Hello, " + name + "!\"}"; } }

Zuletzt erstellen wir einen Client in JavaScript:

var request = new XMLHttpRequest() function sendName() { request.open('GET', '//localhost:8080/rest/'+$("#name").val(), true) request.onload = function () { var data = JSON.parse(this.response) showGreeting(data.greeting) } request.send() } function showGreeting(message) { $("#greetings").append("" + message + ""); }

Das wars so ziemlich! Wieder gibt es eine HTML-Seite im Code-Repository, um mit einer Benutzeroberfläche zu arbeiten.

Although profound in its simplicity, defining production grade REST API can be much more extensive task!

6. Comparison of WebSocket and RESTful HTTP

Having created minimal, but working, examples of WebSocket and RESTful HTTP, we're now ready to understand how do they fare against each other. We'll examine this against several criteria in the next sub-sections.

It is important to note that while we can directly compare HTTP and WebSocket as they are both application layer protocols, it's not natural to compare REST against WebSocket. As we saw earlier REST is an architectural style which leverages HTTP for communication.

Hence our comparison to WebSocket will mostly be regarding the capabilities, or lack thereof, in HTTP.

6.1. URL Scheme

A URL defines the unique location of a web resource and mechanism to retrieve it. In a client-server communication, more often than not we're looking to get static or dynamic resources through their associated URL.

We're all familiar with the HTTP URL scheme:

//localhost:8080/rest

WebSocket URL scheme is not much different either:

ws://localhost:8080/ws

At the outset, the only difference seems to be the characters before the colon, but it abstracts a lot which happens under the hood. Let's explore further.

6.2. Handshake

Handshakerefers to the automatic way of negotiating communication protocol between communicating parties. HTTP is a stateless protocol and works in a request-response mechanism. On every HTTP request, a TCP connection is established with the server over the socket.

The client then waits until the server responds with the resource or an error. The next request from the client repeats everything as if the previous request never happened:

WebSocket works very differently compared to HTTP and starts with a handshake before actual communication.

Let's see what comprise a WebSocket handshake:

In case of WebSocket, the client initiates a Protocol Handshake request in HTTP and then waits until the server responds accepting an upgrade to WebSocket from HTTP.

Of course, since Protocol Handshake happens over HTTP, it follows the sequence from the previous diagram. But once the connection is established, from there on client and server switches over to WebSocket for further communication.

6.3. Connection

As we saw in the previous subsection, one stark difference between WebSocket and HTTP is that WebSocket works on a persistent TCP connection while HTTP creates a new TCP connection for every request.

Now obviously creating new TCP connection for every request is not very performant and HTTP has not been unaware of this. In fact, as part of HTTP/1.1, persistent connections were introduced to alleviate this shortcoming of HTTP.

Nevertheless, WebSocket has been designed from the ground up to work with persistent TCP connections.

6.4. Communication

The benefit of WebSocket over HTTP is a specific scenario that arises from the fact that the client can server can communicate in ways which were not possible with good old HTTP.

For instance, in HTTP, usually the client sends that request, and then the server responds with requested data. There is no generic way for the server to communicate with the client on its own. Of course, patterns and solutions have been devised to circumvent this like Server-Sent Events (SSE), but these were not completely natural.

With WebSocket, working over persistent TCP communication, it's possible for server and client both to send data independent of each other, and in fact, to many communicating parties! This is referred to as bi-directional communication.

Another interesting feature of WebSocket communication is that it's full-duplex. Now while this term may sound esoteric; it simply means that both server and client can send data simultaneously. Compare this with what happens in HTTP where the server has to wait until it receives the request in full before it can respond with data.

While the benefit of bi-directional and full-duplex communication may not be apparent immediately. we'll see some of the use-cases where they unlock some real power.

6.5. Security

Last but not least, both HTTP and WebSocket leverage the benefits of TLS for security. While HTTP offers https as part of their URL scheme to use this, WebSocket has wss as part of their URL scheme for the same effect.

So the secured version of URLs from the previous subsection should look like:

//localhost:443/rest wss://localhost:443/ws

Securing either a RESTful service or a WebSocket communication is a subject of much depth and can not be covered here. For now, let's just say that both are adequately supported in this regard.

6.6. Performance

We must understand that WebSocket is a stateful protocol where communication happens over a dedicated TCP connection. On the other hand, HTTP is inherently a stateless protocol. This has an impact on how these will perform with the load but that really depends on the use case.

Since communication over WebSocket happens over a reusable TCP connection, the overhead per message is lower compared to HTTP. Hence it can reach higher throughput per server. But there is a limit to which a single server can scale and that is where WebSocket has issues. It's not easy to horizontally scale applications with WebSockets.

This is where HTTP shines. With HTTP each new request can potentially land on any server. This implies that to increase overall throughput we can easily add more servers. This should potentially have no impact on the application running with HTTP.

Obviously an application may itself need state and session stickiness which can make it easier said than done.

7. Where Should We Use Them?

Now, we have seen enough of RESTful service over HTTP and simple communication over WebSocket to form our opinion around them. But where should we use what?

It's important to remember that while WebSocket has emerged out of shortcomings in HTTP, it's not, in fact, a replacement of HTTP. So they both have their place and their uses. Let's quickly understand how can we make a decision.

For the bulk of the scenario where occasional communication is required with the server like getting the record of an employee, it's still sensible to use REST service over HTTP/S. But for newer client-side applications like a stock-price application which requires real-time updates from the server, it's much convenient to leverage WebSocket.

Generalizing, WebSocket is more suitable for cases where a push-based and real-time communication defines the requirement more appropriately. Additionally, WebSocket works well for scenarios where a message needs to be pushed to multiple clients simultaneously. These are the cases where client and server communication over RESTful services will find it difficult if not prohibitive.

Die Verwendung von WebSocket- und RESTful-Diensten über HTTP muss jedoch aus den Anforderungen abgeleitet werden. Da es keine Silberkugeln gibt, können wir nicht einfach erwarten, eine auszuwählen, um jedes Problem zu lösen. Daher müssen wir unsere Weisheit und unser Wissen nutzen, um ein effizientes Kommunikationsmodell zu entwerfen.

8. Fazit

In diesem Tutorial haben wir die Grundlagen der Netzwerkkommunikation mit Schwerpunkt auf den Protokollen der Anwendungsschicht HTTP und WebSocket besprochen. Wir haben im Spring Boot einige kurze Demonstrationen von WebSocket und RESTful API über HTTP gesehen.

Schließlich haben wir die Funktionen der HTTP- und WebSocket-Protokolle verglichen und kurz erläutert, wann sie verwendet werden sollen.

Wie immer ist der Code für die Beispiele auf GitHub verfügbar.