1. 介绍
fasthttp是由valyala
编写,并宣称比Go
官方标准库net/http
快十倍。fasthttp
采用了许多性能优化上的最佳实践,尤其是在内存对象的重用上,大量使用sync.Pool以降低对Go GC
的压力。
推荐文章: Go标准库http与fasthttp服务端性能比较:https://tonybai.com/2021/04/25/server-side-performance-nethttp-vs-fasthttp/
2.工作原理
2.1 net/http
工作原理示意图
a. 流程说明
http
包作为server
端的原理很简单,那就是accept
到一个连接(conn
)之后,将这个conn
甩给一个worker goroutine
去处理,后者一直存在,直到该conn
的生命周期结束:即连接关闭。
2.2 fasthttp
工作原理示意图
fasthttp
高性能主要源自于复用,fasthttp
设计了一套机制,目的是尽量复用goroutine
,而不是每次都创建新的goroutine
。
a. 流程说明
当fasthttp
的Server
接到一个conn
之后,会尝试从workerpool
中的ready
切片中取出一个channel
,该channel
与某个worker goroutine
一一对应。
一旦取出channel
,就会将accept
到的conn
写到该channel
里,而channel
另一端的worker goroutine
就会处理该conn
上的数据读写。
当处理完该conn
后,该worker goroutine
不会退出,而是会将自己对应的那个channel
重新放回workerpool中的ready
切片中,等待这下一次被取出。
3. 安装
go get -u github.com/valyala/fasthttp
|
4. 使用
4.1 自定义客户端配置
func getFastReqClient() *fasthttp.Client { reqClient := &fasthttp.Client{ ReadTimeout: time.Second * 5, WriteTimeout: time.Second * 5, MaxIdleConnDuration: time.Second * 5, NoDefaultUserAgentHeader: true, DisableHeaderNamesNormalizing: true, DisablePathNormalizing: true, Dial: (&fasthttp.TCPDialer{ Concurrency: 4096, DNSCacheDuration: time.Hour, }).Dial, } return reqClient }
|
4.2 发起GET
请求
func FastGetWithDo() string { client := getFastReqClient() req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse() defer func() { fasthttp.ReleaseRequest(req) fasthttp.ReleaseResponse(resp) }() req.Header.SetMethod(fasthttp.MethodGet) req.SetRequestURI("http://127.0.0.1/test") var arg fasthttp.Args arg.Add("name", "张三") arg.Add("id", "10001") req.URI().SetQueryString(arg.String()) req.Header.Add(HAppIdKey, HAppIdVal) req.Header.SetCookie("key", "val") if err := client.Do(req, resp); err != nil { fmt.Println("req err ", err) return err.Error() } return string(resp.Body()) }
|
4.3 发起POST
请求
type postParamExample struct { Id int `json:"id,omitempty"` Name string `json:"app_id_list,omitempty"` }
func FastPostRawWithDo() string { client := getFastReqClient() req, resp := fasthttp.AcquireRequest(), fasthttp.AcquireResponse() defer func() { fasthttp.ReleaseRequest(req) fasthttp.ReleaseResponse(resp) }() req.Header.SetMethod(fasthttp.MethodPost) req.SetRequestURI("http://127.0.0.1/test") req.Header.SetContentType("application/json") param := postParamExample{ Id: 10001, Name: "小明", } marshal, _ := json.Marshal(param) req.SetBodyRaw(marshal) if err := client.Do(req, resp); err != nil { fmt.Println("req err ", err) return err.Error() } return string(resp.Body()) }
|