Golang 线程池实现http异步响应

参考:https://blog.csdn.net/weixin_44211968/article/details/123048160

最近在用golang改写一个模型服务接口,之前的开发人员用的echo框架,是常见的http方式,不支持多线程的方式,为了提高并发 ,想用多线程(go routine)。若直接go func()的方式,每次来请求,都开一个线程,会导致线程的数量不受控制。在请求数量未知的情况下,怎么可以控制线程数量,复用线程?这就是线程池的概念。上述链接中的代码很有代表性,总结起来模式就两点:

1. 用for循环开启指定数量的线程,然后让每个线程不停地遍历读取同一个管道,从管道中读取任务信息并进行处理;

2. 每次来请求的时候,把请求信息包装一下,放入管道即可,无需其他操作。

这样,客户端请求一进来就被放进管道,而一放进管道就会被早已等待多时的各个线程处理掉,而线程的数量又是恒定的,在不断地跑,可以重复利用,这样就实现了线程池。

以下代码就是一个带线程池的Golang web服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package main
 
import (
    "encoding/json"
    "fmt"
    "net/http"
    "time"
)
func Write_JSON(data map[string]interface{}, w http.ResponseWriter) {
    bytes, _ := json.Marshal(data)
    w.Write(bytes)
}
 
func GenerateResponse(w http.ResponseWriter, r *http.Request) {
    //处理业务请求的方法
    fmt.Printf("handle request:%s\n", r.RequestURI)
    data := make(map[string]interface{})
    data["id"] = r.URL.Query().Get("id")
    data["host"] = r.Host
    data["tm"] = time.Now().UnixMilli() % 10000
    //把结果写入response
    Write_JSON(http.StatusOK, data, w)
}
 
 
type Context struct {
    response http.ResponseWriter
    request  *http.Request
}
 
func HandleAllRequest(w http.ResponseWriter, r *http.Request) {
    //处理请求的方法只需把请求放入管道进行排队
    contextChan <- &Context{response: w,request: r}
}
 
//启动多个worker线程
func CreateWorkers(num_workers int, contextChan chan *Context) {
    for i := 0; i < num_workers; i++ {
        go func(contextChan chan *Context) {
            //每个线程读取管道中的请求任务
            for context := range contextChan {
                //用指定方法处理获取到的上述请求
                GenerateResponse(context.response, context.request)
            }
        }(contextChan)
    }
}
 
//任务(请求)管道
var contextChan chan *Context
 
func main() {
    num_workers := 32 //指定线程个数
    contextChan = make(chan *Context, 10) //初始化任务管道
    CreateWorkers(num_workers, contextChan) //启动多个处理请求的线程
 
    http.HandleFunc("/sayhi", HandleAllRequest) //指定处理请求的方法
    fmt.Printf("Server is running.\n")
    http.ListenAndServe(":8888", nil) //指定Http服务的运行端口
}

  

posted @   morein2008  阅读(1903)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示