使用node.js进行长轮询并表达:如何将res对象缓存到redis或其他缓存框架中

时间:2014-01-25 08:35:36

标签: javascript json node.js express redis

我尝试在服务器端使用node.js / express / redis构建聊天室网页。

遵循这段代码:A Message Wall With Long Poll Properties in Node.JS and Express,我成功地使一个节点服务器正常运行。在此示例中,res对象保存在列表中,不需要任何转换。

但是我想用pm2集群模式(-i 4)运行节点应用程序,所以我必须将res对象保存到4个节点之间共享的某个地方。

我已经在我的节点项目中使用了redis,用于express.session。所以我想将res缓存到redis中。

但问题出现了:当我尝试用res来强制JSON.stringify(res)对象时,我得到了:

TypeError: Converting circular structure to JSON

我的问题是:

如何保存一个res对象以供以后在节点群集中使用,使用redis或其他内容。

欣赏。


我使用util.inspect打印出res(chatroom_id:res)对象的容器:

{ '0': null,
  '1390640136999': 
   { domain: null,
     _events: 
      { finish: [Object],
    header: [Function],
    close: [Function: logRequest] },
     _maxListeners: 10,
     output: [],
     outputEncodings: [],
     writable: true,
     _last: false,
     chunkedEncoding: false,
     shouldKeepAlive: false,
     useChunkedEncodingByDefault: false,
     sendDate: true,
     _headerSent: false,
     _header: '',
     _hasBody: true,
     _trailer: '',
     finished: false,
     _hangupClose: false,
     socket: 
      { _connecting: false,
    _handle: [Object],
    _readableState: [Object],
    readable: true,
    domain: null,
    _events: [Object],
    _maxListeners: 10,
    _writableState: [Object],
    writable: true,
    allowHalfOpen: true,
    onend: [Function],
    destroyed: false,
    errorEmitted: false,
    bytesRead: 894,
    _bytesDispatched: 0,
    _pendingData: null,
    _pendingEncoding: '',
    server: [Object],
    _idleTimeout: 120000,
    _idleNext: [Object],
    _idlePrev: [Object],
    _idleStart: 1390640145289,
    parser: [Object],
    ondata: [Function],
    _paused: false,
    _httpMessage: [Circular],
    _peername: [Object] },
     connection: 
      { _connecting: false,
    _handle: [Object],
    _readableState: [Object],
    readable: true,
    domain: null,
    _events: [Object],
    _maxListeners: 10,
    _writableState: [Object],
    writable: true,
    allowHalfOpen: true,
    onend: [Function],
    destroyed: false,
    errorEmitted: false,
    bytesRead: 894,
    _bytesDispatched: 0,
    _pendingData: null,
    _pendingEncoding: '',
    server: [Object],
    _idleTimeout: 120000,
    _idleNext: [Object],
    _idlePrev: [Object],
    _idleStart: 1390640145289,
    parser: [Object],
    ondata: [Function],
    _paused: false,
    _httpMessage: [Circular],
    _peername: [Object] },
     _headers: { 'x-powered-by': 'Express' },
     _headerNames: { 'x-powered-by': 'X-Powered-By' },
     req: 
      { _readableState: [Object],
    readable: true,
    domain: null,
    _events: {},
    _maxListeners: 10,
    socket: [Object],
    connection: [Object],
    httpVersion: '1.0',
    complete: true,
    headers: [Object],
    trailers: {},
    _pendings: [],
    _pendingIndex: 0,
    url: '/robot/chat/query/99/1390640136999/270125/',
    method: 'GET',
    statusCode: null,
    client: [Object],
    _consuming: false,
    _dumped: false,
    httpVersionMajor: 1,
    httpVersionMinor: 0,
    upgrade: false,
    originalUrl: '/robot/chat/query/99/1390640136999/270125/',
    _parsedUrl: [Object],
    query: {},
    res: [Circular],
    next: [Function: next],
    secret: undefined,
    cookies: [Object],
    signedCookies: {},
    sessionStore: [Object],
    sessionID: '4PACUldyCHhT8NgdGY1yz9Pk',
    session: [Object],
    _startTime: Sat Jan 25 2014 16:55:45 GMT+0800 (CST),
    _remoteAddress: '127.0.0.1',
    body: {},
    originalMethod: 'GET',
    _route_index: 2,
    route: [Object],
    params: [Object] },
     locals: [Function: locals],
     end: [Function],
     student_id: '99',
     channel_id: '1390640136999',
     last_msg_id: '270125' } }

有三个[通告]。


我的伪代码:

/*
 * query from http client
 * url: /chat/query/:student_id/:channel_id/:last_msg_id/
 */
exports.query = function(req, res){

    // if find some new msg
        // return them as json, immediately
    // else
        // set participator info into res object
        // read the res_list from redis
        // put this res into res_list
        // write back res_list into redis

};


/*
 * notification from other web server: one new msg been created
 * url: /chat/notify/:new_msg_id/
 */
exports.notify = function(req, res){

    // get new_msg from database by id

    // read the res_list from redis
    // for old_res in res_list
        // if this old_res is releated with the new_msg (participator)
            // old_res.sent(json_content)
            // remove this old_res from res_list
    // write back res_list into redis

};

我怎样才能实现那些“读写回写”部分?

1 个答案:

答案 0 :(得分:1)

简短的回答:不可能将res对象放入缓存中,并以任何有意义的方式从另一个进程再次获取它。

如果您考虑轮询的工作时间,每个HTTP客户端都会保持与服务器的开放连接,等待(很长一段时间)发送回来。换句话说,当你推出新消息时,你只是在已经打开的连接上发送数据。如果您将res缓存到redis中,连接会发生什么?

可能无关紧要,只要您有办法在4个后端进程之间传递内容,他们就可以更新自己的res个连接集。新的连接仍然是负载平衡的。