? ? ? ? 聊天是最典型的多用戶實(shí)時(shí)交互的應(yīng)用。從IRC開始,有許多開源或者不開源的協(xié)議都運(yùn)行在非標(biāo)準(zhǔn)端口上,而現(xiàn)在,使用 Node.js 則可以解決這些問題——在標(biāo)準(zhǔn)的80端口運(yùn)行 WebSockets。
聊天應(yīng)用程序是最能體現(xiàn) Node.js 優(yōu)點(diǎn)的例子:輕量級(jí)、高流量并且能良好的應(yīng)對(duì)跨平臺(tái)設(shè)備上運(yùn)行密集型數(shù)據(jù)(雖然計(jì)算能力低)。同時(shí),聊天也是一個(gè)非常值得學(xué)習(xí)的用例,因?yàn)樗芎?jiǎn)單,并且涵蓋了目前為止一個(gè)典型的 Node.js 會(huì)用到的大部分解決方案。
在最簡(jiǎn)單的情況下,我們布置了一個(gè)聊天室在我們的網(wǎng)站上,用戶可以在上面發(fā)消息,當(dāng)然是一對(duì)多的形式。例如,假設(shè)總共有三個(gè)人連接到我們的網(wǎng)站上。
在服務(wù)端這邊, 我們有一個(gè)使用 Express.js 搭建的簡(jiǎn)單站點(diǎn),該站點(diǎn)實(shí)現(xiàn)了兩件事 1) 處理路徑為 ‘/’ 的GET請(qǐng)求時(shí),下發(fā)包括一個(gè)留言板以及一個(gè)發(fā)送信息的 ‘發(fā)送’ 按鈕的頁(yè)面 2) 一個(gè)監(jiān)聽客戶端發(fā)送新消息的 websockets 服務(wù)。
在客戶端這邊,我們有一個(gè) HTML 頁(yè)面,上面有個(gè)兩個(gè) js 方法,一個(gè)是用于觸發(fā)事件的 “發(fā)送” 按鈕,這會(huì)把把輸入的消息通過 webscoket 發(fā)送,另一個(gè)方法是用 webscoket 在客戶端上監(jiān)聽服務(wù)端來的推送(例如,其他用戶發(fā)送的消息)。
當(dāng)有一個(gè)客戶端發(fā)送消息的時(shí)候,發(fā)生的事情是:
瀏覽器上,點(diǎn)擊發(fā)送按鈕觸發(fā)了 js 函數(shù),將輸入框中的文字通過 websocket 消息發(fā)送到服務(wù)器的 websocket 客戶端(頁(yè)面初始化加載的時(shí)候連接的)。
服務(wù)端的 websocket 組件收到 消息,然后通過廣播方法轉(zhuǎn)發(fā)到其他所有連接的客戶端。
通過頁(yè)面上運(yùn)行的 websocket 客戶端組件,所有的客戶端都能收到這條推送的新消息。接著 js 處理函數(shù)可以把這個(gè)消息添加到文字框內(nèi)。
這是一個(gè)最簡(jiǎn)單的例子。如果要更好的解決方案,你可以使用 Redis 數(shù)據(jù)庫(kù)做一個(gè)簡(jiǎn)單的緩存。在一個(gè)更高級(jí)的解決方案中,你可能需要一個(gè)消息路由來專門處理消息隊(duì)列,并且需要一個(gè)更強(qiáng)健的發(fā)送機(jī)制,比如發(fā)送的時(shí)候覆蓋上暫時(shí)離線的用戶或者為離線的注冊(cè)用戶存儲(chǔ)尚未接收的消息等等。但是不論你做了怎么樣的改進(jìn),Node.js 都將遵循一個(gè)基本原則:響應(yīng)事件,處理多個(gè)并發(fā)連接,并保持流動(dòng)性的用戶體驗(yàn)。