文档中心

探索 DWeb 框架的无限可能,构建下一代高性能 Web 应用

优雅关闭 (shutdown)

DWeb 框架提供了优雅关闭功能,确保服务器在关闭时能够正确处理未完成的请求和清理资源。

快速开始

基本使用

Code
import { setupSignalHandlers, registerShutdownHandler } from "@dreamer/dweb";
import { Server } from "@dreamer/dweb";

const server = new Server();

// 设置信号监听器(自动处理 SIGTERM 和 SIGINT)
setupSignalHandlers(server);

// 注册关闭处理器(清理资源)
registerShutdownHandler(async () => {
  console.log("关闭数据库连接...");
  await database.close();
});

registerShutdownHandler(async () => {
  console.log("清理临时文件...");
  await cleanupTempFiles();
});

// 启动服务器
await server.start(3000);

工作原理

Code
优雅关闭流程包括以下步骤:

1. 停止接收新请求:服务器停止接受新的连接
2. 等待现有请求完成:给现有请求一定时间完成处理
3. 执行关闭处理器:按注册顺序的逆序执行所有关闭处理器
4. 退出进程:正常退出或错误退出

完整示例

Code
import { Server } from "@dreamer/dweb";
import { setupSignalHandlers, registerShutdownHandler } from "@dreamer/dweb";
import { Database } from "./database";

const server = new Server();
const database = new Database();

// 注册关闭处理器
registerShutdownHandler(async () => {
  console.log("关闭数据库连接...");
  await database.close();
});

registerShutdownHandler(async () => {
  console.log("关闭 Redis 连接...");
  await redis.quit();
});

registerShutdownHandler(async () => {
  console.log("保存应用状态...");
  await saveApplicationState();
});

// 设置信号监听器
setupSignalHandlers(server);

// 配置服务器
server.setHandler(async (req, res) => {
  res.text("Hello World");
});

// 启动服务器
await server.start(3000);
console.log("服务器运行在 http://localhost:3000");

Docker 环境

在 Docker 容器中,优雅关闭特别重要:

Code
# Dockerfile
FROM denoland/deno:latest

# 设置信号处理
STOPSIGNAL SIGTERM

# 运行应用
CMD ["deno", "run", "-A", "main.ts"]
Code
// main.ts
import { setupSignalHandlers } from "@dreamer/dweb";

const server = new Server();
setupSignalHandlers(server);

await server.start(3000);

关闭处理器执行顺序

Code
// 关闭处理器按照注册顺序的逆序执行(后注册的先执行)

// 注册顺序
registerShutdownHandler(() => console.log("1"));
registerShutdownHandler(() => console.log("2"));
registerShutdownHandler(() => console.log("3"));

// 执行顺序:3 -> 2 -> 1

// 这样设计是为了确保:
// - 最后注册的处理器(通常是关键资源)最先执行
// - 先注册的处理器(通常是次要资源)最后执行

API 参考

registerShutdownHandler(handler)

注册一个关闭处理器,在服务器关闭时执行。

Code
registerShutdownHandler(async () => {
  // 关闭数据库连接
  await db.close();
  
  // 清理缓存
  await cache.clear();
  
  // 保存状态
  await saveState();
});

setupSignalHandlers(server)

设置系统信号监听器,自动处理 `SIGTERM` 和 `SIGINT` 信号。

Code
const server = new Server();
setupSignalHandlers(server);

gracefulShutdown(signal, server)

手动触发优雅关闭流程。

Code
await gracefulShutdown("SIGTERM", server);

最佳实践

  • 注册所有资源清理:数据库连接、Redis 连接、文件句柄、定时器、WebSocket 连接
  • 处理异步操作:确保所有异步操作在关闭前完成,使用 await 等待异步清理
  • 错误处理:关闭处理器中的错误不会阻止其他处理器执行,记录所有错误以便调试
  • 测试优雅关闭:在开发环境中测试关闭流程,确保所有资源正确清理

注意事项

  • 优雅关闭仅在收到 SIGTERMSIGINT 信号时触发
  • 强制终止(SIGKILL)无法被捕获,不会执行关闭处理器
  • 确保关闭处理器不会执行过长时间的操作
  • 在生产环境中,确保进程管理器配置了合理的超时时间

相关文档