十萬同時在線用戶,需要多少內存?——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 Dashboard Orleans Gateway Orleans 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,您也可以發送郵件到 newbe-claptrap@googlegroups.com 來參与我們的討論。

點擊鏈接 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 許可協議。轉載請註明出處!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

FB行銷專家,教你從零開始的技巧

您可能也會喜歡…