Q1:eventdriver是个啥?有什么用
Q2:netty怎么实现eventdriver
Q3:reactor模型和proactor
上来三联问,不懂的还不快上车一起看看这都怎么事儿?
A1:事件驱动真的非常easy
一切的故事还得从”同步式“代码讲起,试想我们最熟悉的原生socket,每次我们为一个socket连接建立一个handler线程去处理对应的handler和filter,那么默认场景下就还好。突然某天连接数陡增,而且来了很多占着连接不拉shi的怪癖连接。那么服务的accept和read,write都会收到影响,如果我们把accept和read/write都抽象成事件去理解,我们的work线程只关心具体时间的发生,在把时间的执行进行分发处理,情况是不是就好转很多?让我们的cpu彻底丧失摸鱼机会。
当然这是抽象上的模型,实际的落地要比这复杂一些,有能力的可以参考下vert.x,micronaut的设计思想。
A2:大名鼎鼎的netty要出场了
netty是一个网络编程框架,所以一切还是围绕socket的读写展开,netty对socket的accept/write/read做了抽象,同时也对事件循环做了自己的实现也就是一个叫做EventLoop的东西,抛开eventloop的实现方式,本质的讲,eventloop就是围绕注册到自身的事件来循环事件是否发生,发生后再交给pipeline去进一步handler,其实这里的实现就和servlet的filterchain实现非常像了。channel这里担任一个wrapper的角色,它屏蔽了netty的事件循环已经jdk底层的socket的不同性质,使得所有的eventloop都可以对同一种的channel展开。而实际上每个loop还是一个excutor,这就是netty的事件驱动方案。
当然netty还有很多其他概念,包括task等等实现细节请看下节详细分析。
A3:这里引用一张著名的reactor的图例
1.主从结构
这是一个典型的主从reactor模型,当然除此还有单/多线程模型,当然他们都是上述模型的简化版本,那这种模型有啥好处让我专门贴了张图?
显而易见,主从两个线程只关心响应事件的处理,具体的handler是交给worker去做了,这样性能瓶颈不会出现在连接事件的处理上,相当于先把客人接进来再排队,通俗一点的就是让cpu忙真正的起来。而不是让事件处理影响handler处理。
但是这样就解决根本问题了吗?并没有,现在解决的仅仅是事件处理时的拥塞问题,但是我们的事件处理仍然是同步的,仍然会产生性能瓶颈,那么就需要再度进行升级。
2.Proactor
既然同步处理是现在的瓶颈那么有没有办法让它异步起来呢?当然有
这就要说到异步io了,(对五大io不熟悉的同学赶快恶补一下)。proactor实现的是所有handler都交给worker去执行,主线程去处理io事件,那么主线程处理就要保证io是异步的(因为同步的那不就思想倒退了。。。)通过aio让内核去准备数据,当数据准备好了,触发回调信息/函数完成io。
这样看来是不是这个模型看来就完整多了~
关于netty的源码和架构还会进一步细化分析,请看下节😎😎😎