apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.55k stars 26.44k forks source link

protobuf 泛化调用类型校验异常问题 #10069

Open boooobao opened 2 years ago

boooobao commented 2 years ago

最近在调研泛化调用的功能

构造的请求如下 reference.setGeneric(GENERIC_SERIALIZATION_PROTOBUF); GenericService genericService = reference.get(); Object response = genericService.$invoke("getMixResult", new String[]{"com.xxx.xx.xxxx.xx.entity.MixRequest"}, new Object[]{mixRequest});

然后会报出如下错误 cause: org.apache.dubbo.remoting.RemotingException: io.netty.handler.codec.EncoderException: java.lang.IllegalArgumentException: This serialization only supports google protobuf objects, current object class is: [Ljava.lang.String; io.netty.handler.codec.EncoderException: java.lang.IllegalArgumentException: This serialization only supports google protobuf objects, current object class is: [Ljava.lang.String; at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:125) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:709) at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:792) at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:702) at io.netty.handler.timeout.IdleStateHandler.write(IdleStateHandler.java:304) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:709) at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:792) at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:702) at io.netty.channel.ChannelDuplexHandler.write(ChannelDuplexHandler.java:115) at org.apache.dubbo.remoting.transport.netty4.NettyClientHandler.write(NettyClientHandler.java:88) at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717) at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764) at io.netty.channel.AbstractChannelHandlerContext$WriteTask.run(AbstractChannelHandlerContext.java:1071) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: java.lang.IllegalArgumentException: This serialization only supports google protobuf objects, current object class is: [Ljava.lang.String; at org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufObjectOutput.writeObject(GenericProtobufObjectOutput.java:109) at org.apache.dubbo.rpc.protocol.dubbo.DubboCodec.encodeRequestData(DubboCodec.java:207) at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encodeRequest(ExchangeCodec.java:257) at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encode(ExchangeCodec.java:71) at org.apache.dubbo.rpc.protocol.dubbo.DubboCountCodec.encode(DubboCountCodec.java:47) at org.apache.dubbo.remoting.transport.netty4.NettyCodecAdapter$InternalEncoder.encode(NettyCodecAdapter.java:69) at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107) ... 21 more at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:114) at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:340) at org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter.invoke(RouterSnapshotFilter.java:46) at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:99) at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) at org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:51) at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) at org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter.invoke(ConsumerContextFilter.java:109) at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321) at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:193) at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$ClusterFilterInvoker.invoke(AbstractCluster.java:92) at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:97) at org.apache.dubbo.registry.client.migration.MigrationInvoker.invoke(MigrationInvoker.java:280) at org.apache.dubbo.rpc.proxy.InvocationUtil.invoke(InvocationUtil.java:57) at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:73) at com.heytap.ad.show.mixer.service.IAdShowMixerServiceDubboProxy0.$invoke(IAdShowMixerServiceDubboProxy0.java) at com.oppo.itest.example.DubboGenericPbTest.main(DubboGenericPbTest.java:100) 所描述的是在序列化时String[],判断并不是一个pb对象因此序列化失败了 调试之后看到相关代码为 org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufObjectOutput 我在试用dubbo3时将dubbo2的相关逻辑挪移过来的

public void writeObject(Object obj) throws IOException { /**

在这个地方只会判断是否为String类型然后将其转换成StringValue类型,但是如同代码块1所示,所传入的参数为String[]类型,因此并不会进行转换,同时在ProtobufUtils.isSupported(obj.getClass())会判断失败从而抛出异常,我尝试性的进行了一些处理但是结果不尽人意,请问该如何修改转化逻辑才能将new String[]{"com.xxx.xx.xxxx.xx.entity.MixRequest"}通过转化呢?

EarthChen commented 2 years ago

都用 pb 了,不妨尝试一下 triple 协议?

habertzk commented 2 years ago

都用 pb 了,不妨尝试一下 triple 协议?

有的场景需要使用泛化调用,比如dubbo admin中的服务测试使用的就是泛化调用,但是也遇到了楼主的问题,dubbo3并未实现protobuf序列化,所以只能引入dubbo-serialization-protobuf 2.x的版本,但是参数会校验判断并不是一个pb对象,从而导致报错