Golang的HTTP连接持续保持不断。

huangapple go评论83阅读模式
英文:

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 .
Golang的HTTP连接持续保持不断。

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)

huangapple
  • 本文由 发表于 2017年5月19日 07:31:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/44059263.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定