ミッション
1000台分の接続テストがしたい。
下準備
Linuxのシェルスクリプトで
一枚のNICに大量のIPアドレスを割り当てる
Windowsのバッチファイルで
一枚のNICに大量のIPアドレスを割り当てる(Windowsバッチ編)
実装
とある内製サーバーアプリケーションのテストで多数の接続テストがしたい。
でも、そんなにクライアントを用意できないので、仮想クライアントを用意しようというのが始まりです。
一枚のNICに大量のIPアドレスを割り付けて、複数のIPアドレスから繋いでいる風にみせようかと。
とりあえずNode.jsでサーバーとクライアントのアプリのサンプルを作って見ました。
サーバーは待ち受けてエコーしているだけです。
server.js
var net = require('net');
var readline = require('readline');
require('date-utils');
var server = net.createServer();
server.maxConnections = 2000;
function Client(socket){
this.socket = socket;
}
Client.prototype.writeData = function(d){
var socket = this.socket;
if(socket.writable){
var key = socket.remoteAddress + ':' + socket.remotePort;
log('[' + key + '] - ' + d);
socket.write('[R]' + d);
}
};
function log(log) {
var date = new Date();
var formatted = date.toFormat("YYYY/MM/DD HH24:MI:SS");
process.stdout.write( formatted + ":" + log + '\r\n');
}
var clients = {}
server.on('connection', function(socket){
var status = server.connections + '/' + server.maxConnections;
var key = socket.remoteAddress + ':' + socket.remotePort;
log('Connection Start(' + status + ') - ' + key);
clients[key] = new Client(socket);
});
server.on('connection', function(socket){
var data = '';
var newline = /\r\n|\n/;
socket.on('data', function(chunk){
data += chunk.toString();
var key = socket.remoteAddress + ':' + socket.remotePort;
if(newline.test(data)){
clients[key].writeData(data);
data = '';
}
});
});
server.on('connection', function(socket){
var key = socket.remoteAddress + ':' + socket.remotePort;
socket.on('end', function(){
var status = server.connections + '/' + server.maxConnections;
log('Connection End(' + status + ') - ' + key);
delete clients[key];
});
});
server.on('close', function(){
log('Server Closed');
});
server.listen(8778, '172.21.0.228', function(){
var addr = server.address();
log('Listening Start on Server - ' + addr.address + ':' + addr.port);
});
var rl = readline.createInterface(process.stdin, process.stdout);
rl.on('SIGINT', function(){
for(var i in clients){
var socket = clients[i].socket;
socket.end();
}
server.close();
rl.close();
});
クライアントはlocalAddressを変えながら繋いでいます。
client.js
var net = require('net');
require('date-utils');
function log(log) {
var date = new Date();
var formatted = date.toFormat("YYYY/MM/DD HH24:MI:SS");
process.stdout.write( formatted + ":" + log + '\r\n');
}
var adr3Array=[], adr4Array=[];
for(var i=40; adr3Array.push(i++) < 50;);
for(var j=0; adr4Array.push(j++) < 100;);
function clientFunc(local) {
var options = {
port: 8778,
host: '172.21.0.228',
localAddress: local
};
var client = net.connect(options);
client.on('error', function(e){
log(local + ':Connection Failed');
log(e.message);
});
client.on('connect', function(){
log(local + ':Connected');
});
client.setTimeout(1000);
client.on('timeout', function(){
var str = 'Hello World\r\n';
log(local + ":" + str);
client.write(str);
});
client.on('data', function(chunk){
log(local + ":" + chunk.toString());
});
client.on('end', function(had_error){
client.setTimeout(0);
log(local + ':Connetion End');
});
client.on('close', function(){
log(local + ':Client Closed');
});
};
adr3Array.forEach(function(adr3) {
adr4Array.forEach(function(adr4) {
clientFunc('172.21.'+adr3+'.'+adr4);
});
});
確認
サーバー側のログ。
2016/04/29 13:28:58:[172.21.47.28:59911] - Hello World
2016/04/29 13:28:58:[172.21.47.29:59912] - Hello World
2016/04/29 13:28:58:[172.21.47.30:59913] - Hello World
2016/04/29 13:28:58:[172.21.47.31:59914] - Hello World
2016/04/29 13:28:58:[172.21.47.32:59915] - Hello World
2016/04/29 13:28:58:[172.21.47.33:59916] - Hello World
2016/04/29 13:28:58:[172.21.47.34:59917] - Hello World
2016/04/29 13:28:58:[172.21.47.35:59918] - Hello World
2016/04/29 13:28:58:[172.21.47.36:59919] - Hello World
2016/04/29 13:28:58:[172.21.47.37:59920] - Hello World
あとはクライアント側の実装を、実際のサーバーの電文仕様に合わせていこう。
それが大変なわけだが・・・。