我正在尝试构建一个系统(工作池/作业队列),以在每个API端点上处理尽可能多的http requests。 我研究了这个示例,并使其工作正常,只是我偶然发现了一个问题,即我不知道如何将pool / jobqueue扩展到不同的端点。

出于场景考虑,让我们概述一个Golang http服务器,该服务器在不同的端点和请求类型GETPOST ETC上的请求数/分钟为一百万。

我如何扩展这个概念? 我应该为每个端点创建不同的工作池和作业。 还是可以创建不同的作业,然后将它们输入相同的队列并由相同的池来处理这些作业?

我想保持简单性,如果我创建一个新的API端点,则不必创建新的工作程序池,因此我可以只关注api。 但是性能也非常重要。

我要构建的代码取自前面链接的示例,这是使用此代码的其他人的github"要点"。


前面的一件事:如果您正在运行HTTP服务器(无论如何是Go的标准服务器),则无法在不停止和重新启动服务器的情况下控制goroutine的数量。每个请求至少启动一个goroutine,对此您无能为力。好消息是,这通常不是问题,因为goroutine非常轻便。但是,完全希望控制辛苦工作的goroutine的数量是完全合理的。

您可以将任何值(包括函数)放入通道。因此,如果目标是只需要在http处理程序中编写代码,则将作业设为闭包-工人不知道(或不在乎)他们在做什么。

这是一个非常简单的例子,可以帮助您理解这一点。如何设置工作池并不重要。您只需要一个聪明的工作定义。在上面的示例中,它是一个闭包,但是您也可以定义一个Job接口,例如。

现在,我不会将整个工作人员池方法称为"简单"方法。您说您的目标是限制(正在工作的)goroutine的数量。那根本不需要工人。它只需要一个限制器。这是与上面相同的示例,但是使用通道作为信号量来限制并发。


如之前在服务器中回答的那样,每个请求处理程序将至少在一个goroutine中运行。

但是,如有必要,您仍然可以将工作池用于后端并行任务。例如,假设您的某些Http Handler函数触发了对其他外部api的调用,并将它们的结果"聚合"在一起,因此在这种情况下调用的顺序无关紧要,在这种情况下,您可以利用工作池并分发您的工作池为了使它们并行运行而进行的工作,将每个任务分派给工作人员goroutine:

示例代码段:

。异步运行"通用"任务的工作池的完整示例:https://github.com/guilhebl/go-offer/blob/master/offer/repo.go

。使用的工人池库:https://github.com/guilhebl/go-worker-pool


目前尚不清楚为什么根本需要工人池? goroutines不够吗?

如果您受到资源的限制,则可以考虑实施速率限制。如果不是,为什么不根据需要简单地遍历go例程?

最好的学习方法是研究他人如何做好事。

看看https://github.com/valyala/fasthttp

Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http.

他们声称:

serving up to 200K rps from more than 1.5M concurrent keep-alive connections per physical server

这非常令人印象深刻,我怀疑您可以使用pool / jobqueue做得更好。