1.Netty的简单介绍
① Netty是基于Java NIO的网络应用框架,client-server框架
② Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过FutureListener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。
③ 作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用。
2.Netty中的观察者模式
(1)经典的“观察者模式”模型图
(2)netty版本:5.0.0(github)
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha2</version> </dependency>
(3)代码举例
1 public void nettyTest(NioSocketChannel channel, Object object) { 2 //新建被观察者 3 ChannelFuture channelFuture = channel.writeAndFlush(object); 4 //添加观察者一 5 channelFuture.addListener(future -> { 6 if (future.isSuccess()) { 7 8 } else { 9 10 } 11 }); 12 //添加观察者二 13 channelFuture.addListener(future -> { 14 if (future.isSuccess()) { 15 16 } else { 17 18 } 19 }); 20 }
(4)创建被观察者
1 @Override 2 public ChannelFuture writeAndFlush(Object msg) { 3 return writeAndFlush(msg, newPromise()); 4 } 5 6 @Override 7 public ChannelPromise newPromise() { 8 return new DefaultChannelPromise(channel(), executor()); 9 }
追溯上述例子中的源代码,发现 writeAndFlush() 最终返回的是一个 ChannelPromise 的对象,即被观察者。
(5)添加观察者
1 synchronized (this) { 2 if (!isDone()) { 3 if (listeners == null) { 4 listeners = listener; 5 } else { 6 if (listeners instanceof DefaultFutureListeners) { 7 ((DefaultFutureListeners) listeners).add(listener); 8 } else { 9 final GenericFutureListener<? extends Future<V>> firstListener = 10 (GenericFutureListener<? extends Future<V>>) listeners; 11 listeners = new DefaultFutureListeners(firstListener, listener); 12 } 13 } 14 return this; 15 } 16 }
跟踪 addListener() 方法,在DefaultPromise类里面发现这样上述代码
public void add(GenericFutureListener<? extends Future<?>> l) { GenericFutureListener<? extends Future<?>>[] listeners = this.listeners; final int size = this.size; if (size == listeners.length) { this.listeners = listeners = Arrays.copyOf(listeners, size << 1); } listeners[size] = l; this.size = size + 1; if (l instanceof GenericProgressiveFutureListener) { progressiveSize ++; } }
点击 add() 方法,发现多个listener被封装成一个GenericFutureListener数组,也就是多个观察者
(6)如何通知
@Override public boolean trySuccess(V result) { if (setSuccess0(result)) { notifyListeners(); return true; } return false; } ...... try { l.operationComplete(future); } catch (Throwable t) { logger.warn("An exception was thrown by " + l.getClass().getName() + ".operationComplete()", t); }
同样的,在 writeAndFlush() 方法的跟踪过程中,分别有 notifyListeners() 方法和 operationComplete() 方法,实现通知观察者的功能,完成异步流程。
3.总结:
netty通过Promise模式或者说ChannelFuture模式实现了观察者模式。netty通过实现观察者模式达到异步通知,每次写成功写失败,都会回调给listener,也就是回调到future.isSuccess()等方法。其实就是变种的观察者模式。
优点:在netty中使用观察者模式,可以充分利用NioEventLoopGroup这一线程池的资源,避免启动线程阻塞在网络链接上。
4.参考文献