sofastack / sofa-jraft

A production-grade java implementation of RAFT consensus algorithm.
https://www.sofastack.tech/projects/sofa-jraft/
Apache License 2.0
3.57k stars 1.14k forks source link

request cannot be cast to com.google.protobuf.Message #600

Closed Mervey0324 closed 3 years ago

Mervey0324 commented 3 years ago

我尝试使用sofa-jraft中自带的rpc框架(request、response和RpcProcessor),但是得到一个java.lang.ClassCastException错误MetaStoreTestRequest cannot be cast to com.google.protobuf.Message. 相关代码如下:

public class MetaStoreTestRequest extends MetaStoreRequest{

    private static final long serialVersionUID = -472951628397420368L;

    private String data;

    public MetaStoreTestRequest(String data) {
        this.data = data;
    }

    @Override
    public byte magic() {
        return AUTH;
    }
}
public class MetaStoreTestResponse extends MetaStoreResponse<String>{
    private static final long serialVersionUID = 8507492618405370694L;
}
public class MetaStoreProcessorTest<T extends MetaStoreRequest> implements RpcProcessor<T> {

    private final Class<T>    reqClazz;
    private final String methodName;

    public MetaStoreProcessorTest(String methodName, Class<T> reqClazz) {
        this.reqClazz = Requires.requireNonNull(reqClazz, "reqClazz");
        this.methodName = Requires.requireNonNull(methodName, "methodName");
    }

    @Override
    public void handleRequest(final RpcContext rpcCtx, final T request) {
        Requires.requireNonNull(request, "request");
        final RequestProcessClosure<MetaStoreRequest, MetaStoreResponse<?>> closure = new RequestProcessClosure<>(request, rpcCtx);

        switch (request.magic()) {
            case MetaStoreRequest.AUTH:
                this.handleTest((MetaStoreTestRequest) request, closure);
                break;
            default:
                throw new RheaRuntimeException("Unsupported request type: " + request.getClass().getName());
        }
    }

    @Override
    public String interest() {
        return this.reqClazz.getName();
    }

    @Override
    public Executor executor() {
        return StoreEngineHelper.createCliRpcExecutor(10);
    }

    private void handleTest(MetaStoreTestRequest request, RequestProcessClosure closure){
        final MetaStoreTestResponse response = new MetaStoreTestResponse();
        response.setValue(request.getData());
        closure.sendResponse(response);
    }
}
public class BoltServerTest {
    public static void main(String[] args) {
        Endpoint endpoint = new Endpoint("127.0.0.1", 8411);
        BoltRaftRpcFactory rpcFactory = new BoltRaftRpcFactory();
        rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());
        RpcServer server = rpcFactory.createRpcServer(endpoint);
        server.registerProcessor(new MetaStoreProcessorTest<MetaStoreTestRequest>("test", MetaStoreTestRequest.class));
        server.init(null);
        try {
            new CountDownLatch(1).await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class BoltClientTest {
    public static void main(String[] args) {
        BoltRaftRpcFactory rpcFactory = new BoltRaftRpcFactory();
        rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());
        RpcClient client = rpcFactory.createRpcClient();
        client.init(null);
        try {
            Object res = client.invokeSync(new Endpoint("127.0.0.1", 8411), new MetaStoreTestRequest("test"), 10000);
            System.out.println(res);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (RemotingException e) {
            e.printStackTrace();
        }
    }
}
fengjiachun commented 3 years ago

把错误堆栈发出来

Mervey0324 commented 3 years ago
com.alipay.sofa.jraft.error.RemotingException: com.alipay.remoting.exception.SerializationException: Exception caught when serialize header of rpc request command!
    at com.alipay.sofa.jraft.rpc.impl.BoltRpcClient.invokeSync(BoltRpcClient.java:101)
    at com.alipay.sofa.jraft.rpc.RpcClient.invokeSync(RpcClient.java:71)
    at com.meituan.daojia.ci.metastore.example.rpc.BoltClientTest.main(BoltClientTest.java:16)
Caused by: com.alipay.remoting.exception.SerializationException: Exception caught when serialize header of rpc request command!
    at com.alipay.remoting.rpc.protocol.RpcRequestCommand.serializeHeader(RpcRequestCommand.java:98)
    at com.alipay.remoting.rpc.RpcCommand.serialize(RpcCommand.java:104)
    at com.alipay.remoting.rpc.RpcRemoting.toRemotingCommand(RpcRemoting.java:354)
    at com.alipay.remoting.rpc.RpcRemoting.invokeSync(RpcRemoting.java:179)
    at com.alipay.remoting.rpc.RpcClientRemoting.invokeSync(RpcClientRemoting.java:64)
    at com.alipay.remoting.rpc.RpcRemoting.invokeSync(RpcRemoting.java:143)
    at com.alipay.remoting.rpc.RpcClient.invokeSync(RpcClient.java:225)
    at com.alipay.sofa.jraft.rpc.impl.BoltRpcClient.invokeSync(BoltRpcClient.java:97)
    ... 2 more
Caused by: java.lang.ClassCastException: com.meituan.daojia.ci.metastore.example.rpc.cmd.MetaStoreTestRequest cannot be cast to com.google.protobuf.Message
    at com.alipay.sofa.jraft.rpc.ProtobufSerializer.serializeHeader(ProtobufSerializer.java:44)
    at com.alipay.remoting.rpc.protocol.RpcRequestCommand.serializeHeader(RpcRequestCommand.java:94)
    ... 9 more
fengjiachun commented 3 years ago

rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());

这行代码去掉再看下(加了这行代码代表你要使用 com.alipay.sofa.jraft.rpc.ProtobufSerializer 作为 Serializer,而你不应该使用它)

Mervey0324 commented 3 years ago

我删除rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());后对于上述例子可以运行了。🙏🙏🙏

但是上面的代码,我换成GrpcRaftRpcFactory,其他逻辑不变,就会出现另外一个错误。

Exception in thread "main" java.lang.NullPointerException: null default instance: com.meituan.daojia.ci.metastore.example.rpc.cmd.MetaStoreTestRequest
    at com.alipay.sofa.jraft.util.Requires.requireNonNull(Requires.java:55)
    at com.meituan.daojia.ci.metastore.rpc.grpc.impl.GrpcServer.registerProcessor(GrpcServer.java:119)
    at com.meituan.daojia.ci.metastore.example.rpc.GrpcServerTest.main(GrpcServerTest.java:15)

我看着像是GrpcRaftRpcFactory.parserClasses中不包含自定的request,所以试着加上rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());,就会报最初的MetaStoreTestRequest cannot be cast to com.google.protobuf.Message错误。

是需要定义MetaStoreTestRequest对应的proto文件吗?

fengjiachun commented 3 years ago

我删除rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());后对于上述例子可以运行了。🙏🙏🙏

但是上面的代码,我换成GrpcRaftRpcFactory,其他逻辑不变,就会出现另外一个错误。

Exception in thread "main" java.lang.NullPointerException: null default instance: com.meituan.daojia.ci.metastore.example.rpc.cmd.MetaStoreTestRequest
  at com.alipay.sofa.jraft.util.Requires.requireNonNull(Requires.java:55)
  at com.meituan.daojia.ci.metastore.rpc.grpc.impl.GrpcServer.registerProcessor(GrpcServer.java:119)
  at com.meituan.daojia.ci.metastore.example.rpc.GrpcServerTest.main(GrpcServerTest.java:15)

我看着像是GrpcRaftRpcFactory.parserClasses中不包含自定的request,所以试着加上rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());,就会报最初的MetaStoreTestRequest cannot be cast to com.google.protobuf.Message错误。

是需要定义MetaStoreTestRequest对应的proto文件吗?

GrpcRaftRpcFactory 只支持 protobuf 序列化/反序列化,你需要定义 proto 并且注册到 GrpcRaftRpcFactory 中,这一点和 BoltRaftRpcFactory 不一样

Mervey0324 commented 3 years ago

我删除rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());后对于上述例子可以运行了。🙏🙏🙏 但是上面的代码,我换成GrpcRaftRpcFactory,其他逻辑不变,就会出现另外一个错误。

Exception in thread "main" java.lang.NullPointerException: null default instance: com.meituan.daojia.ci.metastore.example.rpc.cmd.MetaStoreTestRequest
    at com.alipay.sofa.jraft.util.Requires.requireNonNull(Requires.java:55)
    at com.meituan.daojia.ci.metastore.rpc.grpc.impl.GrpcServer.registerProcessor(GrpcServer.java:119)
    at com.meituan.daojia.ci.metastore.example.rpc.GrpcServerTest.main(GrpcServerTest.java:15)

我看着像是GrpcRaftRpcFactory.parserClasses中不包含自定的request,所以试着加上rpcFactory.registerProtobufSerializer(MetaStoreTestRequest.class.getName(), new MetaStoreTestRequest());,就会报最初的MetaStoreTestRequest cannot be cast to com.google.protobuf.Message错误。 是需要定义MetaStoreTestRequest对应的proto文件吗?

GrpcRaftRpcFactory 只支持 protobuf 序列化/反序列化,你需要定义 proto 并且注册到 GrpcRaftRpcFactory 中,这一点和 BoltRaftRpcFactory 不一样

好的 我试一下 多谢!

Mervey0324 commented 3 years ago

试了一下bolt和grpc框架,当前框架下,感觉bolt方便易用一些。