如何协调并发的请求-响应流程?

huangapple go评论78阅读模式
英文:

How can I orchestrate concurrent request-response flow?

问题

我是新手并不了解并发编程的概念,也不知道从哪些概念开始学习,请你温柔点。

我正在编写一个作为TCP服务器前端的Web服务。这个服务器监听我指定的端口,并将每个请求的响应返回给TCP连接。

以下是我编写Web服务前端的原因:

  • 服务器一次只能处理一个请求,我想让它能够同时处理多个输入,通过启动多个进程并让它们监听不同的端口来实现。例如,我想启动30个实例,并告诉它们监听20000-20029端口。
  • 我们的团队使用PHP,而PHP没有能力启动服务器实例并同时维护它们,所以我想编写一个API,让他们可以向其发送HTTP请求。

所以,这是我考虑的结构。

  1. 我将有一个main()函数。这个函数同时启动进程,然后在端口80上启动HTTP服务器并监听。
  2. 我有一个http.Handler,它将请求的内容添加到一个通道中。
  3. 我将有多个goroutine,每个服务器实例一个,它们都在一个无限循环中。

第三条中提到的函数的代码可能如下所示:

func handleRequest(queue chan string) {
    for {
        request := <-queue
        conn, err := connectToServer()
        err = sendRequestToServer(conn)
        response, err := readResponseFromServer(conn)
    }
}

因此,我的http.Handler可以简单地执行queue <- request将请求添加到队列中,而已经阻塞等待通道有内容的handleRequest将获取请求并继续执行。完成后,循环结束,执行回到request := <-queue,然后继续相同的过程。

我的问题出现在http.Handler中。将请求放入通道中是有道理的,因为多个goroutine都在监听它。然而,这些goroutine如何将结果返回给我的http.Handler呢?

一种方法是使用一个通道,让我们称之为responseQueue,所有这些goroutine都会向其中写入响应。问题是,当将响应添加到通道时,我不知道它属于哪个请求。换句话说,当多个http.Handler发送请求时,每个执行处理程序都不知道通道中当前消息属于哪个响应。

是否有最佳实践或模式,可以从一个goroutine向另一个goroutine发送数据并接收数据返回?

英文:

I'm new to concurrent programming, and have no idea what concepts to start with, so please be gentle.

I am writing a webservice as a front-end to a TCP server. This server listens to the port I give it, and returns the response to the TCP connection for each request.

Here is why I'm writing a web-service front-end for this server:

  • The server can handle one request at a time, and I'm trying to make it be able to process several inputs concurrently, by launching multiple processes and giving them a different port to listen on. For example, I want to launch 30 instances and tell them to listen on ports 20000-20029.
  • Our team uses PHP, and PHP does not have the capacity to launch server instances and maintain them concurrently, so I'm trying to write an API they can just send HTTP requests to.

So, here is the structure I have thought of.

  1. I will have a main() function. This function launches the processes concurrently, then starts an HTTP server on port 80 and listens.
  2. I have an http.Handler that adds the content of a request to a channel,.
  3. I will have gorutines, one per server instance, that are in an infinite loop.

The code for the function mentioned in item three would be something like this:

func handleRequest(queue chan string) {
    for {
        request := &lt;-queue
        conn, err := connectToServer()
        err = sendRequestToServer(conn)
        response, err := readResponseFromServer(conn)
    }
}

So, my http.Handler can simply do something like queue&lt;- request to add the request to the queue, and handleRequest, which has blocked, waiting for the channel to have something to get, will simply get the request and continue on. When done, the loop finishes, execution comes back to the request := &lt;-queue, and the same thing continues.

My problem starts in the http.Handler. It makes perfect sense to put requests in a channel, because multiple gorutines are all listening to it. However, how can these gorutines return the result to my http.Handler?

One way is to use a channel, let's call it responseQueue, that all of these gorutines would then write to. The problem is that when a response is added to the channel, I don't know which request it belongs to. In other words, when multiple http.Handlers send requests, each executing handler will not know which response the current message in the channel belongs to.

Is there a best practice, or a pattern, to send data to a gorutine from another gorutine and receive the data back?

答案1

得分: 1

创建一个每个请求响应通道,并将其包含在发送给工作程序的值中。处理程序从通道接收。工作程序将结果发送到通道中。

英文:

Create a per request response channel and include it in the value sent to the worker. The handler receives from the channel. The worker sends the result to the channel.

huangapple
  • 本文由 发表于 2016年1月11日 17:52:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/34718430.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定