赞
踩
A服务提供了个RPC接口给B服务使用,入参里有个参数是List类型,B服务在传参时使用Guava里的 ImmutableList,结果发生报错。
其中,B服务即consumer端的异常为:「com.alibaba.dubbo.remoting.RemotingException: Fail to decode request due to: RpcInvocation [methodName=…」 。consumer端异常截图:
A服务即provider端的异常为:「com.alibaba.com.caucho.hessian.io.HessianFieldException: com.pdd.service.smart.contract.request.agreement.QueryCarrierAgreementEffectiveWarehouseInfoRequest.agreementTypeList: java.util.List cannot be assigned from null」。provider端异常截图:
然而,当将 ImmutableList 改成 ArrayList 时报错消失,接口恢复正常。
已知我司使用的RPC框架是dubbo,其中的序列化协议是dubbo默认的hessian2,对应版本是:hessian-lite:3.2.1-fixed-2。
< 上图出自:https://cn.dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/protocol/dubbo/ >
从第一部分【问题描述】中的异常堆栈信息可知,问题主要出在hessian2序列化的过程中,更准确一点是consumer反序列化时解析出错,导致异常。因此问题定位为dubbo的Serialize 数据序列化层,仅从hessian2序列化和反序列化来复现和分析问题。
< dubbo代码架构 https://cn.dubbo.apache.org/zh/docs3-v2/java-sdk/concepts-and-architecture/code-architecture/ >
public class HessianLiteUtils { /** * 序列化 */ public static byte[] serialize(Object object) { Hessian2Output h2o = null; ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { h2o = new Hessian2Output(outputStream); h2o.writeObject(object); h2o.flush(); return outputStream.toByteArray(); } catch (Exception e) { System.out.println("HessianUtils.serialize exception " + e.getMessage()); throw new RuntimeException("HessianUtils.serialize 异常", e); } finally { if (h2o != null) { try { h2o.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 反序列化. */ public static Object deserialize(byte[] bytes) { Hessian2Input h2i = null; try { ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); h2i = new Hessian2Input(inputStream); return h2i.readObject(); } catch (Exception e) { System.out.println("HessianUtils.deserialize exception " + e.getMessage()); throw new RuntimeException("HessianUtils.deserialize 异常", e); } finally { if (h2i != null) { try { h2i.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static String hex(byte[] bytes) { StringBuilder result = new StringBuilder(); for (byte b : bytes) { result.append(String.format("%02x", b)); // upper case // result.append(String.format("%02X", aByte)); } return result.toString(); } public static void main(String[] args) { Person person = new Person(); person.setName("胖嘟嘟"); person.setMale(true); person.setAge(10); person.setList(Lists.newArrayList(1, 2)); // Person 可正常序列化和反序列化 byte[] bytes = serialize(person); System.out.println("serialized hex bytes: " + hex(bytes)); Object object = deserialize(bytes); System.out.println("deserialized object: " + object.toString()); // Request 序列化成功,反序列化失败 Request request = new Request(); request.setList(ImmutableList.of(1, 2)); byte[] bytesRequest = serialize(request); System.out.println("serialized hex bytes: " + hex(bytesRequest)); Object objectReq = deserialize(bytesRequest); System.out.println("deserialized object: " + objectReq.toString()); } } // 其中Person和Request的定义为 public class Person implements Serializable { private static final long serialVersionUID = 7242674494415301661L; private String name; private boolean isMale; private int age; private List<Integer> list; // 此处省略getter、setter和toString } public class Request implements Serializable { private static final long serialVersionUID = 408723925489378046L; private List<Integer> list; public List<Integer> getList() { return list; } public void setList(List<Integer> list) { this.list = list; } }
在上述代码中Person可正常序列化,输出结果为:
serialized hex bytes: 4306506572736f6e94046c697374036167650669734d616c65046e616d65607a91929a5403e88396e5989fe5989f
deserialized object: Person{
name='胖嘟嘟', isMale=true, age=10, list=[1, 2]}
Request中List参数传ImmutableList会导致反序列化异常,表现和rpc接口异常一样,问题复现。
serialized hex bytes: 43075265717565737491046c69737460433036636f6d2e676f6f676c652e636f6d6d6f6e2e636f6c6c6563742e496d6d757461626c654c6973742453657269616c697a6564466f726d9108656c656d656e74736172075b6f626a6563749192
HessianUtils.deserialize exception Request.list: com.google.common.collect.ImmutableList cannot be assigned from null
Exception in thread "main" java.lang.RuntimeException: HessianUtils.deserialize 异常
at HessianLiteUtils.deserialize(HessianLiteUtils.java:59)
at HessianLiteUtils.main(HessianLiteUtils.java:99)
Caused by: com.alibaba.com.caucho.hessian.io.HessianFieldException: Request.list: com.google.common.collect.ImmutableList cannot be assigned from null
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.logDeserializeError(JavaDeserializer.java:171)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:414)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:275)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:199)
at com.alibaba.com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:529)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2803)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2743)
at com.alibaba.com.caucho.hessian.io.Hessian2Input
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。