当前位置: 首页 > 知识库问答 >
问题:

什么原因导致阻塞操作 Netty 4 中的异常?

晏弘雅
2023-03-14

最近,我在我的netty4项目中找到了一些BlockingOperationException

有人说在使用start netty的ServerBootstrap的sync()方法时会导致死锁,因为sync()会调用await()方法,而await()中有一个叫‘check deadlock’的方法。

但我不这么认为。ServerBootstrap使用名为boosGroup的EventLoopGroup,Channel使用workerGroup来操作IO,我认为它们不会相互影响,它们有不同的EventExector。

在我的实践中,死锁异常不会出现在Netty启动过程中,大多数发生在等待writeAndFlush的Channel之后。

分析源代码、checkDeadLock exception在当前线程和执行器线程相同时引发异常。

我的项目代码是吹:

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。

共有2个答案

简意
2023-03-14

不能在IO线程中调用await是可以理解的。但是,有2点。1.如果您在通道处理程序中调用以下代码,将不会报告异常,因为大多数情况下,await中的isDone检查返回true,因为您在IO线程中,而IO线程正在同步写入数据。调用await时,数据已经写入。

ChannelPromise p = ctx.writeAndFlush(msg);
p.await()
史骏祥
2023-03-14

如果您在事件加速器正在使用的同一线程中调用“同步”或“等待”则 Netty 将引发“同步”或“等待”,而“事件”演示者正在使用并绑定到该线程。这通常是频道本身使用的事件循环

 类似资料:
  • OpenResty 的诞生,一直对外宣传是同步非阻塞(100% non-blocking)的。基于事件通知的 Nginx 给我们带来了足够强悍的高并发支持,但是也对我们的编码有特殊要求。这个特殊要求就是我们的代码,也必须是非阻塞的。如果你的服务端编程生涯一开始就是从异步框架开始的,恭喜你了。但如果你的编程生涯是从同步框架过来的,而且又是刚刚开始深入了解异步框架,那你就要小心了。 Nginx 为了减

  • 这一节解释 BlockingObservable 的子类. 一个阻塞的Observable 继承普通的Observable类,增加了一些可用于阻塞Observable发射的数据的操作符。 要将普通的Observable 转换为 BlockingObservable,可以使用 Observable.toBlocking( )) 方法或者BlockingObservable.from( )) 方法。

  • 从进程调度谈起 现代操作系统(如 Windows、Linux 等)都是分时系统。分时系统允许同时允许多个任务,但实际上,由于一台计算机通常只有一个 CPU,所以不可能真正地同时运行多个任务。这些进程实际上是轮番运行,每个进程运行一个时间片。由于时间片通常很短,用户不会感觉到,所以这些进程看起来就像是同时运行。 每个进程的时间片由操作系统完成初始化,所有进程轮番地执行相应的时间。具体下一个时间片轮到

  • 问题内容: 和之间有什么区别? 是什么导致它们被抛出?如何解决? 在修改现有代码以包含新的jar文件时,我经常遇到这些throwables。我在客户端和服务器端都通过Webstart分发了一个Java应用程序。 我遇到的可能原因: build.xml代码客户端未包含的软件包 我们正在使用的新jar缺少运行时类路径 版本与先前的jar冲突 今天,当我遇到这些问题时,我会采取一种犯错的方法来使事情正常

  • minecraft 1.8.8的modcoderpack918中的有一个很大的问题。我的Java版本是1.8.0_271-B09。 我不知道我必须做什么。

  • 问题内容: 我需要检查异常是否由某些数据库问题引起。我收到异常,并检查其原因是否包含“ ORA”字符串,然后将其返回(类似于“ ORA-00001”)。这里的问题是我收到的异常嵌套在其他异常中,因此,如果我不知道它是否是oracle异常,则必须检查该异常的原因,以此类推。有没有更清洁的方法可以做到这一点?有没有办法知道给定异常的第一个原因(嵌套的异常)? 我当前的代码如下所示: 问题答案: 只需遍