据我所知,默认的http路由器以及大猩猩/多路复用器路由器将每个传入的HTTP请求入口点放在自己的goroutine中。就像Node.js域一样,我们可以将请求固定到域,是否可以将Golang中的请求固定到goroutine,如果goroutine中出现任何恐慌,我们将以错误响应而不是关闭服务器? / p>
在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做类似的事情?
答案 0 :(得分:3)
net / http服务器为每个连接启动一个goroutine,并在该goroutine上调用根处理程序。我所知道的所有路由器都通过调用goroutine上的已注册处理程序进行调用。通常在net / http服务器上启动的goroutine中调用一种或另一种处理程序。除非请求处理程序直接或间接启动另一个goroutine代表请求处理程序执行工作,否则所有对请求的执行都在该goroutine上进行。由于请求处理程序可以控制所使用的goroutine,因此无需将goroutine固定在请求中。
net / http服务器恢复每个连接goroutine的崩溃。这就是the documentation says about it:
如果ServeHTTP出现紧急情况,则服务器(ServeHTTP的调用方)将假定紧急情况的影响与活动请求无关。它恢复紧急状态,将堆栈跟踪记录到服务器错误日志中,然后关闭网络连接或发送HTTP / 2 RST_STREAM,具体取决于HTTP协议。要中止处理程序,以便客户端看到中断的响应,但服务器不会记录错误,请惊慌于ErrAbortHandler值。
请求处理程序可以与中间件包装在一起,以使用应用程序提供的逻辑来恢复紧急情况。 Gorilla handlers package是如何执行此操作的一个示例。
如果请求处理程序确实启动了goroutine来代表请求进行工作,则在该goroutine中建立恢复是请求处理程序的责任。
答案 1 :(得分:2)
是的,您可以从goroutine恐慌中恢复过来。大猩猩的middleware可以做到,但您自己也很容易。基本上,这只是将处理程序包装在一个函数中,该函数推迟调用recover()
并从那里处理紧急情况。