Netty线程模型、Future、Channel总结和源码分析
创作时间:
作者:
@小白创作中心
Netty线程模型、Future、Channel总结和源码分析
引用
1
来源
1.
http://www.cdweb.net/article/jpoppo.html
Netty线程模型
Netty提供了灵活的线程模型配置,包括单线程Reactor、多线程Reactor和多层线程Reactor。无论采用哪种线程模型,都通过单一的Acceptor接收客户端请求,然后可以创建多个NioEventLoop来处理IO操作。
EventLoop和EventLoopGroup实际上继承了Java的ScheduledExecutorService,具备线程池的特性,线程数量可以根据需要动态配置。例如,配置单线程模型时,只需将线程数量设置为1即可。
Future和Promise机制
Future
Future代表一个异步操作的结果。其主要方法包括:
close():关闭Future,但结果未知get():获取操作结果,但会阻塞当前线程isDone():判断操作是否完成
ChannelFuture是专门用于获取异步返回结果的Future类型。
ChannelFutureListener
可以通过实现ChannelFutureListener接口来获得回调,无需等待get方法返回。
public interface ChannelFutureListener extends GenericFutureListener {
ChannelFutureListener CLOSE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
future.channel().close();
}
};
ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
future.channel().close();
}
}
};
ChannelFutureListener FIRE_EXCEPTION_ON_FAILURE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
future.channel().pipeline().fireExceptionCaught(future.cause());
}
}
};
}
连接超时和channel超时配置
在Bootstrap中可以配置连接超时时间:
Bootstrap bootstrap = new Bootstrap();
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
channelFutrue.awaitUninterruptibly(10, TimeUnit.SECONDS);
需要注意以下两点:
- 谨慎使用await,可能导致死锁。
- ChannelFuture超时后如果调用了业务代码重连,而此时IO未超时,将可能导致多条连接并存,设置IO超时时间建议小于业务代码超时时间。
Promise
Promise是Future的升级版,不仅支持读取结果,还支持在回调过程中进行操作。例如,DefaultPromise类中的awaitUninterruptibly方法可以手动打断回调,使进程等待。
public Promise awaitUninterruptibly() {
if (this.isDone()) {
return this;
} else {
boolean interrupted = false;
synchronized(this) {
while(!this.isDone()) {
this.checkDeadLock();
this.incWaiters();
try {
this.wait();
} catch (InterruptedException var9) {
interrupted = true;
} finally {
this.decWaiters();
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
return this;
}
}
其中,checkDeadLock方法用于避免死锁,incWaiters方法限制了最大等待数量为32767。
Channel和Unsafe
Channel负责对外提供操作IO的接口,而Unsafe是Channel的内部接口类,封装了一些不安全的操作,不允许外部直接调用。实际的IO操作最终都在Unsafe中执行。
以Channel的连接操作为例,跟踪其实现过程:
// Channel调用连接
ChannelFuture connect(SocketAddress var1);
// DefaultChannelPipeline中执行,实际是调用尾部的pipeline
public ChannelFuture connect(SocketAddress remoteAddress) {
return this.tail.connect(remoteAddress);
}
// AbstractChannelHandlerContext持续寻找所有handler执行对象
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
AbstractChannelHandlerContext next = this.findContextOutbound();
next.invoker().invokeConnect(next, remoteAddress, localAddress, promise);
return promise;
}
private AbstractChannelHandlerContext findContextOutbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.prev;
} while(!ctx.outbound);
return ctx;
}
// 实际执行是寻找到Unsafe的Invoker
public ChannelHandlerInvoker invoker() {
return this.invoker == null ? this.channel().unsafe().invoker() : this.invoker;
}
public void invokeConnect(final ChannelHandlerContext ctx, final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
} else if (ChannelHandlerInvokerUtil.validatePromise(ctx, promise, false)) {
if (this.executor.inEventLoop()) {
ChannelHandlerInvokerUtil.invokeConnectNow(ctx, remoteAddress, localAddress, promise);
} else {
this.safeExecuteOutbound(new OneTimeTask() {
public void run() {
ChannelHandlerInvokerUtil.invokeConnectNow(ctx, remoteAddress, localAddress, promise);
}
}, promise);
}
}
}
热门推荐
甲状旁腺素
化工行业周报:“金三银四”涨价品种频现,海外产能不确定性加深或将扰动全球供需格局
上海迪士尼年卡调整!新演出限时开放,不额外收费
精神分裂症复发的5个征兆,希望你一个都没中!
椰子水热量低营养高,果肉热量惊人,这种夏天顶流水果很多人没吃对!
股票收益计算的方法有哪些?这些方法在不同市场环境下的适用性如何?
伊朗和印度历史文化交集那么多,原来他们祖上是远亲
浏览器访问Web网页的多种方式与技术详解
结婚最多的地方,根本不用催
AKG如何通过调节代谢途径对抗衰老,延缓衰老过程
JS闭包造成的内存泄漏及解决方案
膝关节单髁置换:适合人群与优点解析
右边头部神经一抽一抽的痛什么原因
如何理解国债逆回购的交易规则?这种交易规则对资金流动性有何影响?
甲醛有气味吗?一文详解甲醛危害与检测治理方法
水龙头滴水维修指南:原因分析与具体步骤
嘴唇肿胀不痛?揭开饮食习惯背后的健康真相!
红薯育苗的几种方法,红薯育苗失败的原因
晒斑怎么办?斑点会消失吗?专家教你3大晒斑保养,告别色素暗沉靠这招
雀斑是怎么引起的
贝果的本质是大馒头
烧水壶有必要316吗?怎么看烧水壶是否合格?
怎么把手机当电脑的音响用
新年龄分段:联合国世界卫生组织最新划分标准及中西方传统划分对比
助听器价格及其影响因素的详细归纳
Excel表格怎么做3组数据对比
“骑趣石景山 西山永定河观日落”骑行线路推荐
外地车想转进北京上京牌,需要注意什么呢
Excel中怎么给姓名添加汉语拼音
HPV疫苗,男性同样需要接种