gin启动和请求流程,压测
分析
new一个Engine代表gin服务
g := gin.Default()
gin启动
g.Run
http监听服务
http.ListenAndServe
server监听服务
server.ListenAndServe()
监听连接
ln, err := net.Listen("tcp", addr)
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
等待客户端链接
rw, e := l.Accept()
new一个客户端并go一条groutine来处理当前请求
c := srv.newConn(rw)
go c.serve(ctx)
读请求内容,处理请求
w, err := c.readRequest(ctx)
serverHandler{c.server}.ServeHTTP(w, w.req)
serverHandler调用ServeHTTP处理当前请求
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
handler.ServeHTTP
获得路由对应的handler调用ServeHTTP来处理当前的请求
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
获得路由对应的handler和pattern
handler.ServeHTTP(rw, req)
- ServeMux实现了Handler方法,所以会调用到(mux* ServeMux) Handler
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux
func (mux* ServeMux) Handler(r* Request) (h Handler, pattern string)
mux.handler(host, r.URL.Path)
h, pattern = mux.match
- 匹配路由对应的handler
真正的路由响应函数调用
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
思路
通过注册路由和handle函数到路由表中,路由表构建一棵tree。然后就启动listen和accept,有新连接来就new一个conn对象代表当前连接,然后go一条协程单独处理当前请求。接着通过serverHandler和ServeMux实现的ServeHTTP解析路由匹配到handle和pattern,最后通过得到的handler调用真正的路有响应函数处理请求。主要借助了结构体和接口的形式,层层封装代理,直至到在最后的处理响应。
总结
gin就是一个轻量级,高效,方便的web 框架,更偏向于应用服务。
压测gin
附带gin的压测
wrk -c 100 -t 10 -d 10m http://172.16.1.11:8090/hello
- 开10条线程,100并发。
电脑配置
- 双核 Intel® Core™ i5-4210M CPU @ 2.60GHz
- 8.1 GB 内存
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
g := gin.Default()
g.GET("/hello", func(context *gin.Context) {
context.JSON(200, gin.H{
"hello":1,
})
})
fmt.Println(g.Run(":8090").Error())
}
结果:
Running 10m test @ http://172.16.1.11:8090/hello
10 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 14.77ms 20.79ms 119.25ms 82.05%
Req/Sec 1.95k 538.61 5.05k 68.19%
2930271 requests in 2.61m, 377.26MB read
Socket errors: connect 0, read 143, write 765925, timeout 0
Requests/sec: 18692.82
Transfer/sec: 2.41MB
Running 10m test @ http://172.16.1.11:8090/hello
10 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.67ms 13.81ms 96.16ms 88.72%
Req/Sec 2.67k 694.90 5.72k 67.32%
836443 requests in 31.45s, 107.69MB read
Requests/sec: 26599.34
Transfer/sec: 3.42MB
看压测结果,gin上万qps是比较轻松的。