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]

Reply via email to