Nodejs 标准模型的部分扩展思路

Nodejs 标准模型的部分扩展思路

其实我很早就有在一些交流群里发过

1.在不重启服务的情况下实时更新函数。 采用数据库做functionname - functiontext表

服务启动,将表加载进缓存,执行某一步骤时,根据functionname拉取缓存中的function。 此时采用EVAL方法。 因此,此时只需要更新缓存和数据库,即可实时更新函数。

关于EVAL方法的一些弊端,大家自行解决。我的套路就不提供了。

2.全局单传参 基于SESSION的全局单传参。 因为以前用EXPRESS用的很多。传参多的时候自己头疼,于是想到了一个方法。用session做储值。 我的session是挂在REDIS上的,也就是跑得内存,一个session你放很多东西进去也不会超过100KB的数量级。 哪怕是跑企业级服务,不用担心SESSION造成的内存崩溃。 而且SESSION是会过期的。

好了。言归正传。就是req.session 我tar了一个req.session.cache。

比如说从数据库读的用户信息提供全局一直使用。 req.session.cache.user=db;

另外比如我在最后一步 res.render{req.session.page,req.session.pageconfig}; 我在任何时候需要任何传参,只需要一个传参req就全部解决。 原生NODE可以写出同样的方法。

长期测试,以上两种方法的性能都很稳定。


5 回复

Nodejs 标准模型的部分扩展思路

实时更新函数

在Node.js应用中,我们常常需要在不重启服务的情况下实时更新函数。这种需求可以通过数据库来实现,具体做法如下:

  1. 创建数据库表: 假设我们有一个名为 functions 的表,该表包含两个字段:function_namefunction_text

    CREATE TABLE functions (
        function_name VARCHAR(255) PRIMARY KEY,
        function_text TEXT
    );
    
  2. 加载缓存: 在服务启动时,我们将表中的数据加载到内存缓存中。

    const cache = {};
    const redis = require('redis');
    const client = redis.createClient();
    
    client.keys('*', (err, keys) => {
        if (keys.length > 0) {
            keys.forEach(key => {
                client.get(key, (err, value) => {
                    cache[key] = value;
                });
            });
        }
    });
    
  3. 动态执行函数: 当需要执行某个函数时,从缓存中获取函数文本并使用 eval 执行。

    function executeFunction(functionName, params) {
        const functionText = cache[functionName];
        if (functionText) {
            const func = new Function('params', functionText);
            return func(params);
        } else {
            throw new Error(`Function ${functionName} not found`);
        }
    }
    
    // 示例调用
    executeFunction('myFunction', { param1: 'value1' });
    

全局单传参

为了简化参数传递,我们可以利用 express-session 来存储全局变量。这里以 express-session 配合 connect-redis 为例:

  1. 安装依赖

    npm install express express-session connect-redis redis
    
  2. 配置中间件

    const express = require('express');
    const session = require('express-session');
    const RedisStore = require('connect-redis')(session);
    
    const app = express();
    app.use(session({
        store: new RedisStore(),
        secret: 'your_secret_key',
        resave: false,
        saveUninitialized: false
    }));
    
  3. 设置和使用全局变量

    app.get('/set-user', (req, res) => {
        req.session.user = { name: 'John Doe', age: 30 };
        res.send('User set');
    });
    
    app.get('/render-page', (req, res) => {
        res.render(req.session.page, { config: req.session.pageConfig });
    });
    

通过上述步骤,我们可以在不重启服务的情况下动态更新函数,并且通过 express-session 简化了全局变量的传递。这些方法在实际项目中已经经过长期测试,性能表现稳定。


不重启平滑升级服务器 参见 http://baoz.me/420310

全局变量本来,就很臭了,还用全局session。你可能没跑过海量并发。问题可是很严重的。

实时更新这个有点丧心病狂,哈哈 第二个没看懂,什么叫做全局单传参?

在Node.js中,通过扩展标准模型来实现动态更新函数和全局单传参的方法是一种提高灵活性和可维护性的有效方式。下面将详细说明这两种扩展思路,并附带一些示例代码。

动态更新函数

我们可以通过数据库存储函数文本,然后在服务启动时将其加载到内存中作为缓存,从而实现实时更新函数的功能。这里的关键点在于使用eval()函数来动态执行这些函数。

示例代码:

const express = require('express');
const app = express();
const redis = require('redis');
const client = redis.createClient();

// 加载函数到内存缓存
client.get('functions', (err, data) => {
    if (!err && data) {
        global.functionsCache = JSON.parse(data);
    }
});

app.get('/updateFunction', (req, res) => {
    const functionName = req.query.name;
    const newFunctionText = req.query.text;

    // 更新数据库
    client.set('functions', JSON.stringify({[functionName]: newFunctionText}));

    // 更新内存缓存
    global.functionsCache[functionName] = newFunctionText;
    
    res.send('Function updated successfully!');
});

app.get('/executeFunction', (req, res) => {
    const functionName = req.query.name;
    const params = req.query.params ? JSON.parse(req.query.params) : [];

    // 使用eval执行函数
    const result = eval(`(async () => { return (${global.functionsCache[functionName]})(...${JSON.stringify(params)}) })()`);

    result.then((res) => {
        res.send(res);
    }).catch((err) => {
        res.status(500).send(err);
    });
});

注意:eval()存在安全风险,应谨慎使用。可以考虑使用沙箱环境或其他更安全的方式替代。

全局单传参

通过使用Express的Session机制(默认依赖于cookie),我们可以将需要跨请求共享的数据存储在req.session中,这样就可以避免在每个请求中重复传递参数。

示例代码:

const express = require('express');
const session = require('express-session');
const redisStore = require('connect-redis')(session);
const app = express();

app.use(session({
    store: new redisStore({ client: client }),
    secret: 'your-secret-key',
    resave: false,
    saveUninitialized: false,
}));

app.get('/getUserInfo', (req, res) => {
    // 从数据库获取用户信息
    const userInfo = { id: 1, name: 'John Doe' };
    
    // 将用户信息保存到session中
    req.session.userInfo = userInfo;

    res.send(userInfo);
});

app.get('/renderPage', (req, res) => {
    // 从session中获取用户信息
    const user = req.session.userInfo;

    // 渲染页面并返回
    res.render('index', { user });
});

以上两种方法都是为了提升应用的灵活性和维护性,确保在不重启服务的前提下,能够动态地更新逻辑或管理全局状态。

回到顶部