This is a creation in Article, where the information may have evolved or changed.
Objective
Because Golang provides a complete library of net/http standards, the difficulty of implementing a Web framework based on the standard library is much lower than in other languages, so the Go web framework is simply a flowering. From the old Revel and Beego, to the new gin, and Iris, and some like the router of Chi. Personal general small projects, especially middleware needs to expose some HTTP interface, the basic use of Chi can be.
This test is mainly the gin iris echo of the three frames. Focus on high performance, from concurrency and JSON serialization and deserialization two aspects to evaluate, after all, background projects focus on these two aspects.
Test
Test environment Description
In order to select a framework that conforms to the heavy IO, the specific requirements for the following scenarios are set Demo,demo:
- Turn on logging (logs are also logged when impersonating a normal business), recording a log separately at the beginning and end of a request
- Interface with sleep pause for 1 seconds, assuming the network IO operation here (and also more easily from the log to see if the behavior of the co-process concurrency)
- Use the Post interface to do the test, the interface does not do any processing, the received body directly serialized return (serialization and deserialization is the framework of the highest frequency action)
- Open the Accesslog function of a frame
Test tools and scenarios are as follows
- Test tools use the classic JMeter to test directly with the GUI interface
- Scenarios are divided into 10 thread concurrency, 100 thread concurrency, 500 thread concurrency, 1000 thread concurrency, and 1500 thread concurrency
- All results only look at JMeter aggregation reports, focusing on throughput, time, and number of errors
- All demos start with a single thread, and the async framework does not limit the number of threads, setting Gomaxprocs=1
- All tests are local, two minutes of pressure measurement
- Post requests are tested with data samples of 565bytes, 5KB, 10KB, 50KB, and 100KB, each tested on a different concurrent thread
Test code
Gin
Package Mainimport ("Log" "Net/http" "Time" "Github.com/gin-gonic/gin")//Agent ... type agent struct {age Ntid string ' JSON: ' agent_id ' ' Queuedat string ' json: ' Queued_at ' ' Queuedby string ' json: ' queued_by ' '}//Details ... t ype Details struct {EventID string ' JSON: "event_id" ' Endpoint string Metric string Content string Prio rity int Status string}//Test1 ... type Test1 struct {agent agent details details Description str ing EventType string ' json: ' Event_type ' ' Servicekey string ' json: ' Service_key ' '}//Test2 test2type Test2 struct { Data []*test1}func Main () {r: = gin. New ()//Global middleware//Logger middleware would write the logs to gin. Defaultwriter even if you set with Gin_mode=release. By default gin. Defaultwriter = OS. Stdout R.use (gin. Logger ()) R.get ("/ping", func (c *gin). Context) {C.json, gin. h{"message": "Pong",})}) R.post ("/v1/test", Func (c*gin. Context) {var test Test1 if Err: = C.bindjson (&test); err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.post ("/v2/test", func (c *gin). Context) {var test Test2 if Err: = C.bindjson (&test); err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.post ("/v3/test", func (c *gin). Context) {var test Test2 if ERr: = C.bindjson (&test); Err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.post ("/v4/test", func (c *gin). Context) {var test Test2 if Err: = C.bindjson (&test); err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.run ()//listen and serve on 0.0.0.0:8080}
Iris:
Package Mainimport ("Time" "Github.com/kataras/iris" "Github.com/kataras/iris/middleware/logger")//Agent ... Typ E Agent struct {agentid string ' JSON: ' agent_id ' ' Queuedat string ' json: ' Queued_at ' ' Queuedby string ' JSON: ' Queu Ed_by "'}//details ... type details struct {EventID string ' JSON: ' event_id ' ' Endpoint string Metric string Content string Priority int Status string}//Test1 ... type Test1 struct {Agent agent Details Det Ails Description string EventType string ' JSON: ' Event_type ' ' Servicekey string ' json: ' Service_key ' '}//Test2 t Est2type Test2 struct {Data []*test1}func main () {app: = Iris. New () app. Use (logger. New ()) app. Get ("/ping", func (c Iris). Context) {c.writestring ("Pong")}) app. Post ("/v1/test", func (c Iris). Context) {var test Test1 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") Time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io=======================") C.json (test)} else {C.wri Testring ("Failure")}) app. Post ("/v2/test", func (c Iris). Context) {var test Test2 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io=======================") C.json (test)} else {C.wri Testring ("Failure")}) app. Post ("/v3/test", func (c Iris). Context) {var test Test2 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io======================= ") C.json (test)} else {c.writestring (" failure ")} }) app. Post ("/v4/test", func (c Iris). Context) {var test Test2 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io=======================") C.json (test)} else {C.wri Testring ("Failure")})//Start the server using a network address. App. Run (Iris. ADDR (": 8080"),//Disables Updates:iris. Withoutversionchecker,//Skip ERR server closed when Ctrl/cmd+c Pressed:iris. Withoutservererror (Iris. errserverclosed),//enables faster JSON serialization and More:iris. Withoptimizations)}
Echo:
Package Mainimport ("Log" "Net/http" "Time" "Github.com/labstack/echo" "Github.com/labstack/echo/middlewar E ")//Agent ... type agent struct {agentid string ' JSON:" agent_id "' Queuedat string ' JSON:" Queued_at "' Queuedby String ' JSON: ' queued_by '}//details ... type details struct {EventID string ' JSON: ' event_id ' ' Endpoint string M Etric string Content string priority int Status string}//Test1 ... type Test1 struct {agent agent Details Description string EventType string ' JSON: "Event_type" ' Servicekey string ' JSON: "Servic E_key "'}//Test2 test2type Test2 struct {Data []*test1}func Main () {//echo instance app: = Echo. New ()//middleware app. Use (middleware. Logger ())//Routes app. GET ("/ping", Func (c echo.) Context) Error {return c.string ("Pong")}) app. POST ("/v1/test", Func (c echo.) Context) error {var test Test1 if Err: = C.bind (&test); Err! = Nil { Return err} log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") return C.json (http. Statusok, Test)}) app. POST ("/v2/test", Func (c echo.) Context) error {var test Test2 if Err: = C.bind (&test); Err! = nil {return err} Log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") return C.json (http. Statusok, Test)}) app. POST ("/v3/test", Func (c echo.) Context) error {var test Test2 if Err: = C.bind (&test); Err! = nil {return err} Log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io======================= ") return C.json (http. Statusok, Test)}) app. POST ("/v4/test", Func (c echo.) Context) error {var test Test2 if Err: = C.bind (&test); Err! = nil {return err} Log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") return C.json (http. Statusok, Test)})//Start server app. Logger.fatal (app. Start (": 8080"))}
- In addition to Echo, the three other JSON serialization libraries that natively support the performance of Jsoniter are enabled.
- Wait 1s, analog io read/write wait
Test comparison
Due to the testing of 5 body samples, 4 scenarios, 4 frames, the key data is filtered out (throughput, error rate and 99%line, the importance descending in order), the results are drawn graphics, easy to view.
Test results under 565bytes
Test results under 5KB
Test results under 10KB
Test results under 50KB
Test results under 100KB
Summarize
Combined with each of these test results, gin and iris are excellent frameworks, gin are slightly more advantageous than others, Iris is the second, and Echo is almost the same.
This test simply tested the concurrency and JSON correlation of the 3 frameworks. The comparison results, excluding the ecology and the perfection of tools and so on. If there are any imperfections in the test, welcome to the exchange.
You are also welcome to try and star another web framework baa, in order to suspicion I did not post a BAA data, the performance test is gin and between Iris.