【发布时间】:2018-02-11 16:49:24
【问题描述】:
最近,我在我的 netty4 项目中找到了一些BlockingOperationException。
有人说使用start netty的ServerBootstrap的sync()方法时会导致死锁,因为sync()会调用await()方法,而await()中有一个叫做'checkDeadLock'的方法。
但我不这么认为。 ServerBootstrap 使用名为 boosGroup 的 EventLoopGroup,Channel 使用 workerGroup 操作 IO,我认为它们不会相互影响,它们有不同的 EventExecutor。
而且在我的实践中,Netty启动过程中并没有出现Deadlock异常,大部分发生在await writeAndFlush的Channel之后。
分析源码,checkDeadLock,BlockingOperationException是当当前线程和executor线程相同时抛出的异常。
我的项目代码被炸了:
private void channelWrite(T message) {
boolean success = true;
boolean sent = true;
int timeout = 60;
try {
ChannelFuture cf = cxt.write(message);
cxt.flush();
if (sent) {
success = cf.await(timeout);
}
if (cf.isSuccess()) {
logger.debug("send success.");
}
Throwable cause = cf.cause();
if (cause != null) {
this.fireError(new PushException(cause));
}
} catch (LostConnectException e) {
this.fireError(new PushException(e));
} catch (Exception e) {
this.fireError(new PushException(e));
} catch (Throwable e) {
this.fireError(new PushException("Failed to send message“, e));
}
if (!success) {
this.fireError(new PushException("Failed to send message"));
}
}
我知道Netty官方建议不要使用sync()或者await()方法,但是我想知道什么情况会导致进程死锁,当前线程和执行线程是一样的。强>
我更改了我的项目代码。
private void pushMessage0(T message) {
try {
ChannelFuture cf = cxt.writeAndFlush(message);
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws PushException {
if (future.isSuccess()) {
logger.debug("send success.");
} else {
throw new PushException("Failed to send message.");
}
Throwable cause = future.cause();
if (cause != null) {
throw new PushException(cause);
}
}
});
} catch (LostConnectException e) {
this.fireError(new PushException(e));
} catch (Exception e) {
this.fireError(new PushException(e));
} catch (Throwable e) {
this.fireError(new PushException(e));
}
}
但是我遇到了一个新问题,我无法从 ChannelHandlerListener 获取 pushException。
【问题讨论】:
-
当然不能。你甚至还没来得及看它就扔了自己的东西。涉及
future.cause()的代码应该在前面的else块内,而不是在里面。 -
您的
pushMessage抛出pushexception在异步世界中不起作用,它应该为操作返回一个Future,或者对状态使用回调