RPCX的业务逻辑存在于service中,业务通过暴露结构体方法(下称方法)提供RPC服务。业务方法中不可避免的要使用数据库服务。例如在某个服务中存在以下访问用户信息的业务:
service.go
...
type Member struct {
User_id int
Mobile int
}
...
func (user *User) UserInfo(ctx context.Context, args *Args, reply *Reply) error {
dbcnt:=make(map[string]string)
dbcnt["username"] = "root"
dbcnt["password"] = "********"
dbcnt["port"] = "3306"
dbcnt["database"] = "database"
dbcnt["network"] = "tcp"
dbcnt["server"] = "127.0.0.1"
d:=new(db.Sqlstruct)
d.Connt(dbcnt)
d.Table("user")
d.Field("mobile,user_id")
d.Where("user_id=123456")
d.Limit("0,1")
var find = &Member{"mobile","user_id"}
fmt.Println("-------")
// var fd interface{}
res:=d.Select(find)
...
return nil
}
以上代码就是一个在服务中使用mysql完整的例子,但这样会存在问题,当发起RPC调用时会重新创建Mysql连接。如果在高并发的场景根本无法满足性能要求。性能问题主要体现在max_connection和open_files_limit受限,同时还会引发连接阻塞。
当然,就这两个问题,本身就提供了解决的思路--最大连接数和tpc打开数
1、golang的mysql提供了连接池,解决连接复用:
example/db/db.go
...
db.SetMaxOpenConns(500)//最大连接数,当一个查询结束,就会立限返回连接池。
db.SetMaxIdleConns(16)
...
2、将数据库的连接对像在业务服务service.go之外创建,并且在RPC调用时传递数据库的连接对像,供服务使用:
example/db/db.go
...
type Sqlmodel struct{
Wher string
Joinn string
Wherestring string
order string
limit string
alias string
table string
group string
update string
save string
field string
DB sql.DB
Rows interface{}
Row interface{}
sync.RWMutex //在多个服务中使用同一个数据库对像,一定要使用同步锁
}
...
server.go
import(
example/db
)
func main() {
flag.Parse()
s := server.NewServer()
addRegistryPlugin(s)
dbcnt:=make(map[string]string)
dbcnt["username"] = "root"
dbcnt["password"] = "********"
dbcnt["port"] = "3306"
dbcnt["database"] = "database"
dbcnt["network"] = "tcp"
dbcnt["server"] = "127.0.0.1"
// var Db *sql.DB
d:=new(db.Sqlmodel)
d.Connt(dbcnt)
usermodel := user.User{*d}//此处的user为服务中的user struct,这里是
s.RegisterName("User", &usermodel, "")//在server中创建数据库对像传递到方法中使用
s.Serve("tcp", *addr)
}
...
...
s.RegisterName("User",&usermodel,"")
...
以上代码解决了在业务方法中创建数据库对像带来的性能问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。