首页 > 解决方案 > 将 Golang goroutine 或通道固定到请求/响应

问题描述

据我所知,默认的 http 路由器以及 gorilla/mux 路由器将每个传入的 HTTP 请求入口点放在自己的 goroutine 上。像 Node.js 域一样,我们可以将请求固定到域,我们可以将 Golang 中的请求固定到 goroutine,如果 goroutine 中有任何恐慌,我们会以错误响应而不是关闭服务器?

在 node.js 中,它可能看起来像:

const domain = require('domain');
const http = require('http');

const server = http.createServer((req,res) => {

  const d = domain.create();

  d.once('error', e =>{
     res.json({error:e}); // check res.headersSent to see if already sent
  });

  res.once('finish', () => {
     d.removeAllListeners(); // prevent memory leak
  });

  d.run(() => {
     handleRequest(req,res);
  });


});

有没有办法在 Golang 中使用 goroutines 做类似的事情?

标签: go

解决方案


net/http 服务器为每个连接启动一个 goroutine 并调用该 goroutine 上的根处理程序。我所知道的所有路由器都通过调用路由器的 goroutine 上的注册处理程序进行调用。通常在 net/http 服务器上启动的 goroutine 上调用一种或另一种处理程序。请求的所有执行都在该 goroutine 上,除非请求处理程序直接或间接启动另一个 goroutine 来代表请求处理程序工作。因为请求处理程序控制着所使用的 goroutine,所以没有必要将 goroutine “固定”到请求上。

net/http 服务器在每个连接 goroutine 上恢复恐慌。这是文档中有关它的内容

如果 ServeHTTP 发生恐慌,服务器(ServeHTTP 的调用者)假定恐慌的影响与活动请求隔离。它恢复恐慌,将堆栈跟踪记录到服务器错误日志,然后关闭网络连接或发送 HTTP/2 RST_STREAM,具体取决于 HTTP 协议。要中止处理程序以使客户端看到中断的响应但服务器不记录错误,请使用值 ErrAbortHandler 恐慌。

请求处理程序可以用中间件包装,以使用应用程序提供的逻辑来恢复恐慌。Gorilla handlers 包是如何做到这一点的一个例子。

如果请求处理程序确实启动了一个 goroutine 来代表请求执行工作,则请求处理程序有责任在该 goroutine 中建立恢复。


推荐阅读