Vercel создает новое соединение с БД для каждого запроса - PullRequest
0 голосов
/ 01 августа 2020

Я работаю над новым веб-сайтом, и хотя все шло хорошо, поскольку мы разрабатывали локально, мы столкнулись с проблемой при попытке развернуть на Vercel. Приложение использует фреймворк Sapper как для страниц, так и для API, а также базу данных в MongoDB Atlas, к которой мы получаем доступ через Mon goose. Поведение, которое мы имеем локально, заключается в том, что мы npm run dev и делаем одно соединение с БД, которое сохраняется до тех пор, пока мы не закроем приложение.

Local logs

When it gets deployed to Vercel though, the code which makes the DB connection and prints that "DB connection successful" message and is only supposed to run once is instead run on every API request

New DB connection per request

This seems to quickly get out of hand, reaching our database's limit of 500 connections: DB connections hits limit

As a result, after the website is used briefly even by a single user some of our API requests start failing with this error (We have the db accepting any connection rather than an IP whitelist, so the suggestion the error gives isn't helpful): API не может подключиться к БД

Наша реализация состоит в том, что у нас есть вызов mongoose.connect в файле. js:

mongoose.connect(DB, {
    useNewUrlParser: true,
    useCreateIndex: true,
    useFindAndModify: false,
    useUnifiedTopology: true
}).then(() => console.log("DB connection successful!")).catch(console.error);

, а затем мы import этот файл в * 1017 Sapper *. Мы смогли найти рекомендацию «просто кэшировать соединение», но это не увенчалось успехом и, похоже, больше похоже на node-mongodb-native. Тем не менее, это то, что мы пробовали, что не работало ни лучше, ни хуже локально, но также не устранило проблемы на Vercel:

let cachedDb = {};

exports.connection = async () => {
    if (cachedDb.isConnected)
        return;
        try {
            const db = await mongoose.connect(DB, {
                            useNewUrlParser: true,
                            useCreateIndex: true,
                            useFindAndModify: false,
                            useUnifiedTopology: true
                        });
            cachedDb.isConnected = db.connections[0].readyState;
            console.log("DB connection successful!");
            return cachedDb;
        } catch(error) {console.log("Couldn't connect to DB", error);}

Итак ... есть ли способ заставить эту работу без замена хотя бы одной из частей? Веб-сайт еще не работает, поэтому замена чего-либо - еще не конец света, но «просто измените настройки» определенно предпочтительнее начинать с нуля.

1 Ответ

0 голосов
/ 02 августа 2020

Сводка

Бессерверные функции в Vercel работают как автономный процесс. Хотя можно кэшировать соединение «для каждой функции», развертывать готовую к серверу библиотеку в бессерверной среде - не лучший вариант. Вот несколько вопросов, на которые вам нужно ответить:

  • Кэширует ли ваша фреймворк или библиотека БД соединение?
  • Подготовлен ли ваш код для бессерверного режима?
  • Что Тип рабочей нагрузки, для которого оптимизирован Vercel?

Дальнейший контекст

Vercel - отличная платформа для вашего внешнего интерфейса, которая будет использовать бессерверные функции в качестве помощников. CDN, доступный в сочетании с рабочим процессом, делает процесс развертывания очень быстрым и позволяет вам двигаться быстрее. Развертывание полноценного API или серверной нагрузки никогда не будет хорошей идеей. Предположим, мне нужно использовать MySQL с Vercel. Вместо mysql следует использовать mysql -serverless , оптимизированный для бессерверных примитивов. Даже с учетом этого, вероятно, будет дешевле просто использовать виртуальную машину / контейнер для API. Таким образом, мы получили бы следующее идеальное решение:

Static frontend (Vercel - Serverless) --> Backend (Serverful - External provider) --> DB

Отказ от ответственности: на данный момент я работаю в Vercel.

...