服务器崩溃或扩展重载时客户端怎么处理?
结论
语言客户端要监听服务器退出和错误,把错误写到输出通道,并按策略重启。扩展重载或停用时要先 shutdown 再停进程,同时释放客户端。重启后文档要重新 didOpen,因为新进程没有旧副本。
展开
vscode-languageclient 可以配置错误处理器:进程异常退出时选择重启、关闭,或不处理。一般对语言服务器使用有限次数的自动重启,避免崩溃循环把 CPU 打满。连续失败就停下来,在输出通道写清退出码和 stderr,告诉用户去看日志。
日志分开:
- 客户端日志:启动参数、重启、掉线
- 服务器日志:语言自己的栈
- 协议 trace:只在排查时打开,量很大
扩展重载(开发时的重新加载窗口,或用户禁用插件)会走 deactivate。client.start() 返回的 Disposable 放进订阅后,宿主会停客户端。停的过程应发送 shutdown 和 exit。如果服务器是服务器自己拉起的孙子进程,客户端退出时也要把它们一起收掉。
重启成功后,客户端需要对仍然打开的文档重新同步。不要假设服务器还记得重启前的未保存文本。诊断也要等新进程重新发布,旧波浪线应由客户端清掉,避免显示已经不存在的服务器会话留下的结果。
远程窗口里,服务器进程在远端。远端断开时,客户端会跟着工作区宿主一起掉线。重连后应当整段重新初始化,而不是只补一条 didChange。
容易讲错的点
- 无限重启会在配置错误时死循环。要有次数和退避。
- 崩溃不等于用户代码有错。先分清是服务器起不来(路径、运行时)还是请求处理抛错。
- 把服务器嵌进扩展宿主进程「就不用处理崩溃」是反的。那样一崩,整个扩展宿主一起没。