Javascript 是否可以在创建后将Express会话更改为其他存储

Javascript 是否可以在创建后将Express会话更改为其他存储,javascript,node.js,express,express-session,Javascript,Node.js,Express,Express Session,我使用memcached作为ExpressJS会话的备份存储—通过应用程序配置设置选择。如果无法联系到memcached主机,我希望从memcached返回内存。(这不一定是一种生产策略,因为memcached是非常可靠的——更重要的是,当我忘记在dev中启动Docker实例时,它仍然可能是一种生产故障保护。) 我最初认为我可以“app.use”一个新的会话实例,并尝试删除第一个实例,但我已经了解到,“unuse”Express middleware(如果可能的话)很难(如果可能的话)实现,即交

我使用memcached作为ExpressJS会话的备份存储—通过应用程序配置设置选择。如果无法联系到memcached主机,我希望从memcached返回内存。(这不一定是一种生产策略,因为memcached是非常可靠的——更重要的是,当我忘记在dev中启动Docker实例时,它仍然可能是一种生产故障保护。)

我最初认为我可以“app.use”一个新的会话实例,并尝试删除第一个实例,但我已经了解到,“unuse”Express middleware(如果可能的话)很难(如果可能的话)实现,即交换链中的中间件,或者在设置链后对链进行修补

问题是在连接超时之后,应用程序中间件已经安装,在会话中间件之后还安装了许多其他服务

我的第二个想法是,我可以重新配置Express会话实例本身,并在创建存储后更改它吗?我看不出有什么办法进去

我的第三个想法是将express会话包装在一个新的“可交换存储”类中,但我担心包装整个接口的范围

例如,在我的应用程序设置中:

app.use(services.session.middleware());

// then a lot of other middleware...
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(rootPath, 'public')));
...etc
在选择和配置会话实例的会话服务中:

function middleware() {
    // default / Memory Store options
    const opts = {
        resave: false,
        saveUninitialized: false,
        ...etc
        }
    };

    // Install any configured backing store
    if(config.session.storage === "memcached"){
        const MemcachedStore = require('connect-memcached')(session);
        opts.proxy = 'true';
        opts.store = new MemcachedStore({
            hosts: ...,
            secret: ... 

        });
        const errorHandler = (type, details)=> {
            /* HERE I WOULD LIKE TO RE-MAKE THE SESSION USING MEMORY
             * AND DISCARD THE MEMCACHED ONE
             * (THIS HAPPENS AFTER APP BOOT HAS FINISHED)
            */
            console.error( String.format("Memcached {3} with host:{0} details:{1}.", details.server, details.messages.join( '' ), type)); 
        }
        opts.store.client.on('failure', details => errorHandler('failure', details));
        opts.store.client.on('issue', details => errorHandler('issue', details));
    }

    return session(opts);
}

我认为有几种方法可以尝试。第一种方法是根据启动时提供的配置配置存储系统(可能通过config或nconf等模块)。第二种方法是在启动应用程序时运行快速检查,确保它可以访问memcache服务,如果不能,则返回内存并出错

我会相当厌倦做这两件事,因为您使用的是docker,启动memcache应该很容易。这是因为您将引入一些代码,如果出现连接问题,这些代码可能会在生产中触发,然后您可能会发现自己意外地在内存之外服务会话,而不是像memcache这样的东西,而没有意识到这一点

我将在这里详细介绍这两种策略,并提供第三种可能更好的选择

1。根据配置选择缓存系统

这应该非常简单,只需将配置提取到某种配置管理器/环境变量(checkout config或nconf)中即可。启动应用程序并连接会话中间件时,您可以拉出所有可能的配置,查看哪些配置存在,并基于此附加一个配置。这与您的
if(config.session.storage===“memcache”)
目前的情况类似。只需使用不配置的回退,express session中间件就会回退到内存中。这样,您就可以完全省去配置,只需始终使用内存进行开发

2.在连接到所需服务之前运行测试

结合以上内容,如果提供了memcache的详细信息,您可以在启动时尝试在memcache中存储一些内容来运行快速测试在应用程序启动时发出信号?如果出现错误,则不要将
MemcachedStore
附加到express会话选项,您可以安全地销毁MemcachedStore

3.如果无法连接到Memcached,则抛出错误

这是对#2的进一步组合。如果您确定提供了memcache配置,那么我将亲自检查您是否可以联系服务商,如果不能,则抛出一个错误并停止应用程序。这意味着在开发过程中您会立即知道问题所在,在生产过程中您也会知道问题所在,并且可以触发根据应用程序无法启动的事实为您自己自动发出警报


这可能是最好、最稳健的解决方案,一般来说,在谈论连接服务时,执行静默回退不是一个好主意,因为事情可能会出错,而您也不知道。我理解这是出于开发目的,您需要务实,但如果它使您不小心从服务器上为所有会话提供服务,请注意Y那么这将是非常有益的。

好的,是的,你回避这个问题是对的!我实际上已经在做1)我的配置已经有了基于env的覆盖,我可以很容易地为“dev”重新选择内存存储“环境。我可以做到这一点,那么交换会话策略的复杂性就不需要了。然而。。。我最近在另一个SO中读到了关于这个主题的有趣建议,即不要在dev和prod中运行不同的服务,因为您并没有测试所有内容。因此,我想继续在dev中使用memcached,并体验任何怪癖。我认为2)和3)是最合适的。在dev中,只需抛出一个错误,说“嘿,你又忘了docker doofus?”。但在生产中,已经有解决此问题的成熟方法,即memcached已经有了网格/网格概念,并尝试重新连接到各种服务器。我想我不应该试图复制或重新解决那些饱经风霜的技术。我想说,更大的问题是,如果你不小心破坏了配置,推送了代码,突然你的软件甚至没有尝试连接到memache。在这种情况下,你可能永远不会知道,直到你开始得到“99%的服务器内存警报”(取决于应用程序的大小)。我认为可以添加一个额外的功能,只需ping memcache并检查它是否可以在启动应用程序的其余部分之前与服务通信,这是一个相当标准的预先安全检查。