
Neon Compute Tools 實戰指南compute_ctl 計算節點啟動流程、狀態機與運維詳解【免費下載鏈接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.項目地址: https://gitcode.com/GitHub_Trending/ne/neon導讀compute_tools是 Neon 開源倉庫中負責計算節點compute node這一側的完整工具集其核心二進制compute_ctl是一個用 Rust 編寫的 Postgres 包裝器wrapper通常作為 Docker 容器 entrypoint 或 systemdExecStart運行負責在 Neon 存算分離架構下完成計算節點從空目錄到可對外服務的全部初始化工作。本文將基于 compute_tools/README.md 為主體結合 compute_tools/src 目錄下的源碼實現系統講解compute_ctl的啟動流程、命令行參數、后臺服務線程、HTTP API、自動伸縮autoscaling集成、狀態機以及測試與跨平臺編譯方法幫助你從能用進階到理解其內部機制。compute_ctl 的定位與運行形態在 Neon 的存算分離架構中Postgres 作為計算節點與存儲層pageserver分離每次啟動計算節點都是一次從零開始的全新啟動。compute_ctl就是為了管理這一過程而生的它以 JSON 文件形式接收集群計算節點規格說明compute spec每次啟動都是全新啟動數據目錄會被刪除并重新初始化它負責與 safekeeper、pageserver 通信把 Postgres 引導到正確的時間線timeline上它啟動 Postgres、創建角色和數據庫并最終掛起等待 postmaster 退出。從 compute_tools/Cargo.toml 可以看到compute_tools是一個獨立 Cargo 包compute_toolsv0.1.0依賴了compute_api、vm_monitor、remote_storage、postgres_initdb、pageserver_page_api等工作區內部庫以及clap命令行解析、tokio、axum、hyperHTTP 服務等通用依賴這決定了其功能邊界既要與 Neon 控制平面/存儲層通信又要對本地 Postgres 做進程級管理。compute_ctl 的啟動與初始化流程按 README 的描述compute_ctl在計算節點初始化期間處理所有 Neon 特有的工作完整流程如下接受集群計算節點規格說明cluster/compute spec規格以 JSON 文件形式給出每次啟動都是全新啟動fresh start因此每次運行都會刪除并重新初始化數據目錄把配置文件寫入PGDATA目錄同步 safekeeper 并取得 commit LSN使用上一步返回的 LSN 從 pageserver 拉取basebackup嘗試啟動postgres并等待其就緒、可以接受連接檢查并alter/drop/create角色與數據庫掛起hang等待postmaster進程退出。上述流程在源碼中對應 compute.rs 中ComputeNode的啟動邏輯其中第 4、5 步的同步 safekeeper 并取得 LSN由 sync_sk.rs 的check_if_synced/ping_safekeeper實現basebackup 通過pageserver_page_apilibs/pageserver_api的頁服務客戶端從 pageserver 獲取且支持壓縮BaseBackupCompression。需要特別說明的是這是一個無狀態的啟動模型——數據不保存在本地而是全部從存儲層重建這正是 Neon scale to zero 能力的基礎計算節點可以被隨時銷毀下次啟動時通過 safekeeper 的 LSN 與 pageserver 的 basebackup 恢復到一致狀態。spec 從哪來控制平面 API 或本地文件README 中的示例使用-S /var/db/postgres/specs/current.json直接指定本地的 spec 文件。從當前源碼 compute_ctl.rs 看compute_ctl還支持通過-p/--control-plane-uri與-i/--compute-id從 Neon 控制平面拉取 specspec.rs 中get_config_from_control_plane()會請求{base_uri}/compute/api/v2/computes/{compute_id}/spec攜帶NEON_CONTROL_PLANE_TOKEN環境變量作為Authorization: Bearer頭請求采用最多 3 次嘗試的重試邏輯網絡錯誤、503服務暫不可用、502 會重試其他狀態碼如 404、500則直接失敗不重試控制平面返回Empty狀態表示還沒有 speccompute_ctl會進入等待狀態。無論 spec 來自本地文件還是控制平面最終都會解析為 compute.rs 中的ParsedSpec其中包含tenant_id、timeline_id、pageserver_conninfo、safekeeper_connstrings等關鍵信息。對于舊版本控制平面生成的 specParsedSpec::try_from還支持從pageserver_connstring字段或cluster.settings中的 GUC如neon.pageserver_connstring、neon.tenant_id、neon.timeline_id反向推導連接信息保持了向后兼容。命令行參數詳解README 給出的典型用法compute_ctl -D /var/db/postgres/compute \ -C postgresql://cloud_adminlocalhost/postgres \ -S /var/db/postgres/specs/current.json \ -b /usr/local/bin/postgres各參數含義參數含義-D/--pgdataPostgres 數據目錄路徑PGDATA每次啟動會被清空重建-C/--connstr連接 Postgres 的連接串cloud_admin是 Neon 的超級用戶角色-S集群計算節點spec 的 JSON 文件路徑-b/--pgbinpostgres可執行文件路徑默認值postgres也可用環境變量POSTGRES_PATH覆蓋結合當前源碼 compute_ctl.rs 的Cli結構基于clap派生compute_ctl實際支持的參數遠不止上述四個整理如下參數默認值說明-b, --pgbinpostgresenvPOSTGRES_PATHPostgres 可執行文件路徑-r, --remote-ext-base-url無遠程擴展存儲代理網關extension storage proxy gateway的基礎 URL用于按需下載擴展--external-http-port3080外部 HTTP 服務器端口控制平面、metrics 抓取器等通過它訪問 compute--internal-http-port3081內部 HTTP 服務器端口供 compute 內進程neon 擴展、local_proxy使用--http-port無Hadron 部署的向后兼容參數功能等同--external-http-port內部端口自動 1-D, --pgdata必填數據目錄-C, --connstr必填連接串--privileged-role-nameneon_superuser弱超級用戶角色名只能由小寫字母與下劃線組成有正則校驗--cgroupLinuxneon-postgres自動伸縮場景下 postgres 所在的 cgroup 名稱--filecache-connstrLinuxhostlocalhost port5432 ... usercloud_admin連接 Postgres 供 vm-monitor 文件緩存使用的連接串--vm-monitor-addrLinux0.0.0.0:10301vm-monitor 監聽地址--resize-swap-on-bindfalse綁定階段是否調整 swap 大小--set-disk-quota-for-fs無為指定文件系統設置磁盤配額-c, --config無本地配置文件spec路徑與-p互斥-i, --compute-id必填compute 的唯一 ID-p, --control-plane-uri無控制平面 API 基礎 URL指定后從控制平面拉取 spec要求同時提供-i--installed-extensions-collection-interval3600秒已安裝擴展統計的采集間隔--devfalse開發模式跳過 VM 特有操作如進程終止--pg-init-timeout無Init 狀態下的 Postgres 啟動超時--lakebase-modefalseDatabricks lakebase 部署模式Hadron 相關關鍵解讀-C指定的連接串會在ComputeNode::new()compute.rs中被附加一組額外的 GUC 選項-c rolecloud_admin -c default_transaction_read_onlyoff -c search_path -c statement_timeout0 -c pgaudit.lognone。原因是用戶可能通過ALTER DATABASE ... SET ...設置了statement_timeout、default_transaction_read_only等參數會阻礙compute_ctl對數據庫 schema 的配置因此必須在連接前強制重置控制平面提供的選項會被追加在后面允許覆蓋。在 Linux 設置了AUTOSCALING環境變量的情況下compute.rs 的maybe_cgexec()會使用cgexec -g memory:neon-postgres啟動 postgres使其運行在neon-postgrescgroup 中從而允許自動伸縮系統精確控制 postgres 的資源占用。兩個核心服務線程compute-monitor 與 http-endpointREADME 指出compute_ctl除了主流程外還會派生兩個獨立服務線程compute-monitor檢查 Postgres 的最后活動時間戳last activity timestamp并將其寫入共享的ComputeNode狀態http-endpoint運行一個基于 Hyper 的 HTTP API 服務器提供就緒readiness與最近活動last activity查詢。compute-monitor 的檢測原理實現位于 monitor.rs。launch_monitor()會啟動一個名為compute-monitor的線程以500msMONITOR_CHECK_INTERVAL為周期循環執行其活動檢測邏輯check()依次檢查數據庫統計變化實驗性檢測受ActivityMonitorExperimental特性開關控制對pg_stat_database求和active_time、sessions排除postgres、template0、template1任一指標變化即視為有活動后端狀態變化查詢pg_stat_activity中client backend類型的連接排除自身與cloud_admin若存在非idle后端則最后活動現在若都是idle取state_change時間戳的最大值walsender 數量select count(*) from pg_stat_replication where application_name ! walproposer有 walsender 則不掛起邏輯復制訂閱pg_stat_subscription中pid is not null的訂閱存在則不掛起autovacuum workerpg_stat_activity中backend_type autovacuum worker存在則不掛起。這些不應掛起的例外檢測非常關鍵monitor 的目的本質上是為 scale-to-zero 決策提供依據——如果存在復制、訂閱或后臺任務compute 就不應該被自動關閉。同時 monitor 還維護兩個 Prometheus 指標PG_CURR_DOWNTIME_MS當前停機時長與PG_TOTAL_DOWNTIME_MS累計停機時長并在 compute 處于Terminated/TerminationPendingFast/TerminationPendingImmediate/Failed等終態時優雅退出。另外monitor 在等待 Postgres 進入Running狀態時受pg_init_timeout約束默認 60 秒若超時仍未進入 Running例如用錯誤的 spec 啟動、連上了錯誤的 pageserver/safekeeper會直接exit(1)讓計算節點重啟以便用最新 spec 重試見 monitor.rs。http-endpoint內部與外部兩套 HTTP APIcompute_ctl實際啟動的是兩個Hyper/axum HTTP 服務器見 http/server.rs外部服務器默認端口 3080面向控制平面、metrics 抓取器路由包括/status、/configure、/refresh_configuration、/terminate、/promote、/metrics、/check_writability、/hadron_liveness_probe等內部服務器默認端口 3081只綁定 loopback僅對 compute 內的進程Postgres neon 擴展、local_proxy開放路由包括/extension_server/{*filename}下載擴展、/extensions安裝擴展、/grants、/refresh_configuration。各路由實現位于 compute_tools/src/http/routesstatus.rsGET /status加鎖讀取共享ComputeState并序列化為ComputeStatusResponse返回實現 README 所述就緒與最后活動查詢configure.rsPOST /configure接收 JSON 格式的ConfigurationRequest解析為ParsedSpec后寫入共享狀態、置為ConfigurationPending再阻塞等待 compute 變為Running若失敗則返回 500 及錯誤信息這也是狀態機中Running → ConfigurationPending的觸發入口terminate.rs、promote.rs、refresh_configuration.rs分別對應終止、提升災備切換與熱刷新配置。ComputeStatecompute.rs是跨線程共享的核心結構status當前狀態、last_active最后活動時間、error、pspec當前 spec等字段都在Mutex保護之下配合Condvar實現狀態變更通知每次set_status()都會更新COMPUTE_CTL_UP指標便于監控系統追蹤當前狀態。AUTOSCALING 環境變量與 vm-monitorREADME 明確指出如果設置了AUTOSCALING環境變量compute_ctl會啟動位于libs/vm_monitor的 vm-monitor。對于 VM 計算節點vm-monitor 與 VM 自動伸縮系統通信協調降級downscaling并在資源緊張時請求立即升級upscaling。從 compute_ctl.rs 可見autoscaling 模式下涉及三個關鍵參數--cgrouppostgres 所在 cgroup默認neon-postgres、--filecache-connstrvm-monitor 連接 Postgres 用于文件緩存管理的連接串、--vm-monitor-addr默認0.0.0.0:10301。vm-monitor 本體是工作區獨立庫位于 libs/vm_monitor在compute_tools的依賴聲明Cargo.toml中通過path ../libs/vm_monitor/引入。其角色可以概括為作為 compute 內部與外部自動伸縮系統之間的資源代言人——平時配合 scale-to-zero 觀察資源利用率以推動降級當 Postgres 在 cgroup 層面出現內存/CPU 壓力時則向上請求升級從而讓 Neon 的計算節點在最小可用資源與峰值需求之間動態調整。計算節點狀態機State DiagramREADME 附帶的 mermaid 狀態圖完整描述了 compute 在compute_ctl管理下的生命周期。該狀態機在源碼中的落地形態即ComputeStatus見 compute.rs 的set_status()/set_failed_status()與COMPUTE_CTL_UP指標下面完整保留原圖對關鍵狀態的解讀Emptycompute 進程剛被拉起尚無任何 specConfigurationPending / Configuration已收到或正在拉取spec進入配置階段——對應 README 啟動流程的第 25 步清空數據目錄、寫配置、同步 safekeeper、拉 basebackupInitspec 立即可用時直接從 Empty 進入對應啟動 Postgres 并等待就緒階段若失敗進入FailedRunning配置完成、Postgres 可接受連接這是穩態RefreshConfigurationPending / RefreshConfiguration運行中收到/refresh_configuration請求拉取新 spec 并熱重配置如變更實例規格、GUC 參數失敗會回到RefreshConfigurationPending重試TerminationPendingFast / TerminationPendingImmediate收到終止請求Fast 模式會保留 30 秒讓控制平面檢查狀態Immediate 立即終止隨后進入Terminated并退出進程Failed任何階段配置失敗都會進入仍可通過/refresh_configuration請求嘗試恢復或者進程直接退出。從代碼實現看兩個終止路徑的差異也體現在 monitor 的退出邏輯中monitor.rsmonitor 一旦發現 compute 進入這四個終態之一便停止活動檢測、優雅退出。測試與代碼質量README 給出了開發compute_tools時常用的三個命令原樣保留并補充說明# 1. Cargo 格式化 cargo fmt # 2. 運行測試 cargo test # 3. Clippy 靜態檢查將警告視為錯誤 cargo clippy --all --all-targets -- -Dwarnings -Drust-2018-idioms倉庫中已存在的測試包括 compute_tools/tests/config_test.rs 與 compute_tools/tests/pg_helpers_tests.rs前者針對配置解析/生成邏輯后者針對 Postgres 輔助函數。此外compute_tools的testingfeaturetesting [fail/failpoints]會啟用 failpoint 支持便于在 compute_ctl.rs 的單元測試中注入故障場景例如模擬不同 spec 組合下的--pgdata/--connstr解析。同時 Cargo.toml 中#![deny(unsafe_code)]見 lib.rs表明整個 crate 禁用 unsafe 代碼這也解釋了 clippy 檢查為什么對代碼風格如此嚴格。跨平臺編譯從 macOS 交叉編譯 Linux GNU 可執行文件README 提供了兩種從 macOSx86交叉編譯 Linux GNURust 術語中的x86_64-unknown-linux-gnu平臺可執行文件的方法這是 CI 或本地構建 compute 鏡像時的常見需求。方式一使用一次性 Docker 容器使用官方 rustlang/rust或rust鏡像把當前目錄掛載進去編譯docker run --rm \ -v $(pwd):/compute_tools \ -w /compute_tools \ -t rustlang/rust:nightly cargo build --release --targetx86_64-unknown-linux-gnu或者一行版docker run --rm -v $(pwd):/compute_tools -w /compute_tools -t rust:latest cargo build --release --targetx86_64-unknown-linux-gnu方式二Rust 原生交叉編譯在宿主機上添加目標平臺并安裝 macOS 交叉編譯工具鏈# 添加編譯目標 rustup target add x86_64-unknown-linux-gnu # 安裝 macOS 交叉編譯器工具鏈 brew tap SergioBenitez/osxct brew install x86_64-unknown-linux-gnu最后通過CARGO_TARGET_*環境變量指定鏈接器后構建CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKERx86_64-unknown-linux-gnu-gcc cargo build --targetx86_64-unknown-linux-gnu --release注意事項compute_tools依賴鏈中包含 Linux 平臺專用代碼例如 compute.rs 中#[cfg(target_os linux)]的 filecache/cgroup/vm-monitor 參數、nix系統調用、rlimit等因此 README 提供的兩種交叉編譯方案目標明確針對 Linux 部署環境本機macOS開發時這些平臺相關字段會被cfg條件編譯剔除不影響本地cargo test與cargo clippy的正常使用。總結compute_ctl是 Neon 存算分離架構在計算節點側的總調度器它把清空數據目錄 → 同步 safekeeper 取 LSN → 從 pageserver 拉 basebackup → 啟動 Postgres → 配置角色/數據庫 → 掛起等待這一整套無狀態啟動流程自動化并通過 compute-monitor 與內部/外部兩套 HTTP API 支撐起 scale-to-zero、自動伸縮與動態重配置能力。README 中的狀態機圖則是對這一整套生命周期的權威抽象——無論是排查Failed、理解/configure熱更新還是調試終止流程都可以從這張圖出發在 compute.rs、monitor.rs 與 compute_tools/src/http/routes 中找到對應的代碼實現。【免費下載鏈接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.項目地址: https://gitcode.com/GitHub_Trending/ne/neon創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考