dubbox 与 dubbo 兼容的改造
改造位置
不兼容是由 dubbox 与 dubbo 序列化方式不一致导致的,所以改造的也是重新适配序列化
这包括两个部分,encoding / decoding
改造方式
最先尝试最简单的思路:
- 高低版本之间的 dubbo2 是兼容的
- 低版本 Dubbo2 与dubbox 之间也是兼容的
那就把低版本的 dubbo2 的逻辑拿出来,加入到 dubbox 里,做一个版本识别
代码
序列化编码位置
com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec#encodeRequestData
@Override
protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException {
RpcInvocation inv = (RpcInvocation) data;
out.writeUTF(inv.getAttachment(Constants.DUBBO_VERSION_KEY, DUBBO_VERSION));
out.writeUTF(inv.getAttachment(Constants.PATH_KEY));
out.writeUTF(inv.getAttachment(Constants.VERSION_KEY));
out.writeUTF(inv.getMethodName());
if (inv.isDubbox()){
if (getSerialization(channel) instanceof OptimizedSerialization && !containComplexArguments(inv)) {
out.writeInt(inv.getParameterTypes().length);
} else {
out.writeInt(-1);
out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes()));
}
}else {//低版本
out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes()));
}
Object[] args = inv.getArguments();
if (args != null)
for (int i = 0; i < args.length; i++){
out.writeObject(encodeInvocationArgument(channel, inv, i));
}
out.writeObject(inv.getAttachments());
}
序列化解码位置
com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation#decode
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;
if (isDubbox()){
// NOTICE modified by lishen
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);
}
}
}
}
}
} 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<String, String> map = (Map<String, String>) in.readObject(Map.class);
if (map != null && map.size() > 0) {
Map<String, String> attachment = getAttachments();
if (attachment == null) {
attachment = new HashMap<String, String>();
}
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;
}
版本判断
com.alibaba.dubbo.rpc.RpcInvocation#isDubbox
public boolean isDubbox(){
return dubbox || DubboxJudgeUtils.judeByVersion(getAttachments().get(Constants.DUBBO_VERSION_KEY));
}
浙公网安备 33010602011771号