최근에 netty4 프로젝트에서 BlockingOperationException
이 발견되었습니다.Netty 4에서 BlockingOperationException의 원인은 무엇입니까?
startten netty의 ServerBootstrap의 sync() 메소드를 사용하면 sync()가 await() 메소드를 호출하고 await()에 'checkDeadLock'이라는 메소드가 있기 때문에 deadlock이 발생할 수 있다고합니다.
하지만 그렇게 생각하지 않습니다. ServerBootstrap은 boosGroup이라는 EventLoopGroup을 사용하고 Channel은 작업 IO를 위해 workerGroup을 사용합니다. 서로 영향을 미치지 않을 것이라고 생각합니다. 서로 다른 EventExecutor를가집니다.
내 연습에서는 데드락 예외가 Netty 시작 프로세스에 나타나지 않습니다. 대부분의 경우 writeAndFlush를 기다리는 채널 이후에 발생합니다.
분석 소스 코드, checkDeadLock
, BlockingOperationException
현재 스레드와 실행 프로그램 실행 스레드가 동일한 경우 예외가 발생합니다. 내가의 Netty 관계자는 동기화()를 사용하지 않도록 조언 또는() 메소드를 기다리고 알고
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"));
}
}
하지만 나는 윌 과정과 현재의 교착 상태의 원인을 상황을 알고 싶어 :
내 프로젝트 코드는 타격 쓰래드와 Executor 실행 스레드는 동일합니다.
프로젝트 코드가 변경되었습니다.
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' 블록 안에 있어야합니다. – EJP
'pushexception'을 던지는'pushMessage'는 비동기 세계에서 작동하지 않습니다. 작동을 위해 Future를 반환하거나, 상태를 위해 콜백을 사용해야합니다. – Ferrybig