Verx 为什么高性能

同步阻塞式编程

大多数应用程序和服务开发框架都基于多线程。 每个连接对应一个线程 ,开发者可以使用传统的 命令式 代码。

image.png

多个线程可以在同一个进程中存活,并行地执行工作,并共享同一片内存空间。

同步阻塞式编程存在的问题

当使用传统的阻塞式API做以下操作时,调用线程可能会被阻塞:

  • 从 Socket 中读取数据
  • 写数据到磁盘
  • 发送消息给接收者并等待回复
  • 其他很多情况

在上述情况下,线程在等待处理结果时它不能做任何事。

image.png

这意味着如果使用阻塞式API处理大量并发, 需要大量线程来防止应用程序停止运转。

而这些线程使用的内存(例如它们的栈)和线程上下文切换带来昂贵的开销。(一个线程大约占用 521KB-1M的内存空间,上下文切换大约在 2.7-5.48us 左右)

缺点如下:

  • 工作负载过高,多线程处理这些请求会产生太多的上下文切换动作。
  • 线程池中处于IO 阻塞的线程不能被复用(处理新的Http请求)。
  • 需要解决多线程进行内存访问所存在的线程安全问题。
  • 阻塞式的方式对于现代应用程序所需要的并发级别来说是难于扩展的。

Verx 异步非阻塞式编程

使用 Asynchronous I/O,可以用更小的线程处理更多的连接。 当一个任务发生了I/O操作时, Asynchronous I/O不会阻塞线程,而是执行其他待处理的任务,待到I/O结果准备好后再继续执行该任务。

Vert.x 使用 事件循环(event­loop) 多路复用并发处理工作负载。

image.png

在event loop 上运行的代码不应执行阻塞I/O及长时间的处理逻辑。所以 Vert.x有一个黄金法则:不要阻塞 event loop。

The Golden Rule – Don’t Block the Event Loop

思考:

你要等多久?它取决于你的应用程序和所需的并发数量。

如果你只有单个 Event Loop,而且你希望每秒处理10000个 HTTP 请求, 很明显的是每一个请求处理时间不可以超过0.1毫秒,所以你不能阻塞任何过多(大于0.1毫秒)的时间。

因为Vert.x API不会阻塞线程, 所以通过Vert.x,你可以只使用少量的线程来处理大量的并发。 例如,一个单独的 Event Loop 可以非常迅速地处理数千个 HTTP 请求。每个 Vertx 实例维护的是 多个Event Loop 线程 。 默认情况下,会根据机器上可用的核数量来设置 Event Loop 的数量。

Verx的最佳实践

客户端发起一个请求,服务器接收到请求后,通过eventbus将请求分发到具体Service里的某个方法,在此方法里进行查询数据库的异步操作,拿到异步结果后(Future/Promise/Coroutines),再通过event bus发送回一个响应,最终写回到客户端。整个操作流程都是异步的。

image.png

感兴趣的小伙伴,可以 clone 下来我的代码:代码仓库

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享