【问题标题】:I am getting too many open connections when the connection is kept alive当连接保持活动状态时,我打开的连接太多
【发布时间】:2018-10-26 02:28:13
【问题描述】:

我有一个简单的 Go 文件,目的是返回客户信息的 json 响应。当我使用 apache benchmark 对该脚本进行基准测试时,请求保持活动状态

ab -t 10s -kc 1000 http://127.0.0.1:8080/clients/show/1

但是当请求没有保持活跃时,我不会受到这种恐慌

ab -t 10s -c 1000 http://127.0.0.1:8080/clients/show/1

错误:

2018/10/26 03:26:42 http:恐慌服务 127.0.0.1:44800:错误 1040: 连接太多 goroutine 220522 [正在运行]: net/http.(*conn).serve.func1(0xc001779e00)

我的代码:

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "github.com/gorilla/mux"
    "net/http"
    "runtime"
)

type Client struct {
    ID         int    `json:"id"`
    UserID     int    `json:"user_id"`
    Name       string `json:"name"`
    Telephone  string `json:"telephone"`
    Email      string    `json:"email"`
    Category   sql.NullString `json:"string"`
    Notes      string `json:"notes"`
    Additional sql.NullString `json:"additional"`
    CreatedAt  sql.NullString `json:"created_at"`
    UpdatedAt  sql.NullString `json:"updated_at"`
    DeletedAt  sql.NullString `json:"deleted_at"`
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    r := mux.NewRouter()

    r.HandleFunc("/clients/show/{id}", showClient).Methods("GET")

    http.ListenAndServe(":8080", r)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World!")
}

func showClient(w http.ResponseWriter, r *http.Request) {

    db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/crm")

    if err != nil {
        panic(err.Error())
    }

    var client Client

    // Execute the query
    err = db.QueryRow("SELECT * FROM clients where id = ?", 1).Scan(
        &client.ID,
        &client.UserID,
        &client.Name,
        &client.Telephone,
        &client.Email,
        &client.Category,
        &client.Notes,
        &client.Additional,
        &client.CreatedAt,
        &client.UpdatedAt,
        &client.DeletedAt,
    )

    if err != nil {
        panic(err.Error())
    }

    db.Close()

    json.NewEncoder(w).Encode(client)
}

有人可以解释一下为什么会在如此低的并发请求率下发生这种情况,以及解决这个问题的正确方法是什么。

【问题讨论】:

  • 当您调用sql.Open 时,您将获得一个应该重复使用的连接池。您应该在启动服务器之前打开它,让您的处理程序引用一个池。
  • golang.org/pkg/database/sql/#Open > 返回的 DB 对于多个 goroutine 并发使用是安全的,并维护自己的空闲连接池。因此,Open 函数应该只被调用一次。很少需要关闭数据库。

标签: go


【解决方案1】:

有两个问题,程序使用sockets和服务器配置

每个连接可能需要 2 个套接字,一个到数据库,一个到 http 客户端。将 sql.Open() 移动到不同的范围以便它不会被重复调用将有助于数据库套接字。对于 http 服务器,默认值实际上非常低 - 如果有超过 2 个未使用的保持活动,则关闭连接

另外,你的服务器可能需要修改

正如this answer 所讨论的,Linux 的默认每秒连接数相当保守,一个简单的小型 Go 服务器很可能会压倒它。

根据上述答案调整服务器,这应该会有所帮助。

【讨论】:

    猜你喜欢
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 2018-01-23
    • 2012-01-03
    相关资源
    最近更新 更多