BIO、NIO、AIO三者的比较
消息时的系统通信,通常基于网络协议实现。常见的协议包括TCP/IP,UDP/IP。
TCP/IP等协议用于数据传输,但要完成通信,还需要对数据进行处理。例如读取和写入数据。
I/O可以分为两种:同步IO和异步IO,同步I/O最常见的是 BIO(Blocking IO)、NIO(Non-Blocking IO)
BIO:是当发起I/O的读或写操作时,均为阻塞方式,直到应用程序读到了流或者将流写入数据。
NIO:基于事件驱动思想,常采用reactor(反应器)模式。当发起 IO请求时,应用程序是非阻塞的。当SOCKET有流可读或写的时候,由操作系统通知应用程序,应用程序再将流读取到缓冲区或者写入系统。
AIO:同样基于事件驱动的思想,通常采用Proactor(前摄器模式)实现。在进行I/O操作时,直接调用API的read或write,这两种方法均为异步。对于读操作,操作系统将数据读到缓冲区,并通知应用程序,对于写操作,操作系统将write方法传递的流写入并主动通知应用程序。它节省了NIO中遍历事件通知队列的代价。
这里注意比较NIO和AIO的不同,AIO是操作系统完成IO并通知应用程序,NIO是操作系统通知应用程序,由应用程序完成。
spring boot tomcat 默认线程100个,tomcat 9
spring boot 使用servlet 方式
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
异步servlet
image.png
@WebServlet(urlPatterns = "/async", asyncSupported = true)
@Slf4j
public class ASyncServlet extends HttpServlet {
Executor poolExecutor = Executors.newFixedThreadPool(300);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext asyncContext = req.startAsync();
CompletableFuture.runAsync(() -> {
ServletRequest request = asyncContext.getRequest();
ServletResponse response = asyncContext.getResponse();
try {
TimeUnit.SECONDS.sleep(3);
PrintWriter writer = response.getWriter();
writer.print("hello async");
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
asyncContext.complete();
}, poolExecutor);
}
}
异步servlet
ab -c 300 -n 1000 http://localhost:8080/async
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /async
Document Length: 11 bytes
Concurrency Level: 300
Time taken for tests: 15.186 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 104000 bytes
HTML transferred: 11000 bytes
Requests per second: 65.85 [#/sec] (mean)
Time per request: 4555.704 [ms] (mean)
Time per request: 15.186 [ms] (mean, across all concurrent requests)
Transfer rate: 6.69 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 10
Processing: 3000 3018 23.7 3005 3233
Waiting: 3000 3012 17.2 3003 3063
Total: 3000 3019 23.8 3006 3234
同步servlet
@WebServlet(urlPatterns = "/sync")
@Slf4j
public class SyncServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintWriter writer = resp.getWriter();
writer.print("hello async");
writer.close();
}
}
ab -c 300 -n 1000 http://localhost:8080/sync
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /sync
Document Length: 11 bytes
Concurrency Level: 300
Time taken for tests: 18.118 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 104000 bytes
HTML transferred: 11000 bytes
Requests per second: 55.19 [#/sec] (mean)
Time per request: 5435.342 [ms] (mean)
Time per request: 18.118 [ms] (mean, across all concurrent requests)
Transfer rate: 5.61 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.5 1 2
Processing: 3002 4195 1401.3 3071 5942
Waiting: 3000 4188 1404.7 3059 5942
Total: 3003 4196 1401.4 3072 5942
异步模式下使用 300个处理线程在跑分生超出同步模式不少