Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Triple Dubbo dual protocol parameters are missing #13158

Closed
hebrd opened this issue Oct 8, 2023 · 8 comments · Fixed by #13597
Closed

Triple Dubbo dual protocol parameters are missing #13158

hebrd opened this issue Oct 8, 2023 · 8 comments · Fixed by #13597
Labels
type/bug Bugs to being fixed
Milestone

Comments

@hebrd
Copy link

hebrd commented Oct 8, 2023

  • dubbo version: 3.2.2
  • The server uses proto to define the protocol, and the dubbo plug-in generates stub code and exposes the triple protocol and dubbo protocol at the same time.
<dubbo:protocol name="tri" port="9090" serialization="protobuf"/>
<dubbo:protocol name="dubbo" port="${dubbo.protocol.port}"/>

<dubbo:provider filter="xxx" retries="0" timeout="${dubbo.provider.timeout}"
                     protocol="tri,dubbo" serialization="protobuf"/>

Plugin configuration:

<plugin>
     <groupId>org.xolstice.maven.plugins</groupId>
     <artifactId>protobuf-maven-plugin</artifactId>
     <version>0.6.1</version>
     <configuration>
         <protocArtifact>com.google.protobuf:protoc:3.22.3:exe:${os.detected.classifier}</protocArtifact>
         <protocPlugins>
             <protocPlugin>
                 <id>dubbo</id>
                 <groupId>org.apache.dubbo</groupId>
                 <artifactId>dubbo-compiler</artifactId>
                 <version>${dubbo.version}</version>
                 <mainClass>org.apache.dubbo.gen.tri.Dubbo3TripleGenerator</mainClass>
             </protocPlugin>
         </protocPlugins>
         <outputDirectory>${basedir}/src/main/java/</outputDirectory>
     </configuration>
     <executions>
         <execution>
             <goals>
                 <goal>compile</goal>
             </goals>
         </execution>
     </executions>
 </plugin>
  • The interface generated by the client and server is injected using @DubboReference. The parameters passed in when the client calls the service are generated parameters that inherit GeneratedMessageV3. The fields have values when sent, but the field values are lost after the server receives them. From the interceptor, we can see that the argument parameter of invocation was not received on the server side.
    Client:
    image
    Server:
    image
@hebrd hebrd added the type/bug Bugs to being fixed label Oct 8, 2023
@AlbumenJ
Copy link
Member

AlbumenJ commented Oct 8, 2023

Please try use one protocol to see if it work properly?

@AlbumenJ AlbumenJ changed the title Triple Dubbo双协议参数丢失 Triple Dubbo dual protocol parameters are missing Oct 8, 2023
@hebrd
Copy link
Author

hebrd commented Oct 8, 2023

  • Only triple: Invocation from grpc clients works well.
  • Only dubbo: Same error as described.

should I define interface and POJO separately (using code generated by dubbo plugin now) to make dubbo protocol work?

@EarthChen
Copy link
Member

  • Only triple: Invocation from grpc clients works well.
  • Only dubbo: Same error as described.

should I define interface and POJO separately (using code generated by dubbo plugin now) to make dubbo protocol work?

The stub mode uses protobuf serialization, but when using the dubbo protocol, other serializations are used, and protobuf objects cannot be serialized, which causes problems.

@hebrd
Copy link
Author

hebrd commented Oct 8, 2023

  • Only triple: Invocation from grpc clients works well.
  • Only dubbo: Same error as described.

should I define interface and POJO separately (using code generated by dubbo plugin now) to make dubbo protocol work?

The stub mode uses protobuf serialization, but when using the dubbo protocol, other serializations are used, and protobuf objects cannot be serialized, which causes problems.

It there any way to fix this issue without defining another interface and pojo?

@AlbumenJ
Copy link
Member

AlbumenJ commented Oct 9, 2023

Have you added the serialization support?

<dependency>
    <groupId>org.apache.dubbo.extensions</groupId>
    <artifactId>dubbo-serialization-protobuf</artifactId>
    <version>1.0.1</version>
</dependency>

@hebrd
Copy link
Author

hebrd commented Oct 10, 2023

Have you added the serialization support?

<dependency>
    <groupId>org.apache.dubbo.extensions</groupId>
    <artifactId>dubbo-serialization-protobuf</artifactId>
    <version>1.0.1</version>
</dependency>

Not work after adding this dependency.

@namelessssssssssss
Copy link
Contributor

Have you added the serialization support?

<dependency>
    <groupId>org.apache.dubbo.extensions</groupId>
    <artifactId>dubbo-serialization-protobuf</artifactId>
    <version>1.0.1</version>
</dependency>

Not work after adding this dependency.

Can you provide some detailed error message after adding this dependency?

@namelessssssssssss
Copy link
Contributor

Here are one possible solution

  • First, import dubbo-serialization-protobuf:
   <dependency>
            <groupId>org.apache.dubbo.extensions</groupId>
            <artifactId>dubbo-serialization-protobuf</artifactId>
            <version>1.0.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.protobuf</groupId>
                    <artifactId>protobuf-java</artifactId>
                </exclusion>
            </exclusions>
   </dependency>
  • Then, fix org.apache.dubbo.rpc.model.StubMethodDescriptor, and recompile dubbo-common with a new version :
  public StubMethodDescriptor(String methodName,...
        ...
        // this.returnTypes = new Type[]{requestClass, requestClass};
        this.returnTypes = new Type[]{returnClass, returnClass};
        ...
    }
  • Import new dubbo-common to your project, and run mvn clean install to generate triple stub
  • Rename async method name of StubMethodDescriptor :

If you have a service

message GreeterRequest {
  string name = 1;
}
message GreeterReply {
  string message = 1;
}
service Greeter{
  rpc greet(GreeterRequest) returns (GreeterReply);
}

It will generate 3 StubMethodDescriptor for method greet in DubboGreeterTriple:

   private static final StubMethodDescriptor greetMethod = new StubMethodDescriptor("greet", [a lot of params]);

    private static final StubMethodDescriptor greetAsyncMethod = new StubMethodDescriptor("greet",  [a lot of params]);

    private static final StubMethodDescriptor greetProxyAsyncMethod = new StubMethodDescriptor("greetAsync", [a lot of params]);

Rename the second and third StubMethodDescriptor to "greetAsync" and "greetProxyAsync":

   private static final StubMethodDescriptor greetMethod = new StubMethodDescriptor("greet", [a lot of params]);

    private static final StubMethodDescriptor greetAsyncMethod = new StubMethodDescriptor("greetAsync",  [a lot of params]);

    private static final StubMethodDescriptor greetProxyAsyncMethod = new StubMethodDescriptor("greetProxyAsync", [a lot of params]);

I haven't tried if this will affect async call, but if don't do that the async StubMethodDescriptor will take place of the sync one in StubServiceDescriptor.methods, and finally casue Exception java.lang.IllegalArgumentException: This serialization only support google protobuf messages, but the actual input type is :java.util.concurrent.CompletableFuture.

  • Add generated message class to org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils before your dubbo service export/refer
        ProtobufUtils.marshaller(GreeterRequest.getDefaultInstance());
        ProtobufUtils.marshaller(GreeterReply.getDefaultInstance());
  • Set a new protocol for MetadataService beacause it does not support protobuf serialization.

Full demo

provider

public class TriOpServer {

    public static void main(String[] args) throws IOException {
        ServiceConfig<Greeter> service = new ServiceConfig<>();
        service.setInterface(Greeter.class);
        service.setRef(new TriGreeterImpl());
        service.setSerialization("protobuf");
        service.setTimeout(1000000);

        ProtocolConfig dubboProtocolConfig = new ProtocolConfig(CommonConstants.DUBBO,50063);
        dubboProtocolConfig.setSerialization("protobuf");

        ApplicationConfig applicationConfig = new ApplicationConfig("tri-stub-server");
        applicationConfig.setSerializeCheckStatus("DISABLE");

        ProtobufUtils.marshaller(GreeterRequest.getDefaultInstance());
        ProtobufUtils.marshaller(GreeterReply.getDefaultInstance());

        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(applicationConfig)
                .registry(new RegistryConfig("zookeeper://localhost:2181"))
                .protocol(new ProtocolConfig(CommonConstants.TRIPLE, 50053))
                .protocol(dubboProtocolConfig)
                .service(service)
                .start()
                .await();
    }
}

public class TriGreeterImpl extends DubboGreeterTriple.GreeterImplBase {
    private static final Logger LOGGER = LoggerFactory.getLogger(org.apache.dubbo.samples.tri.grpc.interop.server.TriGreeterImpl.class);

    public TriGreeterImpl() {
    }

    @Override
    public GreeterReply greet(GreeterRequest request) {
        LOGGER.info("Server received greet request {}", request);
        return GreeterReply.newBuilder()
                .setMessage("hello," + request.getName())
                .build();
    }
}

consumer

public class TriOpClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(TriOpClient.class);

    private static Greeter triGreeter;

    private static Greeter dubboGreeter;

    public static void main(String[] args) throws IOException, InterruptedException {
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        ReferenceConfig<Greeter> tripleRef = new ReferenceConfig<>();
        tripleRef.setInterface(Greeter.class);
        tripleRef.setProtocol(CommonConstants.TRIPLE);
        tripleRef.setProxy(CommonConstants.NATIVE_STUB);
        tripleRef.setTimeout(3000);

        ReferenceConfig<Greeter> dubboRef = new ReferenceConfig<>();
        dubboRef.setInterface(Greeter.class);
        dubboRef.setProtocol(CommonConstants.DUBBO);
        dubboRef.setProxy(CommonConstants.NATIVE_STUB);
        dubboRef.setTimeout(3000000);

        ProtobufUtils.marshaller(GreeterRequest.getDefaultInstance());
        ProtobufUtils.marshaller(GreeterReply.getDefaultInstance());

        ApplicationConfig applicationConfig = new ApplicationConfig("tri-stub-consumer");
        applicationConfig.setSerializeCheckStatus("DISABLE");
        bootstrap.application(applicationConfig)
                .reference(dubboRef)
                .reference(tripleRef)
                .registry(new RegistryConfig("zookeeper://localhost:2181"))
                .start();

        dubboGreeter = dubboRef.get();
        triGreeter = tripleRef.get();

        while (true){
            Thread.sleep(1000);
            unary(dubboGreeter,"dubbo");
            unary(triGreeter,"triple");
        }
    }

    public static void unary(Greeter ref,String name) {
        LOGGER.info("Start unary");
        final GreeterReply reply = ref.greet(GreeterRequest.newBuilder()
                .setName(name)
                .build());
        LOGGER.info("Unary reply <-{}", reply);
    }
}

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/bug Bugs to being fixed
Projects
None yet
5 participants