1. 程式人生 > >[譯] Node.js 高效能和可擴充套件應用程式的最佳實踐 [第 2/3 部分]

[譯] Node.js 高效能和可擴充套件應用程式的最佳實踐 [第 2/3 部分]

第 2 章 —— 如何使您的 Node.js 應用程式安全擴充套件

上篇文章中,我們學會了如何無需憂慮程式碼,而水平擴充套件 Node.js 應用程式。本章中,我們將討論擴充套件時必須注意的事項,以便在擴充套件流程時防止錯誤發生。

從 DB 中分離應用程式例項

本章首先要講的不是程式碼,而是你的基礎架構

如果你希望應用程式能夠多主機擴充套件,則必須部署資料庫到一些獨立的主機,以便可以根據需要自由複製主機。

在同一臺機器上部署應用程式和資料庫可能很便宜並且用於開發目的,但絕對不建議用於生產環境,其中應用程式和資料庫必須能夠獨立擴充套件。這同樣適用於像 Redis 這樣的記憶體資料庫。

無狀態

如果您生成應用程式的多個例項,每個程序都有自己的記憶體空間。這意味著即使您在一臺機器上執行,當您在全域性變數中儲存某些值,或者更常見的是在記憶體中儲存會話時,如果負載均衡伺服器在下一個請求期間將您重定向到另一個程序,您將無法在那裡找到它。

這適用於會話資料和內部值,如任何型別的應用程式配置。

對於可在執行時更改的設定或配置,一種解決方案是將它們儲存在外部資料庫(磁碟或記憶體中)上,以使所有程序都可以訪問它們。

使用 JWT 進行無狀態身份驗證

身份驗證是開發無狀態應用程式時要考慮的首要問題之一。如果將會話儲存在記憶體中,它們將作用於該單個程序。

為了使工作正常,您應該將網路負載均衡伺服器配置為始終將同一使用者重定向到同一臺計算機,並將重定向到同一使用者的本地使用者始終重定向到同一程序(粘性會話)。

解決此問題的一個簡單方法是將會話的儲存策略設定為永續性,例如將它們儲存在 DB 中而不是 RAM 中。但是,如果您的應用程式檢查每個請求的會話資料,則每次 API 的呼叫都會有磁碟 I/O 操作,從效能的角度來看,這絕對不是好事。

更好,更快的解決方案(如果您的身份驗證框架支援它)是將會話儲存在像 Redis 這樣的記憶體資料庫中。Redis 例項通常位於應用程式例項外部,例如 DB 例項,但在記憶體中工作會更快。無論如何,在 RAM 中儲存會話會使您在併發會話數增加時需要更多記憶體。

如果您想採用更有效的無狀態身份驗證方法,可以檢視 JSON Web 令牌

JWT 背後的想法很簡單:當用戶登入時,伺服器生成一個令牌,該令牌本質上是包含有效負載的 JSON 物件的 base64 編碼,加上簽名獲得的雜湊,該負載具有伺服器擁有的金鑰。有效負載可以包含用於對使用者進行身份驗證和授權的資料,例如 userID 及其關聯的 ACL 角色。令牌被髮送回客戶端並由其用於驗證每個 API 請求。

當伺服器處理傳入請求時,它會獲取令牌的有效負載並使用其金鑰重新簽名。如果兩個簽名匹配,則可以認為有效載荷有效且不被改變,還可以識別使用者。

重要的是要記住 JWT 不提供任何形式的加密。有效負載僅在 base64 中編碼,並以明文形式傳送,因此如果您需要隱藏內容,則必須使用 SSL。

jwt.io 用的以下模式恢復了身份驗證過程:

在認證過程中,伺服器不需要訪問儲存在某處的會話資料,因此每個請求都可以由非常有效的方式由不同的程序或機器處理。RAM 中沒有儲存資料,也不需要執行儲存 I/O 操作,因此在擴充套件時這種方法非常有用。

儲存在 S3 上

使用多伺服器時,無法將使用者生成的資料直接儲存在檔案系統上,因為這些檔案只能由該伺服器本地的程序訪問。解決方案是將所有內容儲存在外部服務上,可能儲存在像 Amazon S3 這樣的專用服務上,並在資料庫中僅儲存指向該資源的絕對 URL。

然後,每個程序/機器都可以以相同的方式訪問該資源。

使用 Node.js 的官方 AWS sdk 非常簡單,您可以輕鬆地將服務整合到應用程式中。S3 非常便宜並且針對此目的進行了優化,在您的應用程式不是多程序的情況下也是一個不錯的選擇。

正確配置 WebSockets

如果您的應用程式使用 WebSockets 進行客戶端之間或客戶端與伺服器之間的實時互動,則需要連結後端例項,以便在連線到不同節點的客戶端之間正確傳播廣播或訊息。

Socket.io 庫為此提供了一個特殊的資料庫連線工具,稱為 socket.io-redis,它允許您使用 Redis pub-sub 功能連結伺服器例項。

為了使用多節點 socket.io 環境,您還需要配置協議為 “websockets”,因為長輪詢需要粘性會話才能工作。

下一步

在這篇簡短的文章中,我們已經看到了一些關於如何擴充套件 Node.js 應用程式需要注意的事情,這對於單節點環境也可以被視為良好的實踐。

在本系列的下一篇文章(也是最後一篇文章)中,我們介紹一些 Nodejs 的進階操作。你可以在這裡找到它。


如果這篇文章對你有用,請給我點贊吧!

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄