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.~