背景
有A ,B,C,D 四個服務 序列化關係如下,其中C服務是一個rpc服務,供很多的服務調用。
由於我是B服務和C服務的維護者,此時A服務和D服務的通信經由我,由於pb字段協議變更。我這個橋樑不得不做變動。
報錯
於是這次增加了一個map字段,意味着你們有變動,放到map,我直接透傳就好了。想法很豐滿,現實很骨幹。
Caused by: com.esotericsoftware.kryo.KryoException: Error during Java serialization.
at com.esotericsoftware.kryo.serializers.JavaSerializer.write(JavaSerializer.java:33)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:599)
at de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer.write(UnmodifiableCollectionsSerializer.java:81)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:599)
at com.esotericsoftware.kryo.serializers.MapSerializer.write(MapSerializer.java:95)
at com.esotericsoftware.kryo.serializers.MapSerializer.write(MapSerializer.java:21)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:599)
at org.apache.dubbo.rpc.protocol.dubbo.DubboCodec.encodeRequestData(DubboCodec.java:188)
at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encodeRequest(ExchangeCodec.java:238)
at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encode(ExchangeCodec.java:69)
at org.apache.dubbo.rpc.protocol.dubbo.DubboCountCodec.encode(DubboCountCodec.java:38)
at org.apache.dubbo.remoting.transport.netty4.NettyCodecAdapter$InternalEncoder.encode(NettyCodecAdapter.java:70)
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107)
... 23 more
Caused by: java.io.NotSerializableException: com.google.protobuf.MapField$MutatabilityAwareMap
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.esotericsoftware.kryo.serializers.JavaSerializer.write(JavaSerializer.java:30)
... 36 more
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter.get(FutureAdapter.java:84)
at sun.reflect.GeneratedMethodAccessor118.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:140)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:294)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:248)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:235)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:398)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:205)
at org.jboss.resteasy.plugins.server.netty.RequestDispatcher.service(RequestDispatcher.java:83)
at org.jboss.resteasy.plugins.server.netty.RequestHandler.channelRead0(RequestHandler.java:53)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373)
at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:39)
at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:364)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:418)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:454)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: io.netty.handler.codec.EncoderException: com.esotericsoftware.kryo.KryoException: Error during Java serialization.
io.netty.handler.codec.EncoderException: com.esotericsoftware.kryo.KryoException: Error during Java serialization.
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:125)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:749)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:741)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:827)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:734)
at io.netty.handler.timeout.IdleStateHandler.write(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:749)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:741)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:827)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:734)
at io.netty.channel.ChannelDuplexHandler.write(ChannelDuplexHandler.java:106)
at org.apache.dubbo.remoting.transport.netty4.NettyClientHandler.write(NettyClientHandler.java:87)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:749)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:741)
at io.netty.channel.AbstractChannelHandlerContext.access$1900(AbstractChannelHandlerContext.java:39)
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1100)
at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1147)
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1089)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:418)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:454)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:748)
二話不說,一上來因爲我在B服務中代碼中是直接把map透傳的,此時kryo序列化報錯,因爲這個內部的mapfield不支持序列化。
好咯,開始做轉化,把pb3的內部的這個不支持序列化的map手動轉爲hashmap
重啓服務,上面的錯誤不報了。出現了新的報錯。
之前是寫序列化,這次是C服務裏面的報錯,但是在B服務中報了。
通過源碼追蹤,看到,報錯出現在下面
錯誤發生在給D服務序列化的時候報錯了。因爲我給D的是hashmap而不是原生的pb內部的map,所以無法初始化這個內部類。
解決
方法1、曲線救國方式,可以通過自定義個repeated message,如下
後來看源碼 ,發現pb內部也是使用這種方式,將map轉爲list去用的。
還記得這個內部的map,mutatabilityAwareMap嗎?之前就是這個報錯的。
方法2,改變C 微服務的rpc的序列化方式爲pb,那麼此時就可以做到真正的透傳!
風險:因爲還有很多其他服務在用c服務的接口,所以貿然改動,必定血流才成河。所以,暫時放棄了。