我正在为我的socket.io应用程序创建一个负载测试应用程序。当服务器端发生数据库错误时,会发生非常奇怪的结果。在DB死锁时,服务器会发出正确的事件,但在客户端会调用错误的事件。
服务器代码:
(I even got rid of all DB code and just output what the DB would output so
I know it's nothing to do with the DB)
function AddUser(gObj, cb) {
if (gObj.UKEY==2)
cb({err: 901, errm: "deadlock baby"});
else if (gObj.UKEY==3)
cb(null, [3,0,0,1,0]);
else
cb(null, [1,1,0,1,0]);
}
var io=require('socket.io')(8080);
var iowm = io.of('/mpp');
iowm.on('connection', function(socket) {
console.log('in MPP connection');
socket.on('nu', function(data) {
console.log('APP: in AddUser');
AddUser(data, function(err, result) {
console.log('RC: ',data);
if (err) {
console.log(err);
iowm.emit('error', {ERRM: err.errm});
console.log('ERROR: emitted');
} else {
console.log('done: ',result);
iowm.emit('done', result);
}
});
});
});
io.httpServer.on('listening', function() {
console.log('listening on port ',io.httpServer.address().port);
});
console.log('Done...');
客户代码:
(我将套接字事件包装在包装函数中(这可能是我的错误所在),以便在此紧密循环中将正确的参数传递给套接字事件)
for(var i=0; i<args[4]; i++) {
age = (Math.floor(Math.random()*args[3]) + 1) * 4;
console.log('ukey: '+args[2],' age: ',age);
socket = io.connect('http://localhost:8080/mpp');
if (socket) {
var OrigSocketOn = socket.on;
socket.on = function(event, data, cb2) {
return OrigSocketOn.call(socket, event, function(res) {
console.log('ESock: ', event,' data: ',data);
switch(data.ENT) {
case 2: // connect
cb2(data);
break;
case 3: // error
cb2({data: data, result: res});
break;
default:
cb2(res);
break;
}
});
};
socket.on('connect', {ENT: 2, GKEY: args[1], UKEY: args[2], AGE: age}, function(data) {
socket.emit('nu', {GKEY: data.GKEY, UKEY: data.UKEY, AGE: data.AGE});
});
socket.on('done', {ENT: 4, UKEY: args[2], AGE: age}, function(data) {
++cnt;
console.log('SOCKET: NewUser Done cnt: ',cnt);
console.log(data);
socket.close();
if (cnt == args[4] || data[4]>0)
cb();
});
socket.on('error', {ENT: 3, GKEY: args[1], UKEY: args[2], AGE: age}, function(data) {
console.log('SOCKET: NewUser Err');
console.log(data);
if (data.result.ERRM.indexOf('deadlock') > -1) { // deadlock - try again
socket.emit('nu', {GKEY: data.GKEY, UKEY: data.UKEY, AGE: data.AGE});
} else {
socket.close();
if (++cnt == args[4])
cb();
}
});
...
服务器输出:
(一切看起来不错。UKEY1和3恢复正常,并发出'done'事件。但是UKEY == 2是死锁的条目,因此它发出'error'事件。
in MPP connection
in MPP connection
in MPP connection
APP: in AddUser
RC: { GKEY: 1, UKEY: 3, AGE: 32 }
done: [ 3, 0, 0, 1, 0 ]
APP: in AddUser
RC: { GKEY: 1, UKEY: 1, AGE: 40 }
done: [ 1, 1, 0, 1, 0 ]
APP: in AddUser
RC: { GKEY: 1, UKEY: 2, AGE: 40 }
{ err: 901, errm: 'deadlock baby' }
ERROR: emitted
客户端输出:(这是问题)
ukey: 1 age: 40
ukey: 2 age: 40
ukey: 3 age: 32
ESock: connect data: { ENT: 2, GKEY: 1, UKEY: 1, AGE: 40 }
ESock: connect data: { ENT: 2, GKEY: 1, UKEY: 2, AGE: 40 }
ESock: connect data: { ENT: 2, GKEY: 1, UKEY: 3, AGE: 32 }
ESock: done data: { ENT: 4, UKEY: 1, AGE: 40 }
SOCKET: NewUser Done cnt: 1
[ 3, 0, 0, 1, 0 ]
ESock: done data: { ENT: 4, UKEY: 2, AGE: 40 }
SOCKET: NewUser Done cnt: 2
[ 3, 0, 0, 1, 0 ]
ESock: done data: { ENT: 4, UKEY: 1, AGE: 40 }
SOCKET: NewUser Done cnt: 3
[ 1, 1, 0, 1, 0 ]
那么3个问题:
1)客户端“完成”事件看似被调用了3次,而应该只有2次,而“错误”事件应被调用一次。
2)第1和第3个“完成”事件的数据相同(UKEY:1),应分别为(UKEY:1)和(UKEY:3)
3)(UKEY:3)根本没有输出数据。
答案 0 :(得分:1)
在我看来,您在iowm.emit(...)
的服务器上应该做socket.emit(...)
。
您的客户端显然正在与服务器建立多个连接,因为io.connect()
循环中有一个for(var i=0; i<args[4]; i++)
。因此,当您在服务器上执行iowm.emit(...)
时,它将向客户端发送所有连接,而不仅仅是发生错误的连接。
1)客户端“完成”事件看似被调用了3次,而应该只有2次,而“错误”事件应被调用一次。
因为您正在将错误传播给所有客户端连接,而不仅仅是错误发生的那一个socket
。