Создание промежуточного ПО для пула на основе поддомена - слишком много подключений - PullRequest
0 голосов
/ 05 августа 2020

По идее, на основе поддомена ex. tenant1.app.com или tenant2.app.com приложение подключается к соответствующей базе данных.

Имя базы данных сохраняется в JWT во время аутентификации.

Это правильный способ справиться с этим использованием case?

промежуточное ПО. js

let authenticationHandler = (req, res, next) => {
    
    let token = req.headers.authorization;

    jwt.verify(token, "tracer", (err, decoded) => {
        if (err) {
            res.status(401).send({message: "Access denied"});
        } else {
            req.decoded = decoded;     // <------ the token is passed to database middleware
            next();
        }
    });
};

let databaseHandler = (req, res, next) => {
    let database = req.decoded.database;

    let util = require("util");

    let pool = mysql.createPool({
        ...db,
        database: database,
    });

    pool.query = util.promisify(pool.query);

    req.pool = pool;             // <------ pool is passed to API

    next();
};

app.all("/api/*", middleware.authenticationHandler);
app.all("/api/*", middleware.databaseHandler);

api. js

router.get("/api/products", async function (req, res, next) {
    try {
        let query = `select * from product;`;

        var rows = await req.pool.query(query);            // <------ the pool is used
        res.status(200).send(rows);
    } catch (err) {
        next(err);
    }
});

1 Ответ

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

В итоге я выбрал подход conn.changeUser () для достижения того, что я хочу.

Другой вариант: mysql .createPoolCluster () , который было немного сложно, так как я должен был знать базы данных заранее, а не делать это на лету.

Как это работает ...

  1. Создать основной пул в server.js .
// One main pool is created on app initialization
let pool = mysql.createPool(db);
// That pool is passed in the database middleware
// which forwards a connection to a corresponding database for further use
app.all("/api/*", middleware.databaseHandler(pool));
Извлечь соединение из пула в промежуточном программном обеспечении.
let databaseHandler = (pool) => {
    return (req, res, next) => {
        // req.decoded comes from authenticationHandler
        let database = req.decoded.database;

        // Get a connection from the main pool in app.js
        pool.getConnection((err, conn) => {
            if (err) {
                console.log(err);
                return;
            }
            // Change the database for the connection
            conn.changeUser({ database: database }, function (err) {
                if (err) {
                    console.log(err);
                    return;
                }

                // Promisify for Node.js async/await.
                const query = util.promisify(conn.query).bind(conn);

                // Pass the modified query method down the chain as a property of req, avaiable via next()
                // connection.release() is called in the routes
                req.query = query;
                req.connection = conn;
                next();
            });
        });
    };
};
Используйте соединение в API и затем освободите его.
router.get("/api/products", async function (req, res, next) {
    try {
        let query = `select * from product;`;

        var rows = await req.query(query);
        res.status(200).send(rows);
    } catch (err) {
        next(err);
    } finally {
        req.connection.release();
    }
});

Кажется, все работает хорошо, если кто-то обнаружит проблему, ответьте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...