我尝试在服务器端使用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
};
我怎样才能实现那些“读写回写”部分?
答案 0 :(得分:1)
简短的回答:不可能将res
对象放入缓存中,并以任何有意义的方式从另一个进程再次获取它。
如果您考虑轮询的工作时间,每个HTTP客户端都会保持与服务器的开放连接,等待(很长一段时间)发送回来。换句话说,当你推出新消息时,你只是在已经打开的连接上发送数据。如果您将res
缓存到redis中,连接会发生什么?
可能无关紧要,只要您有办法在4个后端进程之间传递内容,他们就可以更新自己的res
个连接集。新的连接仍然是负载平衡的。