在对象的整个生命周期中保持一个 MongoDB 会话是否明智?

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

Is it wise to keep a MongoDB session open for the lifetime of an object?

问题

我有一个用于抽象化系统中特定对象的MongoDB的结构体。在该结构体的工厂函数中,我设置了一些变量,如主机名和其他连接信息。目前,在每个UserService的方法中,它都会创建一个新的会话,执行所需的操作,然后在完成后关闭会话。

该系统本身是一个Web应用程序的后端,因此每个UserService结构体的生命周期通常只有几秒钟,但每个请求可能会执行多个操作。因此,我想知道是否应该将session作为结构体的成员,在创建UserService时初始化它,然后确保创建它的请求处理函数在完成所有操作后调用关闭函数。我没有找到任何鼓励或反对这种行为的信息,所以我不太确定我正在使用的mgo包是否设计成这样。

这是我提议的代码:

type UserService struct {
    callingUserId id.ID //调用此服务的用户的ID。
    host string //主机名。
    session mgo.Session //活动会话。
}

func NewUserService(userId id.ID) *UserService {
    nus := new(UserService)
    nus.callingUserId = userId
    nus.host = "localhost" //TODO 从文件或缓冲区中读取此值。
    nus.session, sessionErr = mgo.Dial(nos.host)
    if sessionErr != nil {
        //TODO 记录错误。
    }
    return nus
} 

func (us UserService) GetById(usrId id.ID) *users.User {        
    //TODO 使用现有会话从数据库中获取具有匹配ID的用户。        
}

还将有一个名为UserService.CloseSession的函数,如我所提到的,它将在创建服务的处理程序函数完成所有必需的操作后调用。

有人知道这是否是一个明智的想法,还是我应该在UserService的每个函数中都调用mgo.Dial

英文:

I have a struct that abstracts MongoDB for specific objects in my system, and during the factory function for it I set a few variables like hostname and other connection information. At the moment in each of the UserService's methods* it creates a new session, does what it needs to, then closes the session when it's done.

The system itself is the backend of a web application, so the lifetime of each UserService struct is usually only a few seconds at most, but more than one operation might be performed for each request that comes in. So I'm wondering whether to make session a member of the struct, initialise it when I create my UserService, and then ensure the request handler function that creates it calls a close function once it's done all the operations it needs to. I haven't been able to find anything that encourages or discourages this behaviour so I'm not really sure if the mgo package I'm using is designed that way.

This is my proposed code:

type UserService struct {
	callingUserId id.ID //The ID of the user calling this service.
	host string //The host name.
	session mgo.Session //The active session.
}

func NewUserService(userId id.ID) *UserService {
	nus := new(UserService)
	nus.callingUserId = userId
	nus.host = "localhost" //TODO change this to read from file or buffer.
	nus.session, sessionErr = mgo.Dial(nos.host)
	if sessionErr != nil {
		//TODO log error.
	}
	return nus
} 

func (us UserService) GetById(usrId id.ID) *users.User {    	
	//TODO get a user from the database with the matching ID using the existing session.    	
}

There will also be a function called UserService.CloseSession, which as I mentioned, will be called after all the required operations are done by the handler function that creates the service.

Does anyone know if this is a sensible idea or should I just call mgo.Dial in every function on UserService?

答案1

得分: 4

打开与MongoDB或任何其他数据库的连接是一个昂贵的任务,应该在服务内部只执行一次,并尽可能保持运行。

你有三个选项:

  1. 本地包级别的MongoDB实例。
  2. 使用上下文和组合处理程序。
  3. 一个持有MongoDB实例的方法接收器。

这是一个非常有信息量的博客文章,用于处理数据库连接。请查看这个示例,特别是针对MongoDB的部分。

英文:

Opening a connection to MongoDB or any other DB is an expensive task that should be done once and kept operative as much as possible inside your service.

You have three options:

  1. A local package level MongoDB instance.
  2. Using Contexts and Composing Handlers.
  3. A method receiver which holds the MongoDB Instance.

This is a very informative blog post for handling DBs connections.
Take a look to this example, especially for MongoDB

huangapple
  • 本文由 发表于 2015年12月3日 21:53:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/34067825.html
匿名

发表评论

匿名网友

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

确定