知識庫 / REST RSS 訂閱

REST 與 WebSockets

REST
HongKong
4
03:51 AM · Dec 06 ,2025

1. 概述

本教程將介紹客户端-服務器通信的基礎知識,並通過兩種流行的選項進行探索。我們將對比 WebSocket(作為新興技術)與更流行的 RESTful HTTP。

2. 網絡通信基礎

在深入探討不同選項及其優缺點之前,讓我們快速回顧一下網絡通信的概況。這將有助於我們更好地理解相關內容。

網絡通信可以從開放系統互連(OSI)模型來理解。

OSI 模型將通信系統劃分為七層抽象層:

在模型頂層,應用程序層是我們本教程中的重點。但是,在探討前四層時,我們會比較 WebSocket 和 RESTful HTTP,並討論一些相關方面。

應用程序層是與參與通信的應用程序進行交互的最接近用户的一層,並使用諸如 FTP、SMTP、SNMP、HTTP 和 WebSocket 等多種流行協議。

3. 描述 WebSocket 和 RESTful HTTP

雖然系統之間可以進行通信,但我們特別關注客户端與服務器之間的通信。更具體地説,我們將重點關注瀏覽器與 Web 服務器之間的通信。我們將使用這個框架來比較 WebSocket 與 RESTful HTTP。

但在繼續之前,我們先快速瞭解一下它們是什麼!

3.1. WebSockets

如正式定義所述,WebSocket 是一種具有雙向、全雙工通信功能的協議,它在持久的 TCP 連接上運行。 我們將逐步深入理解該聲明中的每個部分。

WebSocket 協議由 IETF 標準化,具體定義為 RFC 6455 於 2011 年發佈。 如今,大多數現代 Web 瀏覽器都支持 WebSocket 協議。

3.2. RESTful HTTP

雖然我們都瞭解 HTTP 由於其在互聯網上的無處不在而聞名,它也是一種應用層通信協議。 HTTP 是一種基於請求-響應的協議,稍後我們將更好地理解這一點。

REST (表徵狀態轉移) 是一種架構風格,它對 HTTP 施加了一組約束,以創建 Web 服務。

4. WebSocket 子協議

雖然 WebSocket 定義了客户端與服務器之間雙向通信的協議,但它對交換的消息沒有任何限制。 這留給通信各方在子協議協商中達成一致。

為非簡單的應用程序開發子協議並不方便。 幸運的是,STOMP 這樣的許多流行子協議可用。 STOMP 代表 Simple Text Oriented Messaging Protocol,它在 WebSocket 上工作。 Spring Boot 對 STOMP 提供了第一類的支持,我們將在此教程中使用它。

5. Spring Boot 快速搭建

沒有什麼比看到可運行的示例更好了。因此,我們將使用 WebSocket 和 RESTful HTTP 構建簡單的用例,以便更深入地探索它們,然後進行比較。讓我們為兩者創建一個簡單的服務器和客户端組件。

我們將使用 JavaScript 創建一個簡單的客户端,該客户端將發送一個名稱。同時,我們將使用 Java 創建一個服務器,該服務器將用問候語進行響應。

5.1. WebSocket

為了在 Spring Boot 中使用 WebSocket,我們需要 合適的 starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

我們現在將配置 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");
    }
}

讓我們快速定義一個簡單的 WebSocket 服務器,該服務器接受一個名稱並返回一個問候語:

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

最後,讓我們構建客户端與此 WebSocket 服務器進行通信。鑑於我們強調瀏覽器與服務器之間的通信,讓我們用 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("<tr><td>" + message + "</td></tr>");
}

本示例完成了 WebSocket 服務器和客户端的工作演示。代碼倉庫中包含一個 HTML 頁面,提供了一個簡單的用户界面,用於與之交互。

雖然這只是一個初步的介紹,但 WebSocket 與 Spring 可以用於構建複雜的聊天客户端和其他應用。

5.2. RESTful HTTP

我們將現在進行類似的配置,用於 RESTful 服務。 我們的簡單 Web 服務將接受一個 GET 請求,其中包含一個名稱,並以問候語進行響應。

讓我們這次使用 Spring Boot 的 Web Starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

現在,我們將定義一個利用 Spring 中強大的註解支持的 REST 端點:

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

最後,讓我們創建一個 JavaScript 客户端:

var request = new XMLHttpRequest()
function sendName() {
    request.open('GET', 'http://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("<tr><td>" + message + "</td></tr>");
}

基本上就是這樣! 再次強調,有一個 HTML 頁面存儲在代碼倉庫中,用於與用户界面交互。

儘管其簡潔性令人驚歎,但定義生產級別的 REST API 卻可能是一項非常複雜的工作!

6. WebSocket 與 RESTful HTTP 的比較

鑑於我們已經創建了最小但可運行的 WebSocket 和 RESTful HTTP 示例,現在我們可以瞭解它們之間的差異。我們將從下一部分子章節中考察多個標準。

需要注意的是,雖然我們可以直接比較 HTTP 和 WebSocket,因為它們都是應用層協議,但將 REST 與 WebSocket 進行比較並不自然。正如我們之前所見,REST 是一種架構風格,它利用 HTTP 進行通信。

因此,我們的比較將主要集中在 HTTP 的能力(或缺乏)方面

6.1 URL 方案

URL 定義了網絡資源的唯一位置以及檢索它的機制。 在客户端-服務器通信中,我們通常通過其關聯的 URL 獲取靜態或動態資源。

我們都熟悉 HTTP URL 方案:

http://localhost:8080/rest

WebSocket URL 方案與 HTTP 相比並沒有太多不同:

ws://localhost:8080/ws

開篇來看,似乎唯一的區別在於冒號之前的字符,但它抽象了大量的底層操作。我們來進一步探索。

6.2. Handshake

Handshake

WebSocket 與 HTTP 相比,工作方式非常不同,它在實際通信之前會進行握手。

以下是 WebSocket 握手所包含的內容:

在 WebSocket 中,https://localhost:443/rest wss://localhost:443/ws

保障 RESTful 服務或 WebSocket 通信,是一個涉及深度的課題,此處無法詳盡。目前,我們僅説明兩者在相關方面均得到充分支持。

6.6. 性能

我們必須理解 WebSocket 是一種狀態化協議,通信發生在專用 TCP 連接上。相比之下,HTTP 本質上是一種無狀態協議。這會影響它們在高負載下的性能,但具體取決於用例。

由於 WebSocket 通信發生在可重用 TCP 連接上,因此每條消息的開銷低於 HTTP。因此,它可以達到更高的吞吐量。但單個服務器可以擴展的上限是 WebSocket 的問題。難以使用 WebSockets 水平擴展應用程序。

HTTP 在這裏表現出色。使用 HTTP,每個新請求都可能到達任何服務器。這意味着為了提高整體吞吐量,我們可以輕鬆地添加更多服務器。這可能不會對使用 HTTP 的應用程序產生影響。

當然,應用程序本身可能需要狀態和會話粘性,這可能會比説起來容易做起來難。

7. 應該在什麼情況下使用它們?

現在,我們已經充分了解了通過 HTTP 進行的 RESTful 服務以及通過 WebSocket 進行的簡單通信,從而對它們有了自己的看法。但我們應該在什麼情況下使用它們呢?

重要的是要記住,雖然 WebSocket 已經從 HTTP 的不足之處中發展而來,但它實際上並不是 HTTP 的替代品。因此,它們都有各自的位置和用途。讓我們快速瞭解如何做出決定。

對於大多數場景,當需要與服務器進行偶爾的通信,例如獲取員工記錄時,仍然明智地使用 HTTP/S 上的 RESTful 服務。但是,對於像股票價格應用程序這樣的新客户端應用程序,這些應用程序需要從服務器獲取實時更新,利用 WebSocket 更加方便。

總的來説,WebSocket 更適合在推送到客户端的基於實時通信的需求定義更合適的情況下。此外,WebSocket 在需要同時向多個客户端推送消息的場景中也表現良好。這些是客户端和服務器通過 RESTful 服務難以甚至無法實現的場景。

儘管如此,WebSocket 和 HTTP 上的 RESTful 服務的使用必須基於需求。就像沒有萬能的解決方案一樣,我們不能只是選擇一個來解決所有問題。因此,我們必須結合我們的智慧和知識來設計高效的通信模型。

8. 結論

在本教程中,我們回顧了網絡通信的基礎知識,重點介紹了應用層協議 HTTP 和 WebSocket。我們還演示了 WebSocket 和 HTTP 上的 RESTful API 在 Spring Boot 中的一些快速示例。

最後,我們比較了 HTTP 和 WebSocket 協議的功能,並簡要討論了何時使用每種協議。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.