Under Windows, complete the gRPC Java example step by step

Keywords: Maven Java Apache snapshot

This paper gives a Java example of using Google RPC (grpc) to complete rpc step by step under Windows.~

This article will explain from the following parts.

  • Generate code automatically according to proto - Write proto file, and automatically generate code required by gRPC under window s according to tools
  • Code Composition - Gives the modular structure of Maven Engineering and implements the code step by step in each module.
  • Testing - Testing the code written, including Server starting and binding services, Client connecting and invoking services
  • Summary - A brief introduction to the content of this article~

Next, step by step, complete each part.~

Automatically generate code based on proto

Define service interfaces

gRPC is used by default protocol buffers As an interface definition language, it describes service interface and payload message structure.

More proto3 documentation information, see https://developers.google.com/protocol-buffers/docs/proto3

  • hello.proto
syntax = "proto3";

package com.xxx.tutorial.demo.grpc;

option java_multiple_files = true;
option java_package = "com.xxx.tutorial.demo.model";  
option java_outer_classname = "Hello";

message HelloRequest{  
    string name  = 1;  
    int32 id    = 2;  
}  
message HelloResponse{  
    string message = 1;  
}  
  • hello_service.proto
syntax = "proto3";

package com.xxx.tutorial.demo.grpc;


option java_multiple_files = true;
option java_package = "com.xxx.tutorial.demo.service"; 
option java_outer_classname = "GreetingService";

import "hello.proto";

service HelloService{  
    rpc sayHello(HelloRequest) returns (HelloResponse);  
}  

Generate proto file corresponding code

Accessible Web sites[ https://github.com/google/protobuf/releases ] Look at different versions of the code generator. The version used in this article is protoc-3.1.0-win32.zip, which can be downloaded at the following address.

[https://github.com/google/protobuf/releases/download/v3.1.0/protoc-3.1.0-win32.zip]

  • After downloading, decompress and prevent proto files from being placed in bin directory

  • Execute protoc.exe --java_out=./ *.proto generates code~
F:\JavaDeveloper\rpc\gRpc\protoc-3.1.0-win32\bin>protoc.exe --java_out=./ *.proto

After executing the above command, code (including package names) is generated in the bin directory, such as:

The code screenshots in the specific model and service packages are as follows~

Be careful:

The above generated the message object and other related code, but does not include the communication code required by the rpc service.~

Generating rpc communication code

rpc communication code needs protoc-gen-grpc-java plug-in to complete, you can visit the following website to download:

[protoc-gen-grpc-java-0.13.2-windows-x86_64.exe]

Place the downloaded protoc-gen-grpc-java-0.13.2-windows-x86_64.exe in the bin directory under protoc-3.1.0-win32~

For example,

Execute the following statement~

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

Such as:

F:\JavaDeveloper\rpc\gRpc\protoc-3.1.0-win32\bin>protoc.exe --java_out=./ *.proto

F:\JavaDeveloper\rpc\gRpc\protoc-3.1.0-win32\bin>protoc.exe --plugin=protoc-gen-grpc-java=protoc-gen-grpc-java-0.13.2-windows-x86_64.exe --grpc-java_out=./ *.proto

F:\JavaDeveloper\rpc\gRpc\protoc-3.1.0-win32\bin>

You can see an additional HelloService Grpc. java file in the service package~

This file needs to be used in subsequent service implementations

At this point, the Java code generation part based on the proto file is complete. Next, all you have to do is write the service implementation, the server code, and the client call interface code.~

Code composition

Maven Engineering Structure

The Maven project grpc-demo consists of four modules.

  • grpc-demo-interface-Store code generated by proto file
  • grpc-demo-service-Implementing services
  • grpc-demo-server-simple server
  • grpc-demo-client-simple client

The pom file is as follows.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxx.tutorial</groupId>
  <artifactId>grpc-demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <modules>
  	<module>grpc-demo-server</module>
  	<module>grpc-demo-client</module>
  	<module>grpc-demo-interface</module>
  	<module>grpc-demo-service</module>
  </modules>
</project>

The project directory structure of Eclipse is as follows.

grpc-demo-interface module

Copy the generated code directly into src/main/java, such as

The reason for encountering the "red fork" is that the relevant jar packages are not imported to add the relevant dependency packages to the pom.xml file under the module.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.xxx.tutorial</groupId>
		<artifactId>grpc-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>grpc-demo-interface</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.google.protobuf</groupId>
			<artifactId>protobuf-java</artifactId>
			<version>3.1.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/io.grpc/grpc-stub -->
		<dependency>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-stub</artifactId>
			<version>1.3.0</version>
		</dependency>
		<dependency>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-protobuf</artifactId>
			<version>1.3.0</version>
		</dependency>
		<dependency>
			<groupId>io.grpc</groupId>
			<artifactId>grpc-netty</artifactId>
			<version>1.3.0</version>
		</dependency>
	</dependencies>
</project>

The service interface module is completed, and then the implementation of the interface is completed.~

grpc-demo-service module

  • Adding grpc-demo-interface dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.xxx.tutorial</groupId>
		<artifactId>grpc-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>grpc-demo-service</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.xxx.tutorial</groupId>
			<artifactId>grpc-demo-interface</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>
  • Writing Service Interface Implementation Classes
package com.xxx.tutorial.demo.service.impl;

import java.util.logging.Logger;

import com.xxx.tutorial.demo.model.HelloRequest;
import com.xxx.tutorial.demo.model.HelloResponse;
import com.xxx.tutorial.demo.service.HelloServiceGrpc;

import io.grpc.stub.StreamObserver;

public class GreetingServiceImpl implements HelloServiceGrpc.HelloService {

	private static final Logger logger = Logger.getLogger(GreetingServiceImpl.class.getName());

	public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {

		logger.info(String.format("sayHello Request parameter information for method calls: name={%s}, id={%d}", request.getName(), request.getId()));

		HelloResponse reply = HelloResponse.newBuilder().setMessage(String.format("Hello, %s", request.getName()))
				.build();
		
		responseObserver.onNext(reply);
		responseObserver.onCompleted();
	}

}

 

grpc-demo-server module

  • Adding grpc-demo-service dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.xxx.tutorial</groupId>
		<artifactId>grpc-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>grpc-demo-server</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.xxx.tutorial</groupId>
			<artifactId>grpc-demo-service</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
	
</project>
  • Writing Server Code
package com.xxx.tutorial.demo.server;

import java.io.IOException;
import java.util.logging.Logger;

import com.xxx.tutorial.demo.service.HelloServiceGrpc;
import com.xxx.tutorial.demo.service.impl.GreetingServiceImpl;

import io.grpc.Server;
import io.grpc.ServerBuilder;

public class HelloServer {

	private static final Logger logger = Logger.getLogger(HelloServer.class.getName());

	private static final int DEFAULT_PORT = 50051;

	private Server server = null;

	private void start() throws IOException {

		server = ServerBuilder.forPort(DEFAULT_PORT).addService(HelloServiceGrpc.bindService(new GreetingServiceImpl()))
				.build().start();

		logger.info("Server started, listening on " + DEFAULT_PORT);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				System.err.println("*** shutting down gRPC server since JVM is shutting down");
				HelloServer.this.stop();
				System.err.println("*** server shut down");
			}
		});
	}

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

	/**
	 * Await termination on the main thread since the grpc library uses daemon
	 * threads.
	 */
	private void blockUntilShutdown() throws InterruptedException {
		if (server != null) {
			server.awaitTermination();
		}
	}

	public static void main(String[] args) throws IOException, InterruptedException {
		final HelloServer server = new HelloServer();
		server.start();
		server.blockUntilShutdown();
	}

}

grpc-demo-client module

  • Adding grpc-demo-interface dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.xxx.tutorial</groupId>
		<artifactId>grpc-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>grpc-demo-service</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.xxx.tutorial</groupId>
			<artifactId>grpc-demo-interface</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>
  • Writing Client
package com.xxx.tutorial.demo.client;

import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import com.xxx.tutorial.demo.model.HelloRequest;
import com.xxx.tutorial.demo.model.HelloResponse;
import com.xxx.tutorial.demo.service.HelloServiceGrpc;

import io.grpc.ManagedChannel;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;

public class GreetingServiceClient {

	private static final Logger logger = Logger.getLogger(GreetingServiceClient.class.getName());

	private final ManagedChannel channel;

	private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;

	public GreetingServiceClient(String host, int port) {

		channel = NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT).build();
		blockingStub = HelloServiceGrpc.newBlockingStub(channel);
	}

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

	public void sayHello(String name) {
		try {
			System.out.println("Will try to say Hello  " + name + " ...");
			HelloRequest request = HelloRequest.newBuilder().setName(name).setId(12345678).build();
			HelloResponse response = blockingStub.sayHello(request);
			System.out.println("result from server: " + response.getMessage());
		} catch (RuntimeException e) {
			System.out.println("RPC failed:" + e.getMessage());
			return;
		}
	}

	public static void main(String[] args) throws Exception {

		GreetingServiceClient client = new GreetingServiceClient("127.0.0.1", 50051);

		try {
			String name = "Eric";
			logger.info(String.format("Client call RPC Interface, parameter is name = {%s}", name));
			client.sayHello(name);
		} finally {
			client.shutdown();
		}
	}
}

So far, in the Maven project, the code for the four modules is simply written. ~Next, test it.~

test

Server startup

Just run HelloServer.java directly (which contains the main function)~

Client runs

Just run GreetingServiceClient.java directly (which contains the main function)~

Result View

We can see that the client invokes the interface, passes the value name Eric, and gets the corresponding Hello, Eric on the server side.

May 26, 2017: 41:20 p.m. com. xxx. tutorial. demo. client. GreetingService Client main
 Information: Client calls the RPC interface with the parameter name = {Eric}
Will try to say Hello  Eric ...
result from server: Hello, Eric

Look again, the server's output log also contains the request parameters, in which the value of id is not used, so the sayHello interface implemented in Service directly sets up 12345678.

May 26, 2017 6:40:14 p.m. com.xxx.tutorial.demo.server.HelloServer start
 Information: Server started, listening on 50051
 May 26, 2017: 41:20 p.m. com. xxx. tutorial. demo. service. impl. GreetingService Impl sayHello
 Information: Request parameter information for sayHello method calls: name={Eric}, id={12345678}

Summary

As you can see from the results of the above test run, a simple grpc example is complete~

Among them, grpc supports four types of RPC

  • Simple RPC
  • Service-side streaming RPC
  • Client-side streaming RPC
  • Bidirectional Flow RPC

This example completes the first "simple RPC" approach, in which the client issues a single request and receives a single response.

Several other RPC s will be shown later.~

Posted by emceej on Thu, 27 Jun 2019 13:00:02 -0700