Skip to content
FunCoding

Search

Search docs, Skills and MCP

Serve 启动与关闭

理解配置校验、工作区规范化以及内部 hosting 的生命周期绑定。

This page has not been translated into English yet. The original Chinese version is shown below.

runQwenServe 是 CLI 的 daemon 启动层:解析和验证 ServeOptions,组装 bridge、文件服务与 Express,创建监听器,并管理关闭。外部集成应优先使用 qwen serve 与 HTTP/SSE;createServeApp 属于内部 hosting 与测试接口。

启动时固定什么

  1. 解析并 trim token,检查监听地址与认证组合。
  2. 验证 workspace 存在且为目录,对主目录和附加目录进行 canonicalize。
  3. 检查 session、connection、MCP、timeout、Origin 和 rate-limit 参数。
  4. 读取 settings,验证 policy,建立权限审计、文件服务和状态 provider。
  5. 建立 bridge 与 HTTP app,再创建并绑定真实 Node HTTP(S) server。
  6. 完成监听和其他 host gate 后允许 Conversations ownership,注册退出处理。

主工作区的规范路径同时用于 capabilities、POST /session 的默认目录和 bridge,避免不同层使用不同 symlink 拼写。hostname 写成 localhost:4170 会报错;端口应由 --port 提供。

Token 的来源与空值

--token 优先于 QWEN_SERVER_TOKEN。显式空 --token 会遮蔽环境值;环境为空且没有 --token 时,也不属于“未提供来源”。远程非 loopback 在来源完全缺失时可生成临时 128-bit bearer,而显式空来源抑制生成并导致无 token 远程绑定失败。

loopback 拼写通常不自动生成 token。localhost 的一次 DNS 解析与其他主机名拼写还有专门边界,实际行为见认证。不要简单把“未传参数”和“明确传空值”视为同一种配置。

CLI --open-with-auth 是另外的入口:在符合条件的 loopback Web Shell 启动前复用或生成 256-bit bearer。直接调用 createServeApp 不会替嵌入方生成 token。

配置错误与读取失败

无效 policy.permissionStrategy 或非正整数 policy.consensusQuorum 会抛出 InvalidPolicyConfigError,使启动明确失败。非 consensus 模式设置 quorum 会给警告。

settings 文件读取或损坏可能回退默认,不能据此认为有效读出的非法策略也会被忽略。MCP enforce 没有正 budget、非法期限、错误工作区等也应在启动时处理。

多实例的环境

MCP budget/mode 通过 BridgeOptions.childEnvOverrides 传给对应 child。不要为了一个嵌入 handle 改全局 process.env:默认 channel factory 在 spawn 时读取环境,同进程多个 daemon 会互相竞争。

runQwenServe 的文件服务默认 trusted:true;直接 createServeApp 未提供相应依赖时默认 trusted:false 并警告,ACP 文本写入可能因此拒绝为 untrusted_workspace。两种入口不能按同样信任默认值理解。

内部 embedding 生命周期

runQwenServe 返回含实际 url、port、close() 的 handle,支持端口 0 解析后的真实值。createServeApp 只返回 Application。

需要 Live/Conversations 的内部宿主必须在首次 listen 前调用 getServeAppLifecycle(app).bindServer(server),关闭时 await lifecycle.close()。未绑定时普通路由仍可能可用,但 Live/Conversations 会拒绝运行。

直接 server.close() 触发事件清理,不等于宿主已观察到全部 drain 和 ownership-release 结果;仍要等待生命周期 close。

两阶段退出

首次 SIGINT/SIGTERM 封闭新工作并开始 drain,取消设备认证流程,bridge 将 child 标为 isDying 后关闭。ACP child 有 10 秒硬期限;HTTP server.close 停止接收新连接,5 秒后强制关闭连接,另有 2 秒二次升级期限。

Conversations ownership 只在 listener、app、host、Live discovery 和 runtime 都给出成功关闭证明后释放;证明不完整会拒绝关闭结果,而不是宣告可以安全接管。

退出期间再次收到信号会同步 killAllSync 并以 1 退出,避免遗留 child。关闭请求发出、连接消失和所有资源已安全释放是不同状态。