ckeditor不正确的服务器响应_【译文】正确关闭Node.js的应用程序

正确的关闭你的应用是非常重要的,它可以很好处理请求同时防止它接受新的请求。我以web服务器举例。

const http = require('http');const server = http.createServer(function (req, res) {  setTimeout(function () {    res.writeHead(200, {'Content-Type': 'text/plain'});    res.end('Hello World\n');  }, 4000);}).listen(9090, function (err) {  console.log('listening http://localhost:9090/');  console.log('pid is ' + process.pid);});

e8304737c4424a2fbcdca733469ddc60.gif

正如我们所见,我们的服务器没有关闭,而且处理请求没有获得正确的响应。处理它之前我们需要先理解如何终止一个Node进程。

进程在它即将被终止时会接收到一个信号。它们是各种不同的信号,我们将特别关注其中三个:

    • 信号情报:键盘退出(Ctrl+C)。

    • 终止信号:键盘退出(Ctrl +)。它还会生成一个核心转储文件。

    • 软件终止:退出操作系统(例如使用kill命令)。

当进程接收到信号时,Node.js会发出事件。你可以为这些事件编写程序。在这一步中我们将关闭我们的服务器,以便处理正挂起的请求并防止接入新的请求。

function handleExit(signal) {  console.log(`Received ${signal}. Close my server properly.`)  server.close(function () {    process.exit(0);  });}process.on('SIGINT', handleExit);process.on('SIGQUIT', handleExit);process.on('SIGTERM', handleExit);

677a7869e2962acd699728e437c2ac73.gif

现在我们的服务器处理好请求之后正确的关机了。在Nairi Harutyunyan的文章中你可以了解到更多。它详细说明了如何正确地关闭带有数据库的服务器。

还存在一个node模块可以为你处理这种逻辑,你可以叫它“死亡”(由JP Richardson创造)。

const ON_DEATH = require('death')ON_DEATH(function(signal, err) {  // clean up code here})

但这个可能是不够的

我最近遇到了一个情况,我的服务器需要接受新的请求,以便正确关机。我来详细解释一下,我的服务器订阅了一个webhook,这个webhook有订阅名额限制。因此,如果我不想超过此配额,则在服务器关闭时需要正确地取消订阅。这里是取消订阅的工作流:

  1. 向webhook发送一个请求取消订阅。

  2. webhook向服务器发送一个请求来确认取消订阅。

  3. 服务器必须使用特定的令牌进行响应,以验证取消订阅。

一个Node.js进程会在它的事件循环为空时自动关闭,正如你所见到的在1和2之间,事件循环是空的所以进程将会被终止,以至于我们无法成功取消订阅。

这是我们的新服务器代码库:

const server = http.createServer(function (req, res) {  const params = qs.decode(req.url.split("?")[1]);  if (params.mode) {    res.writeHead(200);    res.write(params.challenge);    res.end();  } else {    let body = "";    req.on("data", chunk => {      body += chunk;    });    req.on("end", () => {      console.log('event', JSON.parse(body))      res.writeHead(200);      res.end();    });  }}).listen(9090, function (err) {  console.log('listening http://localhost:9090/');  console.log('pid is ' + process.pid);  fetch('http://localhost:3000/webhook?mode=subscribe&callback=http://localhost:9090')});

这里有两个改变,当服务器开始监听9090端口时,我们发送第一个请求使得我们的服务器订阅webhook。

//fetch('http://localhost:3000/webhook?mode=subscribe&callback=http://localhost:9090')//

我们还更改了服务器的请求处理程序,让它通过响应称为“challenge”的令牌来确认对webhook的订阅。

// ...if (params.mode) {  res.writeHead(200);  res.write(params.challenge);  res.end();} else { // ...}// ...

改变handleExit函数来发送一个请求到我们的webhook。我们请求webhook取消我们服务器的订阅。

function handleExit(signal) {  console.log(`Received ${signal}. Close my server properly.`)  fetch('http://localhost:3000/webhook?mode=unsubscribe&callback=http://localhost:9090')}

我们需要更新代码,处理当webhook确认取消订阅时,服务器能通过“challenge”令牌来终止我们的进程。

// ...if (params.mode) {  res.writeHead(200);  res.write(params.challenge);  res.end();  if (params.mode === 'unsubscribe') {    server.close(function () {      process.exit(0);    });  }} else {  // ...}// ...

当webhook确认取消订阅时,我们关闭服务器,这样它就停止接收新的请求并正确地退出我们的进程。这就是Twitch API Webhooks订阅/取消订阅的工作方式。

让我们来看看当我们试图关闭服务器时服务器是如何工作的。我添加了一些日志,让它更加直观。

1f3aa2dc455fe84b6075c4296f5e0d00.gif如您所见,它无法正常关闭。在我们收到确认取消订阅的webhook请求之前,服务器的进程已终止。因此,webhook不断将事件发送到我们的服务器。

要解决这个问题,我们需要防止Node.js进程退出。我们可以使用process.stdin.resume方法让进程暂停并且覆盖禁用默认行为(如退出时按Ctrl+C)。

const http = require('http');process.stdin.resume();// ...

那么现在呢?

3a2cd3af51c3874ad7d10fb952bb59cb.gif不错,它现在在退出进程之前等待确认。

我用本文中提供的所有源代码创建了一个git仓库[链1]。希望能对你有所帮助。

[链1]:https://github.com/frinyvonnick/node-shutdown-properly-webhooks

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值