Как можно повторно использовать соединение с базой данных в функциях Golang Cloud?

В настоящее время я пытаюсь перенести свое приложение на облачные функции IBM, но одна проблема, с которой я сталкиваюсь, - это предотвращение повторного подключения базы данных Postgresql при каждом вызове действия.

Я нашел очень мало информации о том, как повторно использовать соединение с БД в Go, и решения, которые я пробовал (сохранение обработчика базы данных в глобальной переменной), не работают.

Сможет ли кто-нибудь указать мне на нужный документ?

Спасибо,

-Томас

PS: Вот фрагмент кода, который иллюстрирует мои попытки:

func Storage() Storager {
    once.Do(func() {
        db := InitDB()
        println("Initiating DB...")
        s = &storage{
            db: db,
        }
    })

    return s
}

// This is declared as a global variable in main
var s = storage.Storage()

person thomas    schedule 20.04.2020    source источник
comment
В бессерверных средах, таких как IBM Cloud Functions, каждая функция / действие выполняется самостоятельно. Вы можете попробовать передать информацию о соединении в качестве параметра между действиями.   -  person data_henrik    schedule 20.04.2020
comment
@data_henrik на самом деле другие бессерверные провайдеры, такие как AWS lambda, позволяют повторно использовать соединения с базой данных для экономии времени вычислений, но спасибо.   -  person thomas    schedule 20.04.2020
comment
Существуют образцы кода, в которых используются те же концепции, полагаясь на повторно используемый контейнер. thecodebarbarian.com/ Лично я предпочитаю чистый подход   -  person data_henrik    schedule 20.04.2020
comment
@data_henrik это решение, о котором я изначально упоминал в своем сообщении, и оно не работает   -  person thomas    schedule 20.04.2020


Ответы (1)


Можно сохранить глобальное состояние внутри действий OpenWhisk, и это работает для функций Golang. Например, вот функция counter.go, которая увеличивает глобальный счетчик для каждого вызова функции.

package main

var counter = 1

func Main(args map[string]interface{}) map[string]interface{} {
  msg := make(map[string]interface{})
  msg["counter"] = counter
  counter = counter + 1
  return msg
}

Если вы создадите это действие и запустите его несколько раз подряд, вы увидите, что значение счетчика увеличивается каждый раз.

> wsk action create counter counter.go
> wsk action invoke counter --result
{
  "counter": 1
}
> wsk action invoke counter --result
{
  "counter": 2
}
> wsk action invoke counter --result
{
  "counter": 3
}

Итак, то, что вы пытаетесь сделать, должно сработать. В вашем примере убедитесь, что действие завершается успешно и не вызывает ошибку и не дает сбоев (что предотвращает дальнейшее повторное использование). Кроме того, проверьте запись активации, чтобы узнать, была ли активация теплой или холодной. Это можно увидеть, проверив, есть ли в записи активации аннотация initTime, указывающая на холодный запуск. Если нет, активация является теплой, и последняя активация выполнялась в том же контексте, что и предыдущая.

person user6062970    schedule 21.04.2020
comment
При таком подходе следует помнить, что не все бессерверные платформы позволяют запускать фоновый код. Я столкнулся с этим, играя с IBM Cloud Functions. Я хотел накопить несколько входных запросов в памяти, а затем поместить большой объект в корзину облачного хранилища объектов в фоновом режиме. Я заметил, что для среды выполнения Node.js обратные вызовы вызовов setTimeout не всегда выполняются, и они будут выполняться в другое время, например, при следующем вызове функции. Эта проблема также повлияет на методы управления подключениями к базе данных в фоновом режиме. - person Matt Welke; 19.05.2020
comment
Я решил задать здесь вопрос о своем опыте. Я постараюсь не забыть прокомментировать здесь позже, чтобы исправить сказанное выше, если я обнаружу, что это была моя собственная ошибка. - person Matt Welke; 19.05.2020