ByrsH commented on issue #10688: URL: https://github.com/apache/dubbo/issues/10688#issuecomment-2152201464
2.7.x 也有这样的现象,问题的关键是前后两次请求共用变量 a (注意:假如前后两次请求是两个不同的对象,但是对象的成员变量公用了,也会有同样的问题)。 该问题在 3.2.0 版本得到了解决(虽然此次调整是为了提升效率,并没有说明为了解决这个问题)。commit 记录:[https://github.com/apache/dubbo/commit/5016f550be52f14a232399409a3c97fa6d6db321](https://github.com/apache/dubbo/commit/5016f550be52f14a232399409a3c97fa6d6db321) 关键代码在 dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyChannel.java 中: ``` try { Object outputMessage = message; if (!encodeInIOThread) { ByteBuf buf = channel.alloc().buffer(); ChannelBuffer buffer = new NettyBackedChannelBuffer(buf); codec.encode(this, buffer, message); outputMessage = buf; } ChannelFuture future = writeQueue.enqueue(outputMessage).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (!(message instanceof Request)) { return; } ChannelHandler handler = getChannelHandler(); if (future.isSuccess()) { handler.sent(NettyChannel.this, message); } else { Throwable t = future.cause(); if (t == null) { return; } Response response = buildErrorResponse((Request) message, t); handler.received(NettyChannel.this, response); } } }); ``` Dubbo 在切换到 Netty channel 前对 message 做了 encode,然后放到队列里就返回了。当第二个请求 a.setName("lisi"); 时,就不会影响已经 encode 的 message了。 之前的版本是直接通过 netty channel writeAndFlush message,在第二个请求 a.setName("lisi"); 时,第一个请求还未完成 encode ,就会造成参数覆盖的情况出现。 2.7.22 版本 NettyChannel: ``` try { ChannelFuture future = channel.writeAndFlush(message); if (sent) { // wait timeout ms timeout = getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT); success = future.await(timeout); } Throwable cause = future.cause(); if (cause != null) { throw cause; } } catch (Throwable e) { removeChannelIfDisconnected(channel); throw new RemotingException(this, "Failed to send message " + PayloadDropper.getRequestWithoutData(message) + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e); } ``` 对于使用者来说,应该尽量避免多次异步请求参数共享的情形出现,第二次调用时,可以对参数做一次深拷贝得到新的对象,然后再进行异步请求。 -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@dubbo.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@dubbo.apache.org For additional commands, e-mail: notifications-h...@dubbo.apache.org