我正在研究一个Go项目,该项目使用gRPC作为服务器,使用Voltdb作为DB。向gRPC服务器发送许多数据库读/写请求时出现问题。请求已处理,但在操作员完成后不会释放数据库连接。因此,当池中的连接用完时,会出现此错误:
因为已达到9940的连接限制,所以拒绝了/127.0.0.1:63015的连接
原始文件
syntax = "proto3";
package grpc;
import "google/protobuf/struct.proto";
option java_multiple_files = true;
option java_package = "com.io.test";
service TestService {
rpc updateUser (UserRequest) returns (Status) {};
}
message UserRequest {
string userId = 1;
string name = 2;
}
message Status {
string code = 1;
}
Go中的GRPC工具
package service
import (
"context"
"log"
api "testgrpc/pkg/api/grpc"
"testgrpc/pkg/db"
"testgrpc/pkg/model"
)
var voltDbClient *db.VoltDBClient
func init() {
voltDbClient = db.NewVoltDBClient()
}
type GrpcService struct {
}
func NewGrpcService() *GrpcService {
return &GrpcService{}
}
func (sv *GrpcService) UpdateUser(ctx context.Context, req *api.UserRequest) (*api.Status, error) {
user, err := voltDbClient.FindByID(req.GetUserId())
if user == nil || err != nil {
log.Print("error while reading")
} else {
log.Println(user.(*model.User).UserId)
log.Println(user.(*model.User).Name)
}
err = voltDbClient.Put(req.GetUserId(), req.GetName())
if err != nil {
log.Print("error while writing")
}
return &api.Status{Code: "0"}, nil
}
数据库客户端
package db
import (
"database/sql"
"log"
"testgrpc/pkg/model"
_ "github.com/VoltDB/voltdb-client-go/voltdbclient"
)
var Db *sql.DB
func init() {
if Db == nil {
var err error
Db, err = sql.Open("voltdb", "localhost:21212")
if err != nil {
log.Fatal(err)
}
//limit max connection to reproduce issue
Db.SetMaxOpenConns(20)
}
}
type VoltDBClient struct {
}
func NewVoltDBClient() *VoltDBClient {
return &VoltDBClient{}
}
//Put add or update record
func (dbClient *VoltDBClient) Put(key interface{}, value interface{}) error {
res, err := Db.Exec("GROUPINFO.upsert", key, value)
if err != nil {
log.Println(err)
return err
}
rowCnt, err := res.RowsAffected()
if err != nil {
log.Println(err)
return err
}
log.Printf("affected = %d\n", rowCnt)
return nil
}
//FindByID find a record by ID
func (dbClient *VoltDBClient) FindByID(key interface{}) (interface{}, error) {
rows, err := Db.Query("GROUPSELECT", key)
if err != nil {
log.Println(err)
return nil, err
}
for rows.Next() {
user := model.User{UserId: "", Name: ""}
err := rows.Scan(&user.UserId, &user.Name)
if err != nil {
log.Println(err)
return nil, err
}
return &user, nil
}
return nil, nil
}
注意:我曾尝试在不使用grpc的情况下运行项目,读/写运算符效果很好。