英文:
Golang http connection is persisting indefinitely
问题
我有一个简单的代码,从数据库中检索数据,并且我正在使用Jmeter对其进行负载测试。我正在模拟1,000个请求,有时我会得到全部1,000个成功的请求,而有时我只得到999个请求,我不得不停止它,因为线程或最后的结果似乎无限期地继续进行,如下图所示,请注意最后一个请求所花费的时间超过正常时间的10倍。如果我不停止它,那个请求将会一直进行下去。
这是我的代码:
func get_data(w http.ResponseWriter, r *http.Request) {
var result string
r.ParseForm()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
db.QueryRow("select json_build_object('Locations', array_to_json(array_agg(t))) from (SELECT latitudes,county,longitudes,"+
"statelong,thirtylatmin,thirtylatmax,thirtylonmin,thirtylonmax,city"+
" FROM zips where city='Orlando' ORDER BY city limit 5) t").Scan(&result)
}()
wg.Wait()
fmt.Fprintf(w,result)
}
然后是我的数据库连接:
var db *sql.DB
func init() {
var err error
db, err = sql.Open("postgres", Postgres_Connect)
if err != nil {
log.Fatal("Invalid DB config:", err)
println("Invalid DB config:")
//log_errors("HomePage-Postgres: error opening database",err)
}
if err = db.Ping(); err != nil {
log.Fatal("DB unreachable:", err)
println()
}
}
这是我的HTTP服务器:
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
r := mux.NewRouter()
r.HandleFunc("/mydata",Controllers.Get_Data)
http.Handle("/",r)
srv := &http.Server{
ReadTimeout: 20 * time.Second,
WriteTimeout: 20 * time.Second,
IdleTimeout: 120 * time.Second,
Addr: ":8000",
}
log.Println(srv.ListenAndServe())
}
我原本希望ReadTimeOut会终止连接,但似乎并没有起作用。
英文:
I have a simple code that retrieves data from the database and I am using Jmeter to perform load testing on it . What I am doing is simulating 1,000 requests sometimes I get all 1,000 successful requests and other times I get 999 requests and I have to stop it because it seems like the thread or last results keeps on going indefinitely this is how it looks, notice on how the last request takes more than 10 times the normal time . If i don't stop it then that request would keep going on and on .
This is my code
func get_data(w http.ResponseWriter, r *http.Request) {
var result string
r.ParseForm()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
db.QueryRow("select json_build_object('Locations', array_to_json(array_agg(t))) from (SELECT latitudes,county,longitudes,"+
"statelong,thirtylatmin,thirtylatmax,thirtylonmin,thirtylonmax,city"+
" FROM zips where city='Orlando' ORDER BY city limit 5) t").Scan(&result)
}()
wg.Wait()
fmt.Fprintf(w,result)
}
Then I have my database connection
var db *sql.DB
func init() {
var err error
db, err = sql.Open("postgres", Postgres_Connect)
if err != nil {
log.Fatal("Invalid DB config:", err)
println("Invalid DB config:")
//log_errors("HomePage-Postgres: error opening database",err)
}
if err = db.Ping(); err != nil {
log.Fatal("DB unreachable:", err)
println()
}
}
and here is my HTTP server
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
r := mux.NewRouter()
r.HandleFunc("/mydata",Controllers.Get_Data)
http.Handle("/",r)
srv := &http.Server{
ReadTimeout: 20 * time.Second,
WriteTimeout: 20 * time.Second,
IdleTimeout: 120 * time.Second,
Addr: ":8000",
}
log.Println(srv.ListenAndServe())
}
I was hoping that the ReadTimeOut would kill the connection but it seems like it doesn't
答案1
得分: 2
ReadTimeOut
适用于net/http
的服务器代码进行的读取操作,而不适用于执行请求的goroutine:
> ReadTimeout是读取整个请求(包括请求体)的最长时间。
一旦请求被读取,这个值就不再使用,处理程序负责决定是否超时。
如果你想在数据库查询完成之前取消HTTP请求,可以使用context.Context来实现。
扩展req.Context
,添加超时或截止时间,将这个新的上下文传递给sql.QueryRowContext
:
ctx, _ := context.WithTimeout(r.Context(), 20 * time.Second)
db.QueryRowContext(ctx, "select json_build_object('Locations', array_to_json(array_agg(t))) from (SELECT latitudes,county,longitudes,"+
"statelong,thirtylatmin,thirtylatmax,thirtylonmin,thirtylonmax,city"+
" FROM zips where city='Orlando' ORDER BY city limit 5) t").Scan(&result)
英文:
ReadTimeOut
applies to the reads made by net/http
's server code, not to the goroutine executing the request:
> ReadTimeout is the maximum duration for reading the entire
> request, including the body.`
Once the request has been read this value is no longer used, and the handler is in charge of deciding whether or not things have timed out.
If you want to cancel the HTTP request before the database query is done, you can do this with a context.Context.
Extend req.Context
, add a timeout or deadline, passing this new context to sql.QueryRowContext
:
ctx, _ := context.WithTimeout( r.Context(), 20 * time.Second )
db.QueryRowContext(ctx, "select json_build_object('Locations', array_to_json(array_agg(t))) from (SELECT latitudes,county,longitudes,"+
"statelong,thirtylatmin,thirtylatmax,thirtylonmin,thirtylonmax,city"+
" FROM zips where city='Orlando' ORDER BY city limit 5) t").Scan(&result)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论