我的发件人每秒发送10000个请求(甚至更多),但我的ServerSocketChannel只能读取和处理(在线程中)8000个请求(~appx)。
虚拟代码是这样的:
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;
}
}
当我删除处理逻辑时,它能够接收更多请求,但不是全部。
如何改进我的代码以接收所有10000个传入请求。
答案 0 :(得分:1)
使用线程池/消息队列而不是创建1000个线程来调用processAndStore()
。
启动主题昂贵。
每秒启动10000个线程? 糟糕!
正如@EJP在comment中所说:
NIO的目的是减少所需线程的数量。你似乎没有收到消息。
除此之外,个人资料您的代码,以查看瓶颈所在,而不是猜测。
但是,无论如何,这里有一些猜测:
请勿使用StringBuffer
,请使用StringBuilder
原因:请参阅Difference between StringBuilder and StringBuffer。
请勿拨打lastIndexOf("}")
三次
原因: lastIndexOf()
是一个顺序搜索,所以相对较慢。 JVM可能会也可能不会优化多个调用,但如果性能至关重要,请不要依赖它。通过将结果分配给变量来自己动手。另请参阅Does Java optimize method calls via an interface which has a single implementor marked as final?