跳到正文
FunCoding

搜索

搜索文档、Skill 和 MCP

Serve 启动与关闭

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

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。关闭请求发出、连接消失和所有资源已安全释放是不同状态。