伪异步IO压测

77 阅读1分钟

只做各种IO方式的横向比较,故不列具体机器规格


一、 服务端源码

TimeServer.class

 import java.io.IOException;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 ​
 public class TimeServer {
     private static ExecutorService executor = new ThreadPoolExecutor(10, 10, 120L, TimeUnit.SECONDS,
         new ArrayBlockingQueue<>(10000));
 ​
     public static void main(String[] args) throws IOException {
         int port = 8080;
         if (args != null && args.length > 0) {
             try {
                 port = Integer.valueOf(args[0]);
             } catch (NumberFormatException e) {
 ​
             }
         }
 ​
         try (ServerSocket server = new ServerSocket(port);) {
             System.out.println("The time server is start in port: " + port);
             Socket socket = null;
             while (true) {
                 socket = server.accept();
                 executor.execute(new TimeServerHandler(socket));
             }
         }
     }
 }

TimeServerHandler.class

 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.net.Socket;
 import java.util.Date;
 ​
 public class TimeServerHandler implements Runnable {
     private Socket socket;
 ​
     public TimeServerHandler(Socket socket) {
         this.socket = socket;
     }
 ​
     @Override
     public void run() {
         try (BufferedReader in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
             PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true);){
 ​
             String currentTime = null;
             String body = null;
             while (true) {
                 body = in.readLine();
                 if (body == null) {
                     break;
                 }
                 System.out.println("The time server receive order : " + body);
                 currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(
                     System.currentTimeMillis()).toString() : "BAD ORDER";
                 out.println(currentTime);
             }
         } catch (Exception e) {
             try {
                 this.socket.close();
             } catch (IOException ioException) {
                 ioException.printStackTrace();
             }
         }
 ​
     }
 }

二、Jemeter 压测结果

5线程

Jconsole结果 伪异步IO 5线程压测Jconsole结果.png Jemeter吞吐量 伪异步IO 5线程压测吞吐量.png

CPU占用率18.6%,吞吐量53611。

10线程

Jconsole结果 伪异步IO 10线程压测Jconsole结果.png Jemeter吞吐量 伪异步IO 10线程压测吞吐量.png

CPU占用率18.6%,吞吐量66699。

20线程

Jconsole结果 伪异步IO 20线程压测Jconsole结果.png Jemeter吞吐量 伪异步IO 20线程压测吞吐量.png

CPU占用率19.2%,吞吐量63006。

对于伪异步IO的线程池使用,优缺点都是比较明显的,由于线程池固定10个线程,Jemeter 5线程压测时吞吐量更高,因为服务端起了超过5个线程进行处理,10线程压测时差别不大,20线程压测吞吐量反而不如10线程,还产生了大量失败的请求,因为服务端处理能力不足。