Go `net/http` 在高并发下的一些困惑
Some confusion of Go `net/http` under high concurrency
高并发下有些混乱
我用wrk测试Gin,有一些不确定性。 Gin 似乎并发不安全。
package main
import (
"fmt"
"sync/atomic"
"github.com/gin-gonic/gin"
)
var count int64 = 0
func Test(c *gin.Context) {
atomic.AddInt64(&count, 1)
fmt.Println(count)
c.String(200, "success")
}
func main() {
gin.SetMode(gin.DebugMode)
router := gin.New()
router.GET("test", Test)
router.Run(":8080")
}
测试shell代码
wrk -t50 -c50 -d 1s http://localhost:8080/test
Gin输出重复数据
========更新========
即使这样打印代码。
countCopy := count
go func() {
fmt.Println(countCopy)
}()
我也用ab测试了一下,同样的问题
========更新========
与net/http相同,仍然有重复数据。
package main
import (
"fmt"
"net/http"
"sync/atomic"
)
var count int64 = 0
func Test(w http.ResponseWriter, req *http.Request) {
atomic.AddInt64(&count, 1)
fmt.Println(count)
w.Write([]byte("success"))
}
func main() {
http.HandleFunc("/test", Test)
http.ListenAndServe(":8080", nil)
}
我尝试使用日志包,它对并发 goroutines 是安全的。一样。
log.Println(countCopy)
您必须使用 atomic.AddInt64(&count, 1)
的返回值,因为 count
可能会在您有机会打印之前更改:
func Test(c *gin.Context) {
current := atomic.AddInt64(&count, 1)
fmt.Println(current)
c.String(200, "success")
}
高并发下有些混乱
我用wrk测试Gin,有一些不确定性。 Gin 似乎并发不安全。
package main
import (
"fmt"
"sync/atomic"
"github.com/gin-gonic/gin"
)
var count int64 = 0
func Test(c *gin.Context) {
atomic.AddInt64(&count, 1)
fmt.Println(count)
c.String(200, "success")
}
func main() {
gin.SetMode(gin.DebugMode)
router := gin.New()
router.GET("test", Test)
router.Run(":8080")
}
测试shell代码
wrk -t50 -c50 -d 1s http://localhost:8080/test
Gin输出重复数据
========更新========即使这样打印代码。
countCopy := count
go func() {
fmt.Println(countCopy)
}()
我也用ab测试了一下,同样的问题
========更新========与net/http相同,仍然有重复数据。
package main
import (
"fmt"
"net/http"
"sync/atomic"
)
var count int64 = 0
func Test(w http.ResponseWriter, req *http.Request) {
atomic.AddInt64(&count, 1)
fmt.Println(count)
w.Write([]byte("success"))
}
func main() {
http.HandleFunc("/test", Test)
http.ListenAndServe(":8080", nil)
}
我尝试使用日志包,它对并发 goroutines 是安全的。一样。
log.Println(countCopy)
您必须使用 atomic.AddInt64(&count, 1)
的返回值,因为 count
可能会在您有机会打印之前更改:
func Test(c *gin.Context) {
current := atomic.AddInt64(&count, 1)
fmt.Println(current)
c.String(200, "success")
}