Nextcloud VPS 的真實限制與效能瓶頸
Nextcloud 在 VPS 上不擅長處理 400,000 個小檔案、大型資料樹同步與未設定的 cron;Office 也有明確記憶體下限。
Nextcloud 的限制,依實際遇到的順序排列
Nextcloud 在 VPS 上的多數限制,來自檔案數量與請求數量,而不是磁碟容量。200 GB 的影片檔案集中在少數檔案中,在小型伺服器上通常能正常運作。同樣是 200 GB,若分散在 400,000 個小檔案中,每次列出資料夾都會變慢,也會讓資料庫成為伺服器上最忙碌的程序。以下順序就是自架使用者通常遇到這些限制的順序:先是 PHP 的請求模型,再來是同步用戶端,接著是資料庫預設值,然後是背景工作,最後是記憶體。
有些人所說的「Nextcloud 很慢」,其實是因為某個預設值從未調整。其餘則是產品設計本身,調校也無法消除。每個章節都會說明屬於哪一種情況。
PHP 如何決定並行處理上限
Nextcloud 以 PHP 撰寫,而 PHP 應用程式不是長時間執行的伺服器。每個請求都由 PHP-FPM(FastCGI process manager)集區中的一個 worker process 處理,且該 worker 會從頭到尾負責這個請求。因此,伺服器同一時間能處理的請求數量就是 pm.max_children,而每個 worker 都會占用自己的記憶體。
這會帶來兩個結果。慢速請求會在整個處理期間占用 worker,因此某個使用者組裝 4 GB 上傳內容時,會占用其他人無法使用的處理名額。當所有 worker 都在忙碌時,新請求會在 socket backlog 中等待。集區的日誌會顯示這一點:
WARNING: [pool www] server reached pm.max_children setting (5), consider raising it讀者通常會先在前端 Web 伺服器看到這個症狀,顯示為 504:
upstream timed out (110: Connection timed out) while reading response header from upstream發行版的預設集區通常會設定為 pm.max_children = 5。這對共用伺服器而言是合理的估值,但對連接十多個同步用戶端的 Nextcloud 執行個體來說遠遠不足。請根據實際可用的記憶體調整:測量忙碌 worker 的常駐記憶體大小,為資料庫與快取保留空間,再進行除法計算。
pm = dynamic
pm.max_children = 12
pm.max_requests = 500
php_value[memory_limit] = 512Mmemory_limit 是每個請求的上限,不是預先配置的記憶體量。大多數請求只會使用其中一小部分。預覽產生與大型上傳組裝會使用較多記憶體,因此必須一併決定這項限制與子程序數量。
請求之間也沒有共用的應用程式記憶體。每個請求都會再次啟動框架:設定、已啟用的應用程式、路由與事件監聽器。OPcache 會保留編譯後的 bytecode,因此這是執行而非剖析;APCu(alternative PHP cache)則會在共用記憶體中保存小型本機 key-value store。這就是管理介面中的「No memory cache has been configured」提示值得注意的原因。沒有這項設定時,原本可從記憶體取得的查詢結果,會在每個請求中再次存取資料庫。這部分屬於設定。底層每個請求使用一個程序的模型則屬於架構。
為什麼小檔案數量會在磁碟出問題前很久就造成負擔
Nextcloud 會在同一個資料庫資料表中,為每個檔案與資料夾保存中繼資料,oc_filecache:路徑、路徑雜湊、大小、修改時間、etag 與儲存區 ID。資料夾清單是對該資料表執行的查詢,不是對磁碟執行的 readdir。寫入檔案時,系統會更新該檔案的資料列,接著將新的大小與 etag 向上傳播,更新每一層父資料夾直到根目錄。一次上傳會產生一個 HTTP 請求、數個 SQL 陳述式,以及依目錄深度對每一層進行的一次更新。
傳輸同樣以檔案為單位。同步協定是 WebDAV(web distributed authoring and versioning),而 WebDAV 每個請求只傳輸一個檔案。400,000 個檔案就代表 400,000 個請求,每個請求都包含驗證、框架初始化、權限檢查與資料庫寫入。若每個請求耗用 25 ms 的伺服器處理時間,光是這些額外成本就接近三小時,還未計入任何有效負載。這只是算術結果,不是效能基準。它說明的重點是:成本取決於檔案數量,而不是檔案大小。
更快的儲存裝置只能改善其中一部分。隨機的小型讀寫正是 NVMe 與 SATA SSD VPS 儲存設備差異最大之處,因此大型實例值得使用 NVMe。它無法降低每個請求的成本,因為這項成本主要來自 PHP 與 SQL,而不是磁碟。
有一個後果會讓所有人很快遇到。直接複製到伺服器、但未經 Nextcloud 處理的檔案,對 Nextcloud 而言並不存在,因為從未有人寫入對應的資料列。只有在 occ files:scan 掃描整個目錄樹並寫入缺少的資料列後,這些檔案才會出現;對大型目錄樹而言,這項掃描可能耗時很久。如果你不確定容器安裝中的檔案究竟位於何處,Nextcloud 在 Docker 中的資料目錄配置是另一篇獨立的說明。本篇討論的是架構:檔案清單存在資料庫中。
大型目錄樹造成桌面用戶端變慢的原因
同步用戶端的效能通常比外界印象更好。因為寫入會將新的 etag 向上傳播到根目錄,用戶端可以先提出一個成本低廉的問題,確認是否有任何變更,再只深入檢查 etag 不同的目錄。因此,閒置輪詢本身不會造成高昂成本。
仍然存在的成本是實際的。首次同步會遍歷每個目錄,每個目錄發出一個 PROPFIND 請求,並下載每個檔案。樹狀結構上層附近的重新命名會變更其下所有內容的 etag,因此用戶端會重新檢查整個子樹。用戶端也會維護自己的本機資料庫,並取得本機檔案的統計資訊,因此速度較慢的筆記型電腦磁碟或過於積極的防毒掃描器,都可能增加與伺服器完全無關的延遲。
如果沒有 Client Push 應用程式,notify_push,每個已連線的用戶端都會依計時器進行輪詢。三十個用戶端會持續對處理相同網頁介面的 worker pool 發出背景請求。notify_push 是一個小型獨立服務,會為每個用戶端維持一個 websocket,並在發生變更時通知用戶端,因而移除大部分閒置流量。在繁忙的執行個體上,這是最有價值的新增功能之一。
不會進行合併。兩個人在離線時編輯同一個檔案,會產生一份衝突副本,名稱類似 budget (conflicted copy 2026-08-22 141530).ods,並由人工手動解決。透過 office service 編輯可以避免此問題,因為此時伺服器上始終只有一份副本具備權威性。Virtual files 會先將檔案顯示為預留位置,直到檔案被開啟;此功能在 Windows 和 macOS 上已相當穩定,但在 Linux 上仍較晚趨於穩定,因此若要據此規劃工作流程,請先確認用戶端版本。輪詢屬於設定。每個檔案發出一個請求則屬於架構。
預設安裝尚未完成的部分
全新安裝的 Nextcloud 可以正常運作。但在典型的手動安裝中,仍有 4 項設定尚未完成。這 4 項都會顯示在 Settings、Administration、Overview 中。
- 沒有記憶體快取。Overview 會顯示「尚未設定記憶體快取」。APCu 幾乎不會增加成本,卻能大幅減少重複的資料庫查詢。
- 將檔案鎖定儲存在資料庫中。Nextcloud 在寫入檔案時會鎖定檔案。沒有 Redis 時,鎖定資訊會儲存在資料庫資料表中,增加寫入負載;請求中斷後也會留下過期的鎖定。使用者接著會看到檔案已鎖定的錯誤,只有手動清理才能解除。
- 缺少資料庫索引。Overview 會顯示「資料庫缺少部分索引」,並列出
occ db:add-missing-indices。當 filecache 有數百萬筆資料列時,這些索引會決定檔案清單能否快速載入。 - SQLite。手動安裝可能會使用 SQLite。文件支援 SQLite 用於單一使用者及測試環境。寫入操作會序列化,因此只要再有 1 名使用者同時操作,就已經超出適用範圍。
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' => [
'host' => 'localhost',
'port' => 6379,
],這些都不是特殊功能,而是設定。如果您希望直接從已完成這些決策的安裝開始,使用 Docker 安裝 TLS 與備份會在啟動堆疊時一併建立快取與 cron 容器。
未設定 cron 時,背景工作為何會停滯
Nextcloud 會將實際工作交由背景工作執行,例如產生預覽、讓舊檔案版本過期、依排程清空垃圾桶、傳送通知郵件,以及清理分享項目。支援的執行方式有 3 種,但預設方式最不可靠。
AJAX 模式會在瀏覽器載入頁面時執行 1 個工作。若個人執行個體 1 週都沒有人造訪,這 1 週內就不會執行任何工作。檔案版本與垃圾桶內容永遠不會過期,因此磁碟會持續被使用者以為已刪除的資料填滿。預覽不會預先產生,因此第 1 個開啟相片資料夾的人,必須等待自己的請求產生預覽。最後,總覽會顯示上次背景工作在數小時前執行,並顯示「似乎發生問題」,而這就是你能收到的唯一警告。
Webcron 與 system cron 都能解決這個問題。System cron 會以 Web 伺服器使用者身分,每 5 分鐘執行 cron.php;容器安裝則會從專用的 cron 容器執行相同工作。文件指定的間隔是 5 分鐘,工作間隔也會依此設定。
剩下的成本是工作會依序執行。長時間工作的預覽批次或檔案掃描,會延後其後所有排入佇列的工作;在單核心 VPS 上,這些工作也會與即時請求競爭資源。在繁忙的主機上,鄰近使用者造成的 CPU steal time 會讓執行時間超出你根據自身數據所做的預測。設定則是多數遭忽略的執行個體中,價值最高的單一修正項目。
加入 office、Talk 或預覽後的記憶體下限
純 Nextcloud 的需求不高:PHP pool、資料庫、Redis 與 Web server。小型執行個體使用 2 GB 就很充裕。每個實際需要的功能,都是具有自身最低需求的獨立服務。
預覽。 預設情況下,系統會在第一次提出要求時產生預覽,因此使用者必須在需要預覽的請求中等待。Preview Generator app 會將這項工作移至 cron,代價是 cron 執行期間會消耗 CPU。無論採用哪種方式,每張來源圖片都會產生數個不同尺寸的預覽檔案,因此相片庫會讓檔案數量倍增,並直接加劇前述的小檔案問題。大型來源圖片也最容易觸及記憶體限制,錯誤會以 Allowed memory size of 536870912 bytes exhausted 的形式出現在 PHP error log 中。請使用 preview_max_x 與 preview_max_y 限制其用量,不要無限提高限制。
Office。 Collabora Online 與 OnlyOffice Docs 都會以獨立服務執行,通常位於不同容器中,並各自使用執行環境與記憶體。文件工作階段會在這些服務中消耗 CPU 與 RAM,而不是在 PHP 中消耗。請先預留 1 或 2 GB,才能維持流暢回應;規劃伺服器規格前,請參考截至 August 2026 的供應商最新需求。兩者的差異不只在資源使用量,自架 OnlyOffice 與 Collabora 的比較 會說明這項區別。
Talk。 少數參與者之間的通話會透過 WebRTC 進行點對點傳輸,伺服器只轉送 signalling 訊息。參與者人數超過約 4 人後,Nextcloud 的官方建議會指向 High Performance Backend,也就是獨立的 signalling server。許多網路還需要 TURN(透過 relay 穿越 NAT)server,例如 coturn;媒體轉送流量會經過你的 VPS,因此頻寬會成為實際的成本項目。
全文搜尋。 Elasticsearch 執行個體本身就需要 1 GB 以上的 heap,還沒開始建立索引。
Nextcloud 需要多少 VPS 資源?
只依使用者人數估算容易產生誤判,因為實際行為才是主要影響因素。5 位開發人員同步 300,000 個檔案的原始碼樹,負載可能高於 30 位只在瀏覽器中開啟文件的使用者。請將以下規格作為起始點,再依自身的檔案數量進行測試,而不要視為測量結果。
- 1 vCPU 和 1 到 2 GB:適合 1 或 2 位使用者,僅使用檔案與行事曆,並嚴格限制預覽功能,不使用 office service。升級與完整檔案掃描會是這台主機上最耗時的作業。
- 2 vCPU 和 4 GB:約適合 5 到 15 位一般使用者,搭配 APCu、Redis 鎖定、system cron,以及由 cron 產生預覽。
- 4 vCPU 和 8 GB:適合相同的使用者範圍並搭配 office service,或適合 15 到 40 位不使用 office service 的輕度使用者。這裡的記憶體用量主要取決於 office session。
- 4 個以上的 vCPU 和 16 GB:適合搭配 High Performance Backend 的 Talk、全文搜尋,或針對相片資料庫大量產生預覽。
磁碟空間需要另外計算。預覽、檔案版本與垃圾桶都會額外佔用實際資料以外的空間,只有在背景工作確實執行時,這些資料才會減少。整體成本是否低於訂閱費,取決於上述數據;比較自架儲存空間與 Dropbox 定價可協助完成這項計算。
哪些 Nextcloud 限制可透過設定修正,哪些屬於架構限制
可在一個下午內修正:記憶體快取與 Redis 鎖定、缺少的資料庫索引、背景工作模式、FPM pool 大小與 PHP 記憶體限制、OPcache 大小設定、notify_push,以及預覽範圍。完成這些調整的執行個體,即使使用相同硬體,也已不同於預設安裝。
無論如何調整都無法改變:
- 每個請求使用一個程序。並行數受 RAM 限制,而一個緩慢的請求會在整個執行期間佔用一個 worker。
- 每個檔案對應一個資料庫資料列,檔案大小與 etag 會逐層傳遞到每個上層目錄。成本會隨檔案數量增加。
- 網路上每個檔案都需要一個請求。同步大量小檔案時,瓶頸是請求的額外負擔,而不是頻寬。
- 這是內含檔案應用程式的群組軟體平台。基準環境包含純同步工具不會載入的機制。
- 升級必須依序進行。主要版本會在維護模式下逐一套用,而且每個步驟都必須先通過應用程式相容性檢查。
這些都不是錯誤,而是共用連結、外部協作者、行動用戶端,以及跨所有功能使用同一個帳戶系統所需付出的代價。購買 enterprise edition 可取得支援與部分額外應用程式,但不會改變上述請求模型。免費 Nextcloud edition 實際包含的內容說明的正是這一點。
不適合在 VPS 上執行 Nextcloud 的情況
- 你只想在幾台機器之間快速同步大型檔案樹,沒有其他需求。點對點工具不會在 Web 應用程式的資料庫中為每個檔案建立資料列,因此小型檔案的成本完全不同:Syncthing 與 Nextcloud 的純同步比較。
- 你需要分享功能與 Web 介面,但資料包含數百萬個小型檔案。Seafile 會將內容儲存在區塊儲存區,而不是每個檔案各自儲存,計算方式因此不同。取捨是資料不再以一般檔案形式存在於磁碟上:Seafile 與 Nextcloud 的比較。
- 你只想透過瀏覽器查看伺服器上既有的檔案,不需要同步用戶端,也不希望在檔案前面配置每檔案一筆的資料庫資料列;這正是較輕量的自架檔案管理工具的用途。
- 你的實際需求是供 4 個人使用的共用磁碟。先採用較輕量的方案,日後再擴充:Nextcloud 的自架替代方案。
- 你只有 1 vCPU 和 1 GB,卻想使用瀏覽器式辦公室編輯功能。這種配置無法滿足需求,任何調校都無法改變這一點。
如果你需要群組協作功能,請執行 Nextcloud:與組織外部人員分享、在每支手機上使用行事曆與聯絡人、在瀏覽器中編輯,以及用同一組登入資訊使用全部功能。故障通常不是突然發生,而是效能逐漸下降。檔案數量持續增加,安裝環境仍沒有快取,也沒有 cron,最後某天開啟資料夾需要 8 秒。這些情況都能量測,而且大多數問題都能在發生前修正。
FAQ
一台 Nextcloud VPS 可以容納多少使用者?
實際行為比使用者人數更能決定需求。經過調校的 2 vCPU、4 GB 伺服器,通常可讓約 5 到 15 名一般使用者處理檔案、行事曆和聯絡人。加入辦公室服務後,通常需要 8 GB。通常最先遇到的限制,是 PHP worker 數量受到可用 RAM 限制,或是 oc_filecache 變大後資料庫成為瓶頸。因此,在決定方案規模前,應使用自己的檔案數量進行測試。
為什麼檔案很多且都很小時,Nextcloud 會變慢?
因為每個檔案都是一筆資料庫資料列,也需要個別的 WebDAV 請求。列出資料夾內容時會執行 SQL 查詢;寫入檔案時會更新該檔案的資料列,以及每個上層資料夾的大小和 etag;傳輸時,每個檔案都會各自發出一次 HTTP 請求,並重新執行驗證和框架初始化。因此,成本取決於檔案數量,而不是檔案總容量。更快的儲存裝置只能降低磁碟 I/O 的部分成本,無法消除每次請求本身的成本。
Nextcloud 需要 Redis 嗎?
單一使用者不需要。只要是多使用者環境,就需要。沒有 Redis 時,交易式檔案鎖定會透過資料庫資料表處理,這會增加寫入負載;請求異常中止後也可能留下過期鎖定,使用者會看到檔案已鎖定的錯誤。一般配置會使用 APCu 處理本機快取,使用 Redis 處理鎖定,兩者都設定在 config.php。
如果始終不設定 Nextcloud 的背景工作,會發生什麼事?
預設的 AJAX 模式會在每次載入頁面時執行一項工作,因此沒有人登入時就不會執行任何工作。預覽不會預先產生,檔案版本和垃圾桶內容也不會過期,磁碟使用量會持續增加,通知郵件也會停止寄送。管理員總覽最後會顯示上次背景工作是在數小時前執行,並指出系統似乎有問題。解決方式是改用每 5 分鐘執行一次的 system cron;容器安裝則由專用的 cron 容器執行這項工作。