送信者が1秒あたり10000リクエストを送信していますが、ServerSocketChannelは8000リクエスト(〜appx)しか読み取りおよび処理できません。Java NIOを使用して1000sの並行接続を処理する方法
public class NioReceiver {
private int port = -1;
private static String message = null;
public void receive() throws IOException {
// Get the selector
Selector selector = Selector.open();
// Selector is open for making connection
// Get the server socket channel and register using selector
ServerSocketChannel SS = ServerSocketChannel.open();
InetSocketAddress hostAddress = new InetSocketAddress(this.port);
SS.bind(hostAddress);
SS.configureBlocking(false);
int ops = SS.validOps();
SelectionKey selectKy = SS.register(selector, ops, null);
for (;;) {
//Waiting for the select operation...
int noOfKeys = selector.select();
// The Number of selected keys are: noOfKeys
Set selectedKeys = selector.selectedKeys();
Iterator itr = selectedKeys.iterator();
while (itr.hasNext()) {
ByteBuffer buffer = ByteBuffer.allocate(1024 * 60);
SelectionKey ky = (SelectionKey) itr.next();
if (ky.isAcceptable()) {
// The new client connection is accepted
SocketChannel client = SS.accept();
client.configureBlocking(false);
// The new connection is added to a selector
client.register(selector, SelectionKey.OP_READ);
// The new connection is accepted from the client: client
} else if (ky.isReadable()) {
// Data is read from the client
SocketChannel client = (SocketChannel) ky.channel();
String output = null;
buffer.clear();
int charRead = -1;
try {
charRead = client.read(buffer);
} catch (IOException e) {
continue;
}
if (charRead <= 0) {
// client closed
client.close();
} else {
output = new String(buffer.array());
message = output;
try {
new Thread(() -> {
processAndStore(message);
}).start();
} catch (Exception e) {
System.err.println("Thread exception:::" + e.getMessage());
}
} // else if of client.isConnected()
} // else if of ky.isReadable()
itr.remove();
} // end of while loop
} // end of for loop
}
public void processAndStore(String output) {
String exchangeName = null;
String dataLine = null;
String Lines[] = output.split("\r\n");
for (int i = 0; i < Lines.length; i++) {
if (Lines[i].contains("Host: ")) {
exchangeName = Lines[i].substring(6);
}
if (Lines[i].isEmpty()) {
dataLine = Lines[i + 1];
}
}
StringBuffer updatedLastLine = null;
if (dataLine != null) {
if (dataLine.contains("POST")) {
updatedLastLine = new StringBuffer(dataLine.substring(0, dataLine.indexOf("POST")));
} else {
updatedLastLine = new StringBuffer(dataLine);
}
if (!dataLine.equals("")) {
try {
if (updatedLastLine.lastIndexOf("}") != -1) {
updatedLastLine.replace(updatedLastLine.lastIndexOf("}"), updatedLastLine.lastIndexOf("}") + 1, ",\"name\":\"" + exchangeName
+ "\"}");
} else {
return;
}
} catch (StringIndexOutOfBoundsException e) {
System.out.println(updatedLastLine + "::" + dataLine);
System.out.println(e);
}
store(updatedLastLine.toString());
}
}
}
public NioReceiver(int port) {
this.port = port;
}
}
私は処理ロジックを削除していた場合、より多くの要求ではなく、すべてを受信することが可能である:
ダミーコードは次のようです。
すべての10000s着信要求を受信するようにコードを改善する方法を教えてください。
高速コンピュータを購入しますか?規格外? --- 'processAndStore()'を呼び出すスレッドを1000個作成するのではなく、スレッドプール/メッセージキューを使用します。スレッドを開始するのは**高価です**。毎秒10000スレッドを開始しますか? * Yikes!* --- **プロファイルコード**は、推測ではなくボトルネックがどこにあるかを見ていますが、ここではいくつかの推測があります:1) 'StringBuffer'を使わず、' StringBuilder'を使います。 2) 'lastIndexOf("}} ")'を3回呼び出さないでください。 – Andreas
NIOの目的は、必要なスレッドの数を減らすことです。あなたはメッセージを持っていないようです。あなたが何を求めているのか不明です。 – EJP
okありがとうございました。私がやったことは、スレッドの作成を取り除いてパフォーマンスが少し向上したことです。また、「NIO」をスキップし、「netty」ベースの受信機と「SimpleChannelInboundHandler」を使用し、同じハードウェア構成でほぼすべての要求を受け取ることができました。 – desaiankitb