Reactor模式(反应器模式)分发恰当的handler来对io event 进行response(netty中的assetExtension就是一个Reactor)
客户端向Reactor线程发起连接,然后Reactor线程将客户端的请求派发给其他xia线程进行请求,在其他请求中完成解码。计算,编码,响应等
作用就是为了在服务端处理并行的客户端请求
netty的 bossGroup和workerGroup是通过 workerGroup的selectionKey所产生的socketchannel进行连接的
Reactor角色在启动之后,先会将若干个具体事件处理器注册到它上面,注册完之后,制定好感兴趣的事件后,一旦后续有感兴趣的事情发生的时候.就由Reactor角色(Initiation Dispatcher)去调用具体的事件处理器,当事件处理器注册完之后,Initiation Dispatcher就开启了自己的事件循环(死循环)
当事件(Handle)产生之后,Synchronous Event Demultiplexer(同步事件分离器 也就是 SelectionKeySet)会获取到产生这个事件的集合,**会返回给Initiation Dispatcher,**它会知道事件是什么.然后select(),选择与这个事件对应的事件处理器,然后遍历这个事件处理器,根据这个事件的类型,来去调用注册到它上面的Concrte Event Handler(具体事件处理器) 的handle_event(type)
netty整体架构是Reactor模式的体现
Reactor流程,
1.当应用向Initiation Dispatcher注册具体的事件处理器对象时,应用会标识出该事件处理器,希望Initiation Dispatcher在某个事件发生时,向其通知该事件,该事件与Handle关联
2.Initiation Dispatcher会要求每个事件处理器向其传递内部的handle,该handle向os标识了事件处理器
3.当所有的事件处理器注册完之后,应用会调用Handle_events方法来启动Initiation Dispatcher的事件循环(死循环),这时,Initiation Dispatcher会将每个注册的事件管理器的Handle合并起来,并使用同步事件分离器(Selection.key)来等待这些事件的发生,比如说 TCP协议层会使用Select同步事件分离层来等待client send data连接到 socket handle 上
4.当与某个事件对应的handle变为ready状态时,(比如 TCP socket变为等待读时) 同步事件分离器 就会通知 Initiation Dispatcher
5.Initiation Dispatcher会触发事件处理器的回调方法,从而响应这个处于ready状态的handle.当事件发生时,Initiation Dispatcher会将被事件激活的handle作为 key 来寻找并分发恰当的事件处理器回调方法,
6.Initiation Dispatcher会回调事件处理器的handle_events回调方法来执行特定于应用的功能,(开发者自己所编写的功能),从而响应这个事件,所发生的事件类型可以作为该方法参数并被该方法内部使用来执行额外的特定于服务的分离与分发
MainReactor和SubReactor之间的连接是由acceptor来接收,acceptor本身也是一个事件处理器,会被piple加到最后
@Override
void init(Channel channel) throws Exception {
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
setChannelOptions(channel, options, logger);
}
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}
ChannelPipeline p = channel.pipeline();
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
}
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
}
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final Channel child = (Channel) msg;
child.pipeline().addLast(childHandler);
setChannelOptions(child, childOptions, logger);
for (Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try {
childGroup.register(child).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}