Гипотетически говоря, правильно ли подключаться к базе данных для каждого запроса и закрываться, когда запрос завершен?Управление соединениями по запросу в Go
Я использую mongodb
с mgo
для базы данных.
В моем проекте я хотел бы подключиться к определенной базе данных, получив имя базы данных из заголовка запроса (конечно, это объединено с механизмом аутентификации, например JWT в моем приложении). Поток идет что-то вроде:
аутентификации пользователя:
POST to http://api.app.com/authenticate // which checks the user in a "global" database, // authenticates them and returns a signed JWT token // The token is stored in bolt.db for the authentication mechanism
Некоторые RESTful операции
POST to http://api.app.com/v1/blog/posts // JWT middleware for each request to /v1* is set up // `Client-Domain` in header is set to a database's name, e.g 'app-com' // so we open a connection to that database and close when // request finishes
Так что мои вопросы:
- Возможно ли это? - Я читал о пулах соединений и их повторном использовании, но я еще не много читал о них.
- Есть ли лучший способ достижения желаемой функциональности?
- Как обеспечить, чтобы сессия закрывалась только после завершения запроса?
Причина, по которой мне нужно это сделать, состоит в том, что у нас есть несколько поставщиков, которые имеют одинаковые коллекции баз данных с разными записями с ограниченным доступом к своим собственным базам данных.
Update/Решение Я закончил с использованием Go
«встроенной в Context
пути копирования сеанса и использовать его в любом месте, что нужно сделать какой-либо CRUD оп
Что-то вроде:
func main() {
...
// Configure connection and set in global var
model.DBSession, err = mgo.DialWithInfo(mongoDBDialInfo)
defer model.DBSession.Close()
...
n := negroni.Classic()
n.Use(negroni.HandlerFunc(Middleware))
...
}
func Middleware(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
...
db := NewDataStore(clientDomain)
// db.Close() is an alias for ds.session.Close(), code for this function is not included in this post
// Im still experimenting with this, I need to make sure the session is only closed after a request has completed, currently it does not always do so
defer db.Close()
ctx := req.Context()
ctx = context.WithValue(ctx, auth.DataStore, db)
req = req.WithContext(ctx)
...
}
func NewDataStore(db string) *DataStore {
store := &DataStore{
db: DBSession.Copy().DB(db),
session: DBSession.Copy(),
}
return store
}
И затем используйте его в HandlerFunc, пример /v1/system/users
:
func getUsers(res http.ResponseWriter, req *http.Request) {
db := req.Context().Value(auth.DataStore).(*model.DataStore)
users := make([]SystemUser{}, 0)
// db.C() is an alias for ds.db.C(), code for this function is not included in this post
db.C("system_users").Find(nil).All(&users)
}
40% время отклика на исходный метод, с которым я экспериментировал.
В своем 2-м ответе вы сказали '' создать глобальную переменную, которая содержит соединение с базой данных ", но это ограничило бы меня только подключением к одной базе данных, правильно? Могу ли я сделать то же самое, создав глобальную срезную переменную, содержащую несколько соединений, и закрою все из них, когда приложение умирает? – borislemke
Это зависит: главным образом потому, что с помощью набора номера вы можете подключиться к нескольким хостам в момент времени, а затем вы можете изменить базу данных Mongo с помощью функции [DB] (https://godoc.org/labix.org/v2/mgo#Session. DB) для изменения базы данных. Тебе решать. Но, imho, более чистая отдельная связь для каждого db. Делая это, вы также можете разделить каждую логику db. – Tinwor
Что вы подразумеваете под логикой db? Каждая база данных имеет одинаковые коллекции. Представьте, что вы реплицируете магазин или аналогичную услугу для хостинга/редактирования веб-сайта SaaS, каждый раз, когда новый пользователь регистрирует и создает веб-сайт, мы запускаем новый контейнер 'docker' для своего« выделенного »веб-сайта, у которого есть собственный сервер' mongodb'. Мы отслеживаем, кто владеет каждым контейнером 'docker' и как получить доступ к ним с нашего« основного »сервера' Go'. Таким образом, разница действительно только в том, кто может получить доступ к этой базе данных из 'main'' Go' сервера. – borislemke