dubbo2.5.3消费dubbox提供的服务报错

dubbox和dubbo 2.x是兼容的,没有改变dubbo的任何已有的功能和配置方式(除了升级了spring之类的版本),但是实际上确实不能相互兼容相互调用服务。

其实不兼容的原因是因为服务端受理请求时,在DecodeableRpcInvocation这个类出现异常,异常出线的行数106行 :

dubbo2.5.3消费dubbox提供的服务报错_第1张图片


出现异常的原因报文解析decode异常。这个要了解dubbo协议的报文格式。
in 对象执行read操作,会一个一个偏移读取报文dubbox提供的服务,当执行该行时,认为报文应该是一个整数,但是确是一个String,解析异常。 所以尝试对DecodeableRpcInvocation类进行了兼容处理:

修改的类如下所示:

/*
 * Copyright 1999-2011 Alibaba Group.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.alibaba.dubbo.rpc.protocol.dubbo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.serialize.Cleanable;
import com.alibaba.dubbo.common.serialize.ObjectInput;
import com.alibaba.dubbo.common.serialize.OptimizedSerialization;
import com.alibaba.dubbo.common.serialize.support.kryo.KryoSerialization;
import com.alibaba.dubbo.common.utils.Assert;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.remoting.Channel;
import com.alibaba.dubbo.remoting.Codec;
import com.alibaba.dubbo.remoting.Decodeable;
import com.alibaba.dubbo.remoting.exchange.Request;
import com.alibaba.dubbo.remoting.transport.CodecSupport;
import com.alibaba.dubbo.rpc.RpcInvocation;

import static com.alibaba.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument;

/**
 * @author kimi
 */
public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Decodeable {

    private static final Logger log = LoggerFactory.getLogger(DecodeableRpcInvocation.class);

    private Channel     channel;

    private byte        serializationType;

    private InputStream inputStream;

    private Request     request;

    private volatile boolean hasDecoded;

    public DecodeableRpcInvocation(Channel channel, Request request, InputStream is, byte id) {
        Assert.notNull(channel, "channel == null");
        Assert.notNull(request, "request == null");
        Assert.notNull(is, "inputStream == null");
        this.channel = channel;
        this.request = request;
        this.inputStream = is;
        this.serializationType = id;
    }

    public void decode() throws Exception {
        if (!hasDecoded && channel != null && inputStream != null) {
            try {
                decode(channel, inputStream);
            } catch (Throwable e) {
                if (log.isWarnEnabled()) {
                    log.warn("Decode rpc invocation failed: " + e.getMessage(), e);
                }
                request.setBroken(true);
                request.setData(e);
            } finally {
                hasDecoded = true;
            }
        }
    }

    public void encode(Channel channel, OutputStream output, Object message) throws IOException {
        throw new UnsupportedOperationException();
    }

    public Object decode(Channel channel, InputStream input) throws IOException {
        ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)
                .deserialize(channel.getUrl(), input);

        try {
            setAttachment(Constants.DUBBO_VERSION_KEY, in.readUTF());
            setAttachment(Constants.PATH_KEY, in.readUTF());
            setAttachment(Constants.VERSION_KEY, in.readUTF());

            setMethodName(in.readUTF());
            try {
                Object[] args;
                Class[] pts;

                // NOTICE modified by lishen
                // 兼容dubbo2.X begin.
                String dubboVerson=getAttachment(Constants.DUBBO_VERSION_KEY);

                if ("2.5.4".equals(dubboVerson) || "2.5.3".equals(dubboVerson)) {
                    String desc=in.readUTF();
                    if (desc.length() == 0) {
                        pts=DubboCodec.EMPTY_CLASS_ARRAY;
                        args=DubboCodec.EMPTY_OBJECT_ARRAY;
                    } else {
                        pts=ReflectUtils.desc2classArray(desc);
                        args=new Object[pts.length];
                        for (int i=0; i < args.length; i++) {
                            try {
                                args[i]=in.readObject(pts[i]);
                            } catch (Exception e) {
                                if (log.isWarnEnabled()) {
                                    log.warn("Decode argument failed: " + e.getMessage(), e);
                                }
                            }
                        }
                    }
                } // 兼容dubbo2.X  end.
                else {
                    int argNum=in.readInt();
                    if (argNum >= 0) {
                        if (argNum == 0) {
                            pts=DubboCodec.EMPTY_CLASS_ARRAY;
                            args=DubboCodec.EMPTY_OBJECT_ARRAY;
                        } else {
                            args=new Object[argNum];
                            pts=new Class[argNum];
                            for (int i=0; i < args.length; i++) {
                                try {
                                    args[i]=in.readObject();
                                    pts[i]=args[i].getClass();
                                } catch (Exception e) {
                                    if (log.isWarnEnabled()) {
                                        log.warn("Decode argument failed: " + e.getMessage(), e);
                                    }
                                }
                            }
                        }
                    } else {
                        String desc=in.readUTF();
                        if (desc.length() == 0) {
                            pts=DubboCodec.EMPTY_CLASS_ARRAY;
                            args=DubboCodec.EMPTY_OBJECT_ARRAY;
                        } else {
                            pts=ReflectUtils.desc2classArray(desc);
                            args=new Object[pts.length];
                            for (int i=0; i < args.length; i++) {
                                try {
                                    args[i]=in.readObject(pts[i]);
                                } catch (Exception e) {
                                    if (log.isWarnEnabled()) {
                                        log.warn("Decode argument failed: " + e.getMessage(), e);
                                    }
                                }
                            }
                        }
                    }
                }
                setParameterTypes(pts);

                Map map=(Map) in.readObject(Map.class);
                if (map != null && map.size() > 0) {
                    Map attachment=getAttachments();
                    if (attachment == null) {
                        attachment=new HashMap();
                    }
                    attachment.putAll(map);
                    setAttachments(attachment);
                }
                //decode argument ,may be callback
                for (int i=0; i < args.length; i++) {
                    args[i]=decodeInvocationArgument(channel, this, pts, i, args[i]);
                }

                setArguments(args);

            } catch (ClassNotFoundException e) {
                throw new IOException(StringUtils.toString("Read invocation data failed.", e));
            }
        } finally {
            // modified by lishen
            if (in instanceof Cleanable) {
                ((Cleanable) in).cleanup();
            }
        }
        return this;
    }

}

修改完这块代码打成jar包重新定义dubbo版本为3.8.4,这样的方式可以解决的问题是2,5.3可以消费3.8.4的服务,但是3.8.4不能消费2.5.3的服务,所以作为服务的提供方,应该升到3.8.4,如果仅仅是消费服务而不提供服务,可以用低版本的dubbo

你可能感兴趣的:(dubbo2.5.3消费dubbox提供的服务报错)