1. 程式人生 > >十萬同時線上使用者,需要多少記憶體?——Newbe.Claptrap 框架水平擴充套件實驗

十萬同時線上使用者,需要多少記憶體?——Newbe.Claptrap 框架水平擴充套件實驗

Newbe.Claptrap 專案是筆者正在構建以反應式Actor模式事件溯源為理論基礎的一套服務端開發框架。本篇我們將來了解一下框架在水平擴充套件方面的能力。

前情提要

時隔許久,今日我們再次見面。首先介紹一下過往的專案情況:

第一次接觸本框架的讀者,可以先點選此處閱讀本框架相關的基礎理論和工作原理。

日前,我們也編寫了一些預熱文章和工具,讀者可以通過以下連結進行了解:

  • 談反應式程式設計在服務端中的應用,資料庫操作優化,從 20 秒到 0.5 秒
  • docker-mcr 助您全速下載 dotnet 映象
  • Newbe.Claptrap 專案週報 1 - 還沒輪影,先用輪跑

今日主題

今天,我們來做一套實驗預演,來驗證 Newbe.Claptrap 框架,如何通過水平擴充套件的形式來適應逐漸增長的同時線上使用者數。

由於此次實驗涉及的內容很多,因此筆者將內容進行了歸類,讀者可以按照自己的興趣閱讀相關的章節:

  • 業務需求說明
  • 呼叫時序關係
  • 物理結構設計
  • 實際測試資料
  • 原始碼構建說明
  • 常見問題解答

業務需求說明

先看看今天要實現的業務場景:

  • 使用者通過 API 登入後生成一個 JWT token
  • 使用者呼叫 API 時驗證 JWT token 的有效性
  • 沒有使用常規的 JWS 公私鑰方式進行 JWT token 頒發,而是為每個使用者單獨使用 secret 進行雜湊驗證
  • 驗證看不同的線上使用者需要消耗的記憶體情況
  • 使用者登入到生成 token 所消耗時間不得超過 200 ms
  • tokn 的驗證耗時不得超過 10 ms

吹牛先打草稿

筆者沒有搜尋到於 “線上使用者數” 直接相關的理論定義,因此,為了避免各位的理解存在差異。筆者先按照自己的理解來點明:線上使用者數到底意味著什麼樣的技術要求?

未線上使用者若上線,不應該受到已線上使用者數的影響

如果一個使用者登入上線需要消耗 100 ms。那麼不論當前線上的使用者數是十人還是百萬人。這個登入上線所消耗的時間都不會明顯的超過 100 ms。

當然,有限的物理硬體肯定會使得,當線上使用者數超過一個閾值(例如兩百萬)時,新使用者登入上線會變慢甚至出錯。

但是,增加物理機器就能提高這個閾值,我們就可以認為水平擴充套件設計是成功的。

對於任意一個已線上使用者,得到的系統性能反饋應當相同

例如已線上的使用者查詢自己的訂單詳情,需要消耗 100 ms。那麼當前任何一個使用者進行訂單查詢的平均消耗都應該穩定在 100 ms。

當然,這裡需要排除類似於 “搶購” 這種高集中效能問題。此處主要還是討論日常穩定的容量增加。(我們以後會另外討論 “搶購” 這種問題)

具體一點可以這樣理解。假設我們做的是一個雲筆記產品。

那麼,如果增加物理機器就能增加同時使用雲筆記產品的使用者數,而且不犧牲任何一個使用者的效能體驗,我們就認為水平擴充套件設計是成功的。

在此次的實驗中,若使用者已經登入,則驗證 JWT 有效性的時長大約為 0.5 ms。

呼叫時序關係

簡要說明:

  1. 客戶端發起登入請求將會逐層傳達到 UserGrain 中
  2. UserGrain 將會在內部啟用一個 Claptrap 來進行維持 UserGrain 中的狀態資料。包括使用者名稱、密碼和用於 JWT 簽名的 Secret。
  3. 隨後的生成 JWT 生成和驗證都將直接使用 UserGrain 中的資料。由於 UserGrain 中的資料是在一段時間內是 “快取” 在記憶體中的。所以之後的 JWT 生成和驗證將非常快速。實測約為 0.5 ms。

物理結構設計

如上圖所示,便是此次進行測試的物理元件:

名稱說明
WebAPI 公開給外部呼叫 WebAPI 介面。提供登入和驗證 token 的介面。
Orleans Cluster 託管 Grain 的核心程序.
Orleans Gateway 於 Orleans Cluster 基本相同,但是 WebAPI 只能與 Gateway 進行通訊
Orleans Dashboard 於 Orleans Gateway 基本相同,但增加了 Dashboard 的展示,以檢視整個 Orleans 叢集的情況
Consul 用於 Orleans 叢集的叢集發現和維護
Claptrap DB 用於儲存 Newbe.Claptrap 框架的事件和狀態資料
Influx DB & Grafana 用於監控 Newbe.Claptrap 相關的效能指標資料

此次實驗的 Orleans 叢集節點的數量實際上是 Cluster + Gateway + Dashboard 的總數。以上的劃分實際上是由於功能設定的不同而進行的區分。

此次測試 “水平擴充套件” 特性的物理節點主要是 Orleans Cluster 和 Orleans Gateway 兩個部分。將會分別測試以下這些情況的記憶體使用情況。

Orleans DashboardOrleans GatewayOrleans Cluster
1 0 0
1 1 1
1 3 5

此次實驗採用的是 Windows Docker Desktop 結合 WSL 2 進行的部署測試。

以上的物理結構實際上是按照最為此次實驗最為複雜的情況設計的。實際上,如果業務場景足夠簡單,該物理結構可以進行裁剪。詳細可以檢視下文 “常見問題解答” 中的說明。

實際測試資料

以下,分別對不同的叢集規模和使用者數量進行測試

0 Gateway 0 Cluster

預設情況下,剛剛啟動 Dashboard 節點時,通過 portainer 可以檢視 container 佔用的記憶體約為 200 MB 左右,如下圖所示:

通過測試控制檯,向 WebAPI 發出 30,000 次請求。每批 100 個請求,分批發送。

經過約兩分鐘的等待後,再次檢視記憶體情況,約為 9.2 GB,如下圖所示:

因此,我們簡單的估算每個線上使用者需要消耗的記憶體情況約為 (9.2*1024-200)/30000 = 0.3 MB。

另外,可以檢視一些輔助資料:

CPU 使用情況

網路吞吐量

Orleans Dashboard 情況。左上角的 TOTAL ACTIVATIONS 中 30,000 即表示當前記憶體中存在的 UserGrain 數量,另外的 3 個為 Dashboard 使用的 Grain。

Grafana 中檢視 Newbe.Claptrap 的事件平均處理時長約為 100-600 ms。此次測試的主要是記憶體情況,處理時長的採集時間為 30s 一次,因此樣本數並不多。關於處理時長我們將在後續的文章中進行詳細測試。

Grafana 中檢視 Newbe.Claptrap 的事件的儲存花費的平均時長約為 50-200 ms。事件的儲存時長是事件處理的主要部分。

Grafana 中檢視 Newbe.Claptrap 的事件已處理總數。一種登入了三萬次,因此事件總數也是三萬。

1 Gateway 1 Cluster

接下來,我們測試額外增加兩個節點進行測試。

還是再提一下,Orleans 叢集節點的數量實際上是 Cluster + Gateway + Dashboard 的總數。因此,對比上一個測試,該測試的節點數為 3。

測試得到的記憶體使用情況如下:

使用者數節點平均記憶體記憶體總佔用
10000 1.8 GB 1.8*3 = 5.4 GB
20000 3.3 GB 3.3*3 = 9.9 GB
30000 4.9 GB 4.9*3 = 14.7 GB

那麼,以三萬使用者為例,平均每個使用者佔用的記憶體約為 (14.7*1024-200*3)/30000 = 0.48 MB

為什麼節點數增加了,平均消耗記憶體上升了呢?筆者推測,沒有進行過驗證:節點增加,實際上節點之間的通訊還需要消耗額外的記憶體,因此平均來說有所增加。

3 Gateway 5 Cluster

我們再次增加節點。總結點數為 1 (dashboard) + 3 (cluster) + 5 (gateway) = 9 節點

測試得到的記憶體使用情況如下:

使用者數節點平均記憶體記憶體總佔用
20000 1.6 GB 3.3*9 = 14.4 GB
30000 2 GB 4.9*9 = 18 GB

那麼,以三萬使用者為例,平均每個使用者佔用的記憶體約為 (18*1024-200*9)/30000 = 0.55 MB

十萬使用者究竟要多少記憶體?

以上所有的測試都是以三萬為使用者數進行的測試,這是一個特殊的數字。因為繼續增加使用者數的話,記憶體將會超出測試機的記憶體餘量。(求贊助兩條 16G)

如果繼續增加使用者數,將會開始使用作業系統的虛擬記憶體。雖然可以執行,但是執行效率會降低。原來登入可能只需要 100 ms。使用到虛擬記憶體的使用者則需要 2 s。

因此,速度降低的情況下,在驗證需要多少記憶體意義可能不大。

但是,這不意味著不能夠繼續登入,以下便是 1+1+1 的情況下,十萬使用者全部登入後的情況。(有十萬使用者同時線上,加點記憶體吧,不差錢了。)

原始碼構建說明

此次測試的程式碼均可以在文末的樣例程式碼庫中找到。為了方便讀者自行實驗,主要採用的是 docker-compose 進行構建和部署。

因此對於測試機的唯一環境需求就是要正確的安裝好 Docker Desktop 。

可以從以下任一地址獲取最新的樣例程式碼:

  • https://github.com/newbe36524/Newbe.Claptrap.Examples
  • https://gitee.com/yks/Newbe.Claptrap.Examples

快速啟動

使用控制檯進入 src/Newbe.Claptrap.Auth/LocalCluster 資料夾。執行以下命令便可以在本地啟動所有的元件:

1
docker-compose up -d

途中需要拉取一些託管於 Dockerhub 上的公共映象,請確保本地已經正確配置了相關的加速器,以便您可以快速構建。可以參看這篇文件進行設定

成功啟動之後可以通過 docker ps 檢視到所有的元件。

1
2
3
4
5
6
7
8
9
10
11
12
13
PS>docker ps
CONTAINER ID        IMAGE                                                                            COMMAND                  CREATED             STATUS              PORTS                                                                                                                              NAMES
66470e5393e2        registry.cn-hangzhou.aliyuncs.com/newbe36524/newbe-claptrap-auth-webapi          "dotnet Newbe.Claptr…"   4 hours ago         Up About an hour    0.0.0.0:10080->80/tcp                                                                                                              localcluster_webapi_1
3bbaf5538ab9        registry.cn-hangzhou.aliyuncs.com/newbe36524/newbe-claptrap-auth-backendserver   "dotnet Newbe.Claptr…"   4 hours ago         Up About an hour    80/tcp, 443/tcp, 0.0.0.0:19000->9000/tcp, 0.0.0.0:32785->11111/tcp, 0.0.0.0:32784->30000/tcp                                       localcluster_dashboard_1
3f60f51e4641        registry.cn-hangzhou.aliyuncs.com/newbe36524/newbe-claptrap-auth-backendserver   "dotnet Newbe.Claptr…"   4 hours ago         Up About an hour    80/tcp, 443/tcp, 9000/tcp, 0.0.0.0:32787->11111/tcp, 0.0.0.0:32786->30000/tcp                                                      localcluster_cluster_gateway_1
7d516ada2b26        registry.cn-hangzhou.aliyuncs.com/newbe36524/newbe-claptrap-auth-backendserver   "dotnet Newbe.Claptr…"   4 hours ago         Up About an hour    80/tcp, 443/tcp, 9000/tcp, 30000/tcp, 0.0.0.0:32788->11111/tcp                                                                     localcluster_cluster_core_1
fc89fcd973f9        grafana/grafana                                                                  "/run.sh"                4 hours ago         Up 6 seconds        0.0.0.0:23000->3000/tcp                                                                                                            localcluster_grafana_1
1f10ed0eb25f        postgres                                                                         "docker-entrypoint.s…"   4 hours ago         Up About an hour    0.0.0.0:32772->5432/tcp                                                                                                            localcluster_claptrap_db_1
d5d2bec74311        adminer                                                                          "entrypoint.sh docke…"   4 hours ago         Up About an hour    0.0.0.0:58080->8080/tcp                                                                                                            localcluster_adminer_1
4c4be69f2f41        bitnami/consul                                                                   "/opt/bitnami/script…"   4 hours ago         Up About an hour    8300-8301/tcp, 8500/tcp, 8301/udp, 8600/tcp, 8600/udp                                                                              localcluster_consulnode3_1
88811d3aa0d2        influxdb                                                                         "/entrypoint.sh infl…"   4 hours ago         Up 6 seconds        0.0.0.0:29086->8086/tcp                                                                                                            localcluster_influxdb_1
d31c73b62a47        bitnami/consul                                                                   "/opt/bitnami/script…"   4 hours ago         Up About an hour    8300-8301/tcp, 8500/tcp, 8301/udp, 8600/tcp, 8600/udp                                                                              localcluster_consulnode2_1
72d4273eba2c        bitnami/consul                                                                   "/opt/bitnami/script…"   4 hours ago         Up About an hour    0.0.0.0:8300-8301->8300-8301/tcp, 0.0.0.0:8500->8500/tcp, 0.0.0.0:8301->8301/udp, 0.0.0.0:8600->8600/tcp, 0.0.0.0:8600->8600/udp   localcluster_consulnode1_1

啟動完成之後,便可以通過以下連結來檢視相關的介面

地址說明
http://localhost:19000 Orleans Dashboard 檢視 Orleans 叢集中各節點的狀態
http://localhost:10080 Web API 基地址,此次使用所測試的 API 基地址
http://localhost:23000 Grafana 地址,檢視 Newbe.Claptrap 相關的效能指標情況

原始碼構建

使用控制檯進入 src/Newbe.Claptrap.Auth 資料夾。執行以下命令便可以在本地完成程式碼的構建:

1
2
./LocalCluster/pullimage.cmd
docker-compose build

pullimage.cmd 使用了筆者編寫的 docker-mcr 加速器功能。您可以通過該文件來了解其工作原理

等待構建完畢之後,本地便生成好了相關的映象。接下來便可以初次嘗試在本地啟動應用:

使用控制檯進入 src/Newbe.Claptrap.Auth/LocalCluster 資料夾。執行以下命令便可以啟動相關的容器:

1
docker-compose up -d

常見問題解答

文中為何沒有說明程式碼和配置的細節?

本文主要為讀者展示該方案的實驗可行性,具體應該如何應用 Newbe.Claptrap 框架編寫程式碼,並非本文的主旨,因此沒有提及。

當然,另外一點就是目前框架沒有最終定版,所有內容都有可能發生變化,講解程式碼細節意義不大。

但可以提前說明的是:編寫非常簡單,由於本樣例的業務需求非常簡單,因此程式碼內容也不多。全部都可以在示例倉庫中找到。

用 Redis 儲存 Token 也可以實現上面的需求,為什麼要選擇這個框架?

目前來說,筆者沒有十足的理由說服讀者必須使用哪種方案,此處也只是提供一種可行方案,至於實際應該選擇哪種方案,應該有讀者自己來考量,畢竟工具是否趁手還是需要試試才知道。

如果是最多 100 個線上使用者,那怎麼裁剪系統?

必要的元件只有 Orleans Dashboard 、 WebAPI 和 Claptrap Db。其他的元件全部都是非必要的。而且如果修改程式碼, Orleans Dashboard 和 WebAPI 是可以合併的。

所以最小規模就是一個程序加一個數據庫。

Grafana 為什麼沒有報表?

Grafana 首次啟動之後需要手動的建立 DataSource 和匯入 Dashboard.

本實驗相關的引數如下:

DataSource

  • URL: http://influxdb:8086
  • Database: metricsdatabase
  • User: claptrap
  • Password: claptrap

點選此處獲取 Dashboard 定義檔案

測試機的物理配置是什麼?

沒有專門騰記憶體,未開始測試前已佔用 16GB 記憶體。以下是測試機的身材資料(洋垃圾,3500 元左右):

處理器 英特爾 Xeon (至強) E5-2678 v3 @ 2.50GHz 12 核 24 執行緒
主機板 HUANANZHI X99-AD3 GAMING (Wellsburg)
顯示卡 Nvidia GeForce GTX 750 Ti (2 GB / Nvidia)
記憶體 32 GB (三星 DDR3L 1600MHz) 2013 年產 高齡記憶體
主硬碟 金士頓 SA400S37240G (240 GB / 固態硬碟)

如果您有更好的物理配置,相信可以得出更加優秀的資料。

即使是 0.3 MB 平均每使用者的佔用的我也覺得太高了

框架還在優化。未來會更好。

最後但是最重要!

最近作者正在構建以反應式Actor模式事件溯源為理論基礎的一套服務端開發框架。希望為開發者提供能夠便於開發出 “分散式”、“可水平擴充套件”、“可測試性高” 的應用系統 ——Newbe.Claptrap

本篇文章是該框架的一篇技術選文,屬於技術構成的一部分。如果讀者對該內容感興趣,歡迎轉發、評論、收藏文章以及專案。您的支援是促進專案成功的關鍵。

GitHub 專案地址:https://github.com/newbe36524/Newbe.Claptrap

Gitee 專案地址:https://gitee.com/yks/Newbe.Claptrap

如果你對該專案感興趣,你可以通過 github issues 提交您的看法。

如果您無法正常訪問 github issue,您也可以傳送郵件到 [email protected] 來參與我們的討論。

點選連結 QQ 交流【Newbe.Claptrap】:https://jq.qq.com/?_wv=1027&k=5uJGXf5。

​​​​​​​

    • 本文作者: newbe36524
    • 本文連結: https://www.newbe.pro/Newbe.Claptrap/How-Many-RAMs-In-Used-While-There-Are-One-Hundred-Thousand-Users-Online/
    • 版權宣告: 本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協議。轉載請註明出處!