Use of gRPC in RPC

Keywords: Programming Java Maven Google github

This article describes the process of using gRPC in Java. Generally speaking, it consists of the following three steps
1) Define the services provided in the. proto file
2) Compile files using protocol buffer compiler
3) Use gRPC API to create and invoke the server and client.

Download and install the required software

1)Protocol Buffers
Structured data serialization mechanism
https://github.com/protocolbuffers/protobuf/releases
Use examples:

protoc --java_out=./ *.proto

2)protoc-gen-grpc-java
Used to generate RPC communication code
http://jcenter.bintray.com/io/grpc/protoc-gen-grpc-java/
Using an example [using the Protobuf-Plugin mechanism]:

protoc --plugin=protoc-gen-grpc-java=protoc-gen-grpc-java-1.19.0-windows-x86_64.exe --grpc-java_out=./ *.proto

Building gRPC with Maven

1) Modify pmo.xml

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <protobuf.version>3.7.0</protobuf.version>
        <grpc.version>1.19.0</grpc.version>
    </properties>

    <dependencies>      
        <dependency>
          <groupId>io.grpc</groupId>
          <artifactId>grpc-netty-shaded</artifactId>
          <version>${grpc.version}</version>
        </dependency>
        <dependency>
          <groupId>io.grpc</groupId>
          <artifactId>grpc-protobuf</artifactId>
          <version>${grpc.version}</version>
        </dependency>
        <dependency>
          <groupId>io.grpc</groupId>
          <artifactId>grpc-stub</artifactId>
          <version>${grpc.version}</version>
        </dependency>
        <!-- Ensure that the runtime version number and protoc Version number matching (or updating) -->
        <dependency>
          <groupId>com.google.protobuf</groupId>
          <artifactId>protobuf-java</artifactId>
          <version>${protobuf.version}</version>
        </dependency>
        <!-- If you want to use Imagination JsonFormat Such a feature adds the following dependencies-->
        <dependency>
          <groupId>com.google.protobuf</groupId>
          <artifactId>protobuf-java-util</artifactId>
          <version>${protobuf.version}</version>
        </dependency>
    </dependencies>
    <build>
        <extensions>
            <extension>
                <!-- Reference to the description of the plug-in https://github.com/trustin/os-maven-plugin -->
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.1</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <!-- proto The path of the file -->
                    <!-- <protoSourceRoot>${project.basedir}/src/main/resources/proto</protoSourceRoot> -->
                    <!-- After compilation java Output path of file,Default is ${project.build.directory}/generated-sources/protobuf/java -->
                    <!--<outputDirectory> ${project.build.directory}/generated-sources/protobuf/java</outputDirectory> -->
                    <!-- Formulate protoc Compiler path -->
                    <!-- <protocExecutable></protocExecutable> -->
                    <!-- Define the generated java File output path -->
                    <!--<outputDirectory>${project.build.sourceDirectory}</outputDirectory> -->
                    <!--Set whether to generate java Clean up before the document outputDirectory File, default value true,Set to false It also overwrites files with the same name. -->
                    <clearOutputDirectory>false</clearOutputDirectory>
                    <protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

By default, the plug-in looks for proto files in the src/main/proto path. Any subfolder under the path will be used as the package path in the proto file.

2) Create proto file under src/main/proto

syntax = "proto3";

package com.ultrapower.ioss.webdriver.proto;

option java_outer_classname = "HarLogRpc";

message HarLogResovleRequest{
    string url = 1 ;
    string file_name = 2;
    string file_dir = 3;
    string context = 4;
}

message HarLogResovleResponse{
    int32 code = 1 ;
}

service HarLogService{
    rpc ResovleHarLog(HarLogResovleRequest) returns (HarLogResovleResponse);
}

3) Compile files

mvn protobuf:compile 
//or
mvn compile

The following two folders are generated under target generated-sources protobuf

The Java folder contains the message we defined, while grpc-java stores the service that both the server and the client use.
Based on the proto file above, two java files are generated

1. HarLogService Grpc. Java is located under grpc-java
 2. HarLogRpc.java is under java

4) Complete the code

First we implement the server-side code

package com.ultrapower.ioss.webdriver.proto;

import com.ultrapower.ioss.webdriver.proto.HarLogRpc.HarLogResovleRequest;
import com.ultrapower.ioss.webdriver.proto.HarLogRpc.HarLogResovleResponse;

import io.grpc.stub.StreamObserver;

public class HarLogServiceImpl extends HarLogServiceGrpc.HarLogServiceImplBase {

    @Override
    public void resovleHarLog(HarLogResovleRequest request, StreamObserver<HarLogResovleResponse> responseObserver) {
        String fileName = request.getFileName() ;
        responseObserver.onNext(HarLogResovleResponse.newBuilder().setCode(200).build());
        //Represents that the process has been completed
        responseObserver.onCompleted();
    }
}

Start the server

public class Startup {
    private Server server;
    private int port = 8888;

    public void start() throws IOException {
        server = ServerBuilder.forPort(port)
                .addService(new HarLogServiceImpl())
                .build()
                .start();

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                Startup.this.stop();
            }
        });
    }

    private void stop() {
        if (server != null) {
            server.shutdown();
        }
    }

    private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

    public static void main(String[] args) throws Exception {
        final Startup server = new Startup();
        server.start();
        server.blockUntilShutdown();
    }
}

Creating a Java-based client

public class Client {

    private final ManagedChannel channel;

    private final HarLogServiceGrpc.HarLogServiceBlockingStub blockingStub;

    /**
     *  Create a server-side connection and create a "pile"
     * */
    public Client(String host, int port) {
        channel = NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT).build();
        blockingStub = HarLogServiceGrpc.newBlockingStub(channel);
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    /**
     *  Send a request to the server
     * */
    public void resovleHarLog() {
        try {
            HarLogResovleRequest request = HarLogResovleRequest.newBuilder().setUrl("www.baidu.com").setFileName("test").build();
            HarLogResovleResponse response = blockingStub.resovleHarLog(request) ;
            System.out.println("result from server: " + response.getCode());
        } catch (RuntimeException e) {
            System.out.println("RPC failed:" + e.getMessage());
            return;
        }
    }

    public static void main(String[] args) throws Exception {
        Client client = new Client("127.0.0.1", 8888);
        try {
            client.resovleHarLog();
        } finally {
            client.shutdown();
        }
    }
}

Posted by MeanMrMustard on Wed, 27 Mar 2019 14:54:29 -0700