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()) }
|