iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0
AI 自動化

AaaS from Scratch: 從一次性定義,到規模化分析系列 第 19 篇

[Day 19] Sandbox Scheduling:有限的 Capacity 怎麼分?

  • 分享至 

  • xImage
  •  

上一篇把 Sandbox 的 architecture 和 lifecycle 整理完之後,我們知道一個 sandbox 大概會經過:

create
→ assigned
→ busy
→ idle
→ delete

但這裡有一個假設:

One conversation
→ One sandbox

conversation 少的時候沒什麼問題,但如果同時進來很多 request,sandbox 不可能無限開。

所以接下來要處理的是:

有限的 execution capacity 到底要怎麼分?

現在還是 POC,所以不會真的去跑 100 個 sandbox,而是在 Daytona 現有額度裡看看怎麼解決 scheduling 的問題。

不能只算 Sandbox 數量

最直覺的限制可能是:

max_sandboxes: 10

但在 Daytona 中還會受到 total memory 的限制,所以 provider 真正在意的不只有 sandbox 數量,也包含總共用了多少 memory。

目前同時設定:

server:
  max_sandboxes: 10
  max_memory_gb: 10

例如:

Sandbox A → 1 GB
Sandbox B → 1 GB
Sandbox C → 4 GB
Sandbox D → 4 GB

雖然只有 4 個 sandbox,但 memory 已經用完 10 GB。

所以 manager 必須同時追蹤:

  • Sandbox slots
  • Total memory

Provider 算什麼 resource,我們就要跟著算什麼 resource。

Slot

這裡把可以拿來建立 sandbox 的 capacity 稱為 slot。

概念上就是:

take capacity
→ create sandbox
→ use
→ delete
→ return capacity

不管是正常 delete、create failed 還是 provider error,最後都必須把 capacity 還回去。

不然可能出現:

Real sandboxes: 6
Manager thinks: 10 / 10 used

所以 resource manager 麻煩的地方不是 create,而是:

不管 sandbox 是正常刪除、建立失敗,還是 provider error,capacity 都要正確釋放。

避免被單一使用者佔用過多資源

只有 global limit 還不夠。

目前設定:

server:
  max_sandboxes: 10
  max_sandboxes_per_account: 3
  borrow_keep_free: 2

max_sandboxes_per_account: 3 比較像正常情況下的 limit,而不是絕對不能超過。

如果使用者不多資源還足夠,一個用戶可以暫時使用更多 sandbox。

例如:

10 total slots
3 already used
7 free

即使已經有 3 個 sandbox在使用,還是可以多使用5個,原因如下:

borrow_keep_free: 2

代表至少保留 2 個 free slots 給其他 request。

這樣做是取平衡:

  • system 很空的時候,不要讓 capacity 閒著
  • system 開始忙的時候,還是要替其他 account 保留空間

所以 max_sandboxes_per_account 比較像 normal share,而 borrow_keep_free 則控制一個 account 最多可以借到什麼程度。

Cold Start 與 Warm Pool

Capacity 處理完之後,下一個問題是 latency。

目前 Daytona 的 cold start 加上 prepare 大約需要11秒左右:

如果每次都等 sandbox ready 才開始處理 request,使用者會明顯感受到延遲。

所以現在會先保留:

warm_sandboxes: 1

也就是預先準備一個 ready sandbox:

Warm Pool
└── Ready Sandbox

新的 conversation 需要時可以直接拿來用,拿走之後如果還有 capacity,再從 background 補一個。

但 warm sandbox 一樣會:

  • occupy slot
  • occupy memory
  • 持續產生成本

因此這是一個 trade-off 的問題:

較低的 startup latency
vs
較高的 idle cost

而且 warm sandbox 一樣算在 global capacity 裡。

例如:

max_sandboxes = 10

9 assigned
1 warm
→ 10 / 10

LazySandbox:用一些成本換較低的 Latency

前面 Day 18 有提到,Agent 拿的是 LazySandbox,而不是直接拿 real Daytona sandbox。

當 request 進來時,Agent 和 sandbox startup 可以同時開始:

            User Request
                 ↓
        ┌────────┴────────┐
        ↓                 ↓
 Agent starts       Sandbox starts
 immediately        in background
        │                 │
        └────────┬────────┘
                 ↓
       First code execution
                 ↓
          Sandbox ready?
            ├─ yes → execute
            └─ no  → wait

如果問題只是:

How many videos are in Gaming?

Agent 可能只需要 query_database → answer,完全不需要 Python。

這種情況下,如果一定要先等 sandbox ready 才能繼續後續的執行,那就只是在浪費時間。

所以現在讓 sandbox creation 在 background 執行。真的第一次碰到 execute(...) 時,LazySandbox 才確認 real sandbox 是否 ready。

這樣不是把 cold start 消失掉,而是盡量把它藏在 Agent 前面的 reasoning、SQL query 或其他工作後面。

當然代價是有可能這個 sandbox 最後根本沒用到。

所以這裡也是一個 trade-off:

較低的 perceived latency
vs
較高的 resource cost

目前選擇讓 sandbox 在 background 先啟動,主要是希望換到比較好的使用者體驗。

Capacity 滿了怎麼辦?

如果 sandbox count 或 memory 都已經滿了,為了讓新的 request 不會無限等帶,目前設定最多等待 30 秒:

sandbox_wait_seconds: 30

這段時間可能發生:

  • sandbox deleted
  • slot released
  • idle sandbox reclaimed

如果最後還是沒有 capacity,LazySandbox 會拿到一個正常的 error result,例如:

Sandbox unavailable:
all sandboxes are in use

而不是直接讓整個 Agent execution crash。

Execution Capacity Scheduling

做到這裡,manager 實際上要一起考慮:

  • Sandbox Count
  • Memory Budget
  • Per-account Limit
  • Idle Resources
  • Warm Capacity

所以這裡做的不是傳統的:

Request
→ Server A / B / C

而比較像:

Execution Capacity Scheduling

決定有限的 sandbox resource 要怎麼分給不同 conversation。

下一個問題:拿到 Sandbox 之後呢?

現在我們處理的是:

  • Sandbox 有限,要怎麼分?
  • Cold start 很慢,要怎麼減少等待?
  • 一個 user 拿太多,要怎麼限制?
  • Capacity 滿了,要怎麼等、怎麼 reclaim?

但到這裡,我們還是把每個 sandbox 當成差不多的 execution resource。

例如:

1 vCPU
1 GB Memory

那如果 Agent 跑了一段 code 結果 memory 爆掉,可能有幾種情況:

  • 是 Sandbox 太小?還是 code 一次 load 太多 data?
  • 是 CPU 不夠?還是 memory 才是問題?
  • 真的需要 4 GB?還是調整 execution strategy,1 GB 就可以完成?

所以下一篇想開始測量每個 execution step 用掉多少資源,再決定應該調整 execution strategy,還是真的需要更大的 Sandbox。


上一篇
[Day 18] Sandbox Lifecycle:從 Create 到 Cleanup
下一篇
[Day 20] Sandbox Adaptive Execution:動態調整執行策略
系列文
AaaS from Scratch: 從一次性定義,到規模化分析 共 21 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言