当前的大部分 Java web 容器基于 Bio 线程模型, 例如常见的 tomcat , 默认 200 线程, 即 200 连接. 由此带来的问题是, 如果想提高并发, 或者提高资源利用率, 就得加大线程数.
如下图:
于是出现了类 Netty 的 Reactor 线程模型. 同时, Java 官方也设计了 Servlet 3 异步 API, 可以通过返回类 Feature 的方式, 实现异步编程. 在某些情况下, 也可以实现万级别并发.
但是, 为什么 Java 社区的异步编程无法推广开来? 究其原因, 数据库是罪魁祸首, 再往上看, 其实是 JDBC 的锅, JDBC 定义了一套阻塞式的数据库 IO 通信模型. 这导致每次请求, 线程都阻塞在等待 DB 结果. 进而导致, 服务器资源无法充分利用.
有没有一种办法, 让 Java Web 应用的整个链路都是非阻塞的呢?
答: 有.
异步编程是提高生产力的关键. 下图是我们今天假设的模型:
其实非常简单.
我们让 tomcat 支持 Servlet 3 异步编程模型, 接口返回 feature 即可, 这个功能其实有很多 Web 容器都实现了. 关键的是, 我们让 DB 客户端和服务器都支持异步编程模型. 让 DB 像 netty 复用 IO 连接, 业务线程只需要将 SQL 交个 数据库 client 即可返回 feature, 然后释放当前线程 (再也不用阻塞, 这是关键), 等 DB 操作结果返回时, 只需通知这个 feature 即可. 这将极大的提高线程的利用率, 不夸张的说, 只需 8 条线程, 就足以承受万级别的并发.
整个的调用流程如下图:
我们看到, 当一个 http 请求过来, 整个流程是无阻塞的, 不用等待 数据库 返回结果, 业务只需添加回调即可, 当数据库结果返回时, 自动触发回调.
当然, 这只是我的一个小设想, MySQL 要重写连接器, 我估计是太难了. 但是, 那些新一代的数据库, 是否能够把连接器设计成支持异步, 支持多路复用的呢? 这样, Web 应用的客户端, 就能够把整个链路设计成异步的, 这将节约很多资源, 提高生产力.
希望那一天快点到来.
来源: https://www.cnblogs.com/stateis0/p/10963171.html