当前位置: 首页 > 面试题库 >

Golang RESTful API负载测试导致数据库连接过多

顾乐池
2023-03-14
问题内容

我认为在Golang中管理数据库连接池时遇到严重问题。我使用Gorilla网络工具包构建了RESTful
API,当只有很少的请求被发送到服务器时,该工具非常有用。但是现在我开始使用loader.io网站执行负载测试。对于冗长的帖子,我深表歉意,但我想为您提供完整的介绍。

在继续之前,这里是运行API和MySQL的服务器上的一些信息:专用主机Linux 8GB RAM Go版本1.1.1使用go-sql-driver
MySQL 5.1的数据库连接

使用loader.io,我可以每15秒发送1000个GET请求,而不会出现问题。但是,当我发送1000个POST请求/
15秒时,我收到很多错误,所有错误都是错误1040,数据库连接过多。许多人在线上报告了类似问题。请注意,目前我仅对一个特定的POST请求进行测试。对于此发布请求,我确保了以下内容(许多在线其他人也建议这样做)

  1. 我确保我没有使用短暂的函数打开和关闭* sql.DB。因此,正如您在下面的代码中看到的那样,我只为连接池创建了全局变量,尽管我愿意在这里提出建议,因为我不喜欢使用全局变量。

  2. 我确保尽可能使用db.Exec,并且在预期结果时仅使用db.Query和db.QueryRow。

由于上述方法无法解决我的问题,因此我尝试设置db.SetMaxIdleConns(1000),该问题解决了1000次POST请求/
15秒的问题。意味着不再有1040错误。然后,我将负载增加到2000个POST请求/
15秒,然后再次开始出现错误1040。我试图增加db.SetMaxIdleConns()中的值,但这没有任何区别。

在这里,我通过运行SHOW STATUS WHERE variable_name=’Threads_connected’
从MySQL数据库获得有关连接数量的一些连接统计信息;

对于1000个POST请求/ 15秒:观察到的#threads_connected〜= 100对于2000个POST请求/
15秒:观察到的#threads_connected〜= 600

我还在my.cnf中增加了MySQL的最大连接数,但这没什么不同。你有什么建议?代码看起来不错吗?如果是,则可能是连接受到限制。

您将在下面找到代码的简化版本。

var db *sql.DB

func main() {
    db = DbConnect()
    db.SetMaxIdleConns(1000)

    http.Handle("/", r)
    err := http.ListenAndServe(fmt.Sprintf("%s:%s", API_HOST, API_PORT), nil)

    if err != nil {
       fmt.Println(err)
    }
}

func DbConnect() *sql.DB {
    db, err := sql.Open("mysql", connectionString)
    if err != nil {
        fmt.Printf("Connection error: %s\n", err.Error())
        return nil
    }
    return db
}

func PostBounce(w http.ResponseWriter, r *http.Request) {
    userId, err := AuthRequest(r)

    //error checking
    //ready requesy body and use json.Unmarshal

    bounceId, err := CreateBounce(userId, b)

    //return HTTP status code here
}

func AuthRequest(r *http.Request) (id int, err error) {
    //parse header and get username and password

    query := "SELECT Id FROM Users WHERE Username=? AND Password=PASSWORD(?)"
    err = db.QueryRow(query, username, password).Scan(&id)

    //error checking and return
}

func CreateBounce(userId int, bounce NewBounce) (bounceId int64, err error) {
    //initialize some variables
    query := "INSERT INTO Bounces (.....) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
    result, err := db.Exec(query, ......)

    //error checking

    bounceId,_ = result.LastInsertId()

    //return 
}

问题答案:

Go database/sql不会阻止您创建与数据库的无限数量的连接。如果池中有一个空闲连接,则将使用该连接,否则将创建一个新连接。

因此,在负载下,您的请求处理程序sql.DB可能找不到任何空闲连接,因此在需要时会创建一个新连接。这有点麻烦-尽可能重用空闲连接,并在需要时创建新连接-
最终达到Db的最大连接数。而且,不幸的是,在Go
1.1中,没有一种简便的方法(例如SetMaxOpenConns)来限制打开的连接。

升级到更高版本的Golang。在Go
1.2+中,您将获得SetMaxOpenConns。并查看MySql文档以开始设置,然后进行调整。

db.SetMaxOpenConns(100) //tune this

如果必须使用Go 1.1,则需要确保您的代码一次*sql.DB仅可被N个客户端使用。



 类似资料:
  • 我正在尝试使用Jeter针对SQLServer 2008 R2数据库设置基本负载测试。但是,当仅使用一个用户运行测试时,我收到错误。 响应消息:com。微软sqlserver。jdbc。SQLServerException:用户XXX登录失败。ClientConnectionId:。 这是我的JDBC连接配置数据库URL: jdbc: sqlserver://Serverame: 1433; Da

  • 我正在使用Heroku,并创建了一个新的应用程序和一个Postgres空数据库设置。 我已经安装了Heroku工具带,可以登录到Heroku并成功运行以下命令: 我在这里查看activerecord选项 但是,我运气不太好。 任何Heroku/Postgres大师能帮我指明正确的方向吗?数据库为空。作为第一步,我所要做的就是成功地连接到数据库。 Ruby文件:

  • 我曾想过简单地对数据库运行一个小命令并捕获任何异常,然而,如果出现问题(例如app.config丢失或数据库服务器关闭),应用程序将花费大量时间运行此代码,然后抛出异常(大约1分钟)。我想这是由于连接超时等,但我已经摆弄了这样的属性没有任何作用。 有没有人能提供任何关于去哪里的建议?

  • 本文向大家介绍Yii 连接、修改 MySQL 数据库及phpunit 测试连接,包括了Yii 连接、修改 MySQL 数据库及phpunit 测试连接的使用技巧和注意事项,需要的朋友参考一下 >>>database<<< 1. 修改 protected/config/main.php 去掉mysql数据库连接方式的注释,并且修改用户名,密码以及连接的数据库。 2. 新建 protected/tes

  • 用Python来编写网站,必须要能够通过python操作数据库,所谓操作数据库,就是通过python实现对数据的连接,以及对记录、字段的各种操作。上一讲提到的那种操作方式,是看官直接通过交互模式来操作数据库。 安装python-MySQLdb 要想通过python来操作数据库,还需要在已经安装了mysql的基础上安装一个称之为mysqldb的库,它是一个接口程序,python通过它对mysql数据

  • 是否可以在没有数据库连接的情况下运行我的测试?如果是,我做错了什么/错过了什么?