用同一個Java Socket Client 分別調用用BIO和NIO實現的Socket Server, 觀察其創建一個Socket (TCP Connection)所須要的時間,從而計算出Server吞吐量TPS。html
之因此能夠用Connection創建時間來計算TPS,而不考慮業務邏輯運行時間,是由於這裏的業務邏輯很簡單,只是Echo回從client傳過來的字符,所消耗時間能夠忽略不計。java
注意: 在現實場景中,業務邏輯會比較複雜,TPS的計算必須綜合考慮IO時間+業務邏輯執行時間+多線程並行運行狀況 等因素的影響。編程
1. Java Socket Client服務器
public class PlainEchoClient { public static void main(String args[]) throws Exception { for (int i = 0; i < 20; i++) { startClientThread(); } } private static void startClientThread() throws UnknownHostException, IOException { Thread t = new Thread(new Runnable() { @Override public void run() { try { startClient(); } catch (Exception e) { e.printStackTrace(); } } }); t.start(); } private static void startClient() throws UnknownHostException, IOException { long beforeTime = System.nanoTime(); String host = "127.0.0.1"; int port = 8086; Socket client = new Socket(host, port); // 創建鏈接後就能夠往服務端寫數據了 Writer writer = new OutputStreamWriter(client.getOutputStream()); writer.write("Hello Server."); writer.flush(); // 寫完之後進行讀操做 Reader reader = new InputStreamReader(client.getInputStream()); char chars[] = new char[64];// 假設所接收字符不超過64位,just for demo int len = reader.read(chars); StringBuffer sb = new StringBuffer(); sb.append(new String(chars, 0, len)); System.out.println("From server: " + sb); writer.close(); reader.close(); client.close(); System.out.println("Client use time: " + (System.nanoTime() - beforeTime) + " ns"); } }
2. IO Socket Server網絡
這個Socket Server模擬的是咱們常用的thread-per-connection模式, Tomcat,JBoss等Web Container都是這種方式。多線程
public class PlainEchoServer { private static final ExecutorService executorPool = Executors.newFixedThreadPool(5); private static class Handler implements Runnable{ private Socket clientSocket; public Handler(Socket clientSocket){ this.clientSocket = clientSocket; } @Override public void run() { try { BufferedReader reader = new BufferedReader( new InputStreamReader( clientSocket.getInputStream())); PrintWriter writer = new PrintWriter( clientSocket.getOutputStream(), true); char chars[] = new char[64]; int len = reader.read(chars); StringBuffer sb = new StringBuffer(); sb.append(new String(chars, 0, len)); System.out.println("From client: " + sb); writer.write(sb.toString()); writer.flush(); } catch (IOException e) { e.printStackTrace(); try { clientSocket.close(); } catch (IOException ex) { // ignore on close } } } } public void serve(int port) throws IOException { final ServerSocket socket = new ServerSocket(port); try { while (true) { long beforeTime = System.nanoTime(); final Socket clientSocket = socket.accept(); System.out.println("Establish connection time: "+ (System.nanoTime()-beforeTime)+" ns"); executorPool.execute(new Handler(clientSocket)); } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException{ PlainEchoServer server = new PlainEchoServer(); server.serve(8086); } }
public class PlainNioEchoServer { public void serve(int port) throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); ServerSocket ss = serverChannel.socket(); InetSocketAddress address = new InetSocketAddress(port); ss.bind(address); // #1 serverChannel.configureBlocking(false); Selector selector = Selector.open(); serverChannel.register(selector, SelectionKey.OP_ACCEPT); // #2 while (true) { try { selector.select(); // #3 } catch (IOException ex) { ex.printStackTrace(); // handle in a proper way break; } Set readyKeys = selector.selectedKeys(); // #4 Iterator iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); try { if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key .channel(); long beforeTime = System.nanoTime(); SocketChannel client = server.accept(); // #6 System.out.println("Accept connection time: "+ (System.nanoTime()-beforeTime)+" ns"); if (client == null){//Check if socketChannel has been created, it could be null, because it's non-blocking continue; } client.configureBlocking(false); client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, ByteBuffer.allocate(100)); } if (key.isReadable()) { SocketChannel client = (SocketChannel) key.channel(); ByteBuffer output = (ByteBuffer) key.attachment(); client.read(output); } if (key.isWritable()) { SocketChannel client = (SocketChannel) key.channel(); ByteBuffer output = (ByteBuffer) key.attachment(); output.flip(); client.write(output); output.compact(); } } catch (IOException ex) { key.cancel(); try { key.channel().close(); } catch (IOException cex) { } } iterator.remove(); // #5 } } } public static void main(String[] args) throws IOException{ PlainNioEchoServer server = new PlainNioEchoServer(); server.serve(8086); } }
版權聲明:本文爲博主原創文章,未經博主容許不得轉載。併發