보낸 사람이 초당 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;
}
}
내가 처리 로직을 제거하고 때 더 많은 요청 전부는 아니지만을받을 수있다.
들어오는 요청을 모두받는 코드를 개선하려면 어떻게해야합니까?
더 빠른 컴퓨터를 사십시오? 스케일 아웃? ---'processAndStore()'를 호출하기 위해 1000 개의 쓰레드를 생성하는 대신 쓰레드 풀/메시지 큐를 사용하십시오. 스레드를 시작하는 것은 ** 고비용 **입니다. 초당 10000 개의 스레드를 시작 하시겠습니까? * Yikes! * --- ** 프로파일 코드 **는 추측보다는 병목 현상을 파악하지만 어쨌든 여기서는 추측 할 수 있습니다. 1)'StringBuffer'를 사용하지 말고'StringBuilder'를 사용하십시오. 2)'lastIndexOf ("}}")'를 세 번 호출하지 마십시오. – Andreas
NIO의 목적은 필요한 스레드의 수를 줄이는 것입니다. 당신은 그 메시지를 가지고 있지 않은 것 같습니다. 네가 묻고있는 것이 불분명하다. – EJP
알맞은 답변을 주셔서 감사합니다. 그 동안 내가 한 일은 스레드 생성을 제거하고 성능을 약간 향상 시켰습니다. 또한, 'NIO'를 건너 뛰고 'netty'기반의 수신기와 'SimpleChannelInboundHandler'를 사용했으며 동일한 하드웨어 구성으로 거의 모든 요청을받을 수있었습니다. – desaiankitb