zhangyz-hd opened a new issue #8362: URL: https://github.com/apache/dubbo/issues/8362
- [x] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate. - [x] I have checked the [FAQ](https://github.com/apache/dubbo/blob/master/FAQ.md) of this repository and believe that this is not a duplicate. ### Environment * Dubbo version: 3.0.2-SNAPSHOT * Operating System version: ANY * Java version: 8 ### Steps to reproduce this issue 服务调用timeout时,消费者端出现NPE日志 ``` java.lang.NullPointerException at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:122) at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57) at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:48) at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41) at java.lang.Thread.run(Thread.java:748) ``` 代码位置 ``` public void decode() throws Exception { if (!hasDecoded && channel != null && inputStream != null) { try { if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, true)) { Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY); // <------ invocation IS NULL!! if (serializationType_obj != null) { if ((byte) serializationType_obj != serializationType) { throw new IOException("Unexpected serialization id:" + serializationType + " received from network, please check if the peer send the right id."); } } } decode(channel, inputStream); } catch (Throwable e) { ``` 初步分析原因 超时时,消费者端TimeoutCheckTask创建了timeoutResponse,并调用了DefaultFuture.received ``` private void notifyTimeout(DefaultFuture future) { // create exception response. Response timeoutResponse = new Response(future.getId()); // set timeout status. timeoutResponse.setStatus(future.isSent() ? Response.SERVER_TIMEOUT : Response.CLIENT_TIMEOUT); timeoutResponse.setErrorMessage(future.getTimeoutMessage(true)); // handle response. DefaultFuture.received(future.getChannel(), timeoutResponse, true); } ``` DefaultFuture.received内会先从FUTURES中删除该id ``` public static void received(Channel channel, Response response, boolean timeout) { try { DefaultFuture future = FUTURES.remove(response.getId()); if (future != null) { Timeout t = future.timeoutCheckTask; if (!timeout) { ``` 当服务提供者返回调用结果时,DefaultFuture#FUTURES缓存的id已经被删除,从而导致DubboCodec#decodeBody中创建DecodeableRpcResult时,传入的invocation是null ``` // org.apache.dubbo.rpc.protocol.dubbo.DubboCodec#decodeBody if (channel.getUrl().getParameter(DECODE_IN_IO_THREAD_KEY, DEFAULT_DECODE_IN_IO_THREAD)) { result = new DecodeableRpcResult(channel, res, is, (Invocation) getRequestData(id), proto); result.decode(); } else { result = new DecodeableRpcResult(channel, res, new UnsafeByteArrayInputStream(readMessageData(is)), (Invocation) getRequestData(id), proto); } ``` ``` // org.apache.dubbo.remoting.exchange.codec.ExchangeCodec#getRequestData protected Object getRequestData(long id) { DefaultFuture future = DefaultFuture.getFuture(id); if (future == null) { return null; //<----------(^_^)v } Request req = future.getRequest(); if (req == null) { return null; } return req.getData(); } ``` -- 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: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
