REST vs WebSockets

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membahas asas komunikasi pelayan pelanggan dan menerokainya melalui dua pilihan popular yang ada sekarang. Kami akan melihat bagaimana WebSocket, yang merupakan peserta baru, menentang pilihan HTTP RESTful yang lebih popular.

2. Asas Komunikasi Rangkaian

Sebelum kita menyelidiki perincian pilihan yang berbeza dan kelebihan dan kekurangannya, mari cepat menyegarkan landskap komunikasi rangkaian. Ini akan membantu meletakkan perkara dalam perspektif dan memahami perkara ini dengan lebih baik.

Komunikasi rangkaian dapat difahami dengan baik dari segi model Open Systems Interconnection (OSI).

Model OSI membahagikan sistem komunikasi kepada tujuh lapisan abstraksi:

Di bahagian atas model ini adalah lapisan Aplikasi yang menjadi minat kami dalam tutorial ini. Walau bagaimanapun, kita akan membincangkan beberapa aspek di empat lapisan teratas ketika kita membandingkan WebSocket dan HTTP RESTful.

Lapisan aplikasi paling dekat dengan pengguna akhir dan bertanggungjawab untuk berinteraksi dengan aplikasi yang mengambil bahagian dalam komunikasi. Ada beberapa protokol popular yang digunakan dalam lapisan ini seperti FTP, SMTP, SNMP, HTTP, dan WebSocket.

3. Menjelaskan WebSocket dan HTTP RESTful

Walaupun komunikasi boleh berlaku di antara sebilangan sistem, kami sangat berminat dengan komunikasi pelayan-pelanggan. Lebih khusus lagi, kami akan menumpukan pada komunikasi antara penyemak imbas web dan pelayan web. Ini adalah bingkai yang akan kami gunakan untuk membandingkan WebSocket dengan HTTP RESTful.

Tetapi sebelum kita melangkah lebih jauh, mengapa tidak cepat memahami apa itu!

3.1. Soket Web

Seperti definisi formal, WebSocket adalah protokol komunikasi yang menampilkan komunikasi dua arah penuh-dupleks melalui sambungan TCP yang berterusan. Sekarang, kami akan memahami setiap bahagian penyataan ini secara terperinci semasa kami meneruskannya.

WebSocket diseragamkan sebagai protokol komunikasi oleh IETF sebagai RFC 6455 pada tahun 2011. Sebilangan besar penyemak imbas web moden hari ini menyokong protokol WebSocket.

3.2. HTTP TERBAIK

Walaupun kita semua mengetahui HTTP kerana keberadaannya di internet, ia juga merupakan protokol komunikasi lapisan aplikasi. HTTP adalah protokol berdasarkan permintaan , sekali lagi kita akan memahami perkara ini dengan lebih baik dalam tutorial.

REST (Perwakilan Negeri Perwakilan) adalah gaya seni bina yang meletakkan sekumpulan kekangan pada HTTP untuk membuat perkhidmatan web.

4. Subprotokol WebSocket

Walaupun WebSocket mendefinisikan protokol untuk komunikasi dua arah antara klien dan pelayan, ia tidak meletakkan syarat pada mesej yang akan ditukar . Ini dibiarkan terbuka bagi pihak-pihak dalam komunikasi untuk menyetujui sebagai sebahagian daripada perundingan subprotokol.

Tidak mudah untuk mengembangkan subprotokol untuk aplikasi yang tidak remeh. Nasib baik, terdapat banyak subprotokol popular seperti STOMP yang tersedia untuk digunakan . STOMP bermaksud Protokol Pemesejan Berorientasikan Teks Sederhana dan berfungsi melalui WebSocket. Spring Boot mempunyai sokongan kelas pertama untuk STOMP, yang akan kami gunakan dalam tutorial kami.

5. Persediaan Pantas di Spring Boot

Tidak ada yang lebih baik daripada melihat contoh yang berfungsi. Oleh itu, kami akan membina kes penggunaan yang mudah di HTTP WebSocket dan RESTful untuk menerokainya lebih jauh dan kemudian membandingkannya. Mari buat komponen pelayan dan pelanggan yang mudah untuk kedua-duanya.

Kami akan membuat klien sederhana menggunakan JavaScript yang akan menghantar nama. Dan, kami akan membuat pelayan menggunakan Java yang akan bertindak balas dengan ucapan.

5.1. Soket Web

Untuk menggunakan WebSocket di Spring Boot, kami memerlukan starter yang sesuai:

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

Kami sekarang akan mengkonfigurasi titik akhir STOMP:

@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"); } }

Mari cepat tentukan pelayan WebSocket sederhana yang menerima nama dan bertindak balas dengan ucapan:

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

Akhirnya, mari membina klien untuk berkomunikasi dengan pelayan WebSocket ini. Oleh kerana kami menekankan komunikasi penyemak imbas ke pelayan, mari buat pelanggan dalam 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 + ""); }

Ini melengkapkan contoh kerja pelayan dan klien WebSocket kami. Terdapat halaman HTML di repositori kod yang menyediakan antara muka pengguna yang mudah untuk berinteraksi.

Walaupun ini hanya menggaru permukaan, WebSocket dengan Spring dapat digunakan untuk membina klien chat yang kompleks dan banyak lagi.

5.2. HTTP TERBAIK

Kami akan melalui penyediaan yang serupa untuk perkhidmatan RESTful sekarang. Perkhidmatan web ringkas kami akan menerima permintaan GET dengan nama dan membalas dengan ucapan.

Mari kita gunakan permulaan web Spring Boot kali ini:

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

Sekarang, kami akan menentukan titik akhir REST yang memanfaatkan sokongan anotasi kuat yang tersedia pada musim bunga:

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

Akhirnya, mari buat pelanggan dalam 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 + ""); }

Itu cukup banyak! Sekali lagi, terdapat halaman HTML di repositori kod untuk berfungsi dengan antara muka pengguna.

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.

Walaupun begitu, penggunaan perkhidmatan WebSocket dan RESTful melalui HTTP perlu diambil dari keperluan tersebut. Seperti tidak ada peluru perak, kita tidak boleh mengharapkan untuk memilih satu untuk menyelesaikan setiap masalah. Oleh itu, kita mesti menggunakan kebijaksanaan kita ditambah dengan pengetahuan dalam merancang model komunikasi yang cekap.

8. Kesimpulannya

Dalam tutorial ini, kami mengkaji asas komunikasi rangkaian dengan penekanan pada protokol lapisan aplikasi HTTP dan WebSocket. Kami melihat beberapa demonstrasi pantas WebSocket dan RESTful API melalui HTTP di Spring Boot.

Dan akhirnya, kami membandingkan ciri protokol HTTP dan WebSocket dan membincangkan secara ringkas bila perlu digunakan.

Seperti biasa, kod untuk contoh boleh didapati di GitHub.