转自:
gRPC
Define your service using Protocol Buffers, a powerful binary serialization toolset and language
gRPC是基于Protobuf开发的RPC框架,简化了protobuf的开发,提供了服务端和客户端网络交互这一块的代码。
Demo
照着
记得要把Update a gRPC service
部分做了。
gRPC整合Gradle与代码生成
这个是gRPC-java项目,先引入gRPC的依赖。 1 2 3 | compile 'io.grpc:grpc-netty:1.4.0' compile 'io.grpc:grpc-protobuf:1.4.0' compile 'io.grpc:grpc-stub:1.4.0' |
然后配置gradle的grpc插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | apply plugin: 'java' apply plugin: 'com.google.protobuf' buildscript { repositories { mavenCentral() } dependencies { // ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier // gradle versions classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1' } } protobuf { protoc { artifact = "com.google.protobuf:protoc:3.2.0" } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.4.0' } } generateProtoTasks { all()*.plugins { grpc {} } } } |
后面直接用gradle的任务就可以生成代码了。
gRPC提供了3种传输层的实现
-
gRPC comes with three Transport implementations:
- The Netty-based transport is the main transport implementation based on Netty. It is for both the client and the server.
- The OkHttp-based transport is a lightweight transport based on OkHttp. It is mainly for use on Android and is for client only.
- The inProcess transport is for when a server is in the same process as the client. It is useful for testing.
The Gradle plugin that compiles Protocol Buffer (aka. Protobuf) definition files (*.proto) in your project. There are two pieces of its job:
- It assembles the Protobuf Compiler (protoc) command line and use it to generate Java source files out of your proto files.
- It adds the generated Java source files to the input of the corresponding Java compilation unit (sourceSet in a Java project; variant in an Android project), so that they can be compiled along with your Java sources.
实战
配置好后,进行一个演示
在src/main/proto
新建一个文件Student.proto
gradle插件默认从src/main/proto
找proto源文件进行代码生成,有提到,而且这个路径的配置是可以修改的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | syntax = "proto3"; package com.sail.proto; option java_package = "com.sail.proto"; option java_outer_classname = "StudentProto"; option java_multiple_files = true; service StudentService { rpc GetRealNameByUsername(MyRequest) returns (MyResponse) {} rpc GetStudentsByAge(StudentRequest) returns (stream StudentResponse) {} rpc GetStudentsWrapperByAges(stream StudentRequest) returns (StudentResponseList) {} rpc BiTalk(stream StreamRequest) returns (stream StreamResponse) {} } message MyRequest { string username = 1; } message MyResponse { string realname = 2; } message StudentRequest { int32 age = 1; } message StudentResponse { string name = 1; int32 age = 2; string city = 3; } message StudentResponseList { repeated StudentResponse studentResponse = 1; } message StreamRequest { string request_info = 1; } message StreamResponse { string response_info = 1; } |
然后执行gradle generateProto
,生成的代码默认是放在/build
目录下,我们手动拷贝到src/main/java
。
实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | package com.sail.grpc; import com.sail.proto.*; import io.grpc.stub.StreamObserver; import java.util.UUID; /** * @author yangfan * @date 2017/08/01 */ public class StudentServiceImpl extends StudentServiceGrpc.StudentServiceImplBase { @Override public void getRealNameByUsername(MyRequest request, StreamObserver |
服务器端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | package com.sail.grpc; import io.grpc.Server; import io.grpc.ServerBuilder; import java.io.IOException; /** * @author yangfan * @date 2017/08/01 */ public class GrpcServer { private Server server; private void start() throws IOException { this.server = ServerBuilder.forPort(8899).addService(new StudentServiceImpl()).build().start(); System.out.println("server started!"); // 这里在关闭JVM的时候会执行JVM回调钩子 Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.println("关闭jvm"); GrpcServer.this.stop(); })); System.out.println("执行到这里"); } private void stop() { if (server != null) { this.server.shutdown(); } } private void awaitTermination() throws InterruptedException { if (server != null) { this.server.awaitTermination(); } } public static void main(String[] args) throws InterruptedException, IOException { GrpcServer grpcServer = new GrpcServer(); grpcServer.start(); grpcServer.awaitTermination(); } } |
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | package com.sail.grpc; import com.sail.proto.*; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.stub.StreamObserver; import java.time.LocalDateTime; import java.util.Iterator; /** * @author yangfan * @date 2017/08/01 */ public class GrpcClient { public static void main(String[] args) { ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 8899) .usePlaintext(true).build(); StudentServiceGrpc.StudentServiceBlockingStub blockingStub = StudentServiceGrpc.newBlockingStub(managedChannel); StudentServiceGrpc.StudentServiceStub stub = StudentServiceGrpc.newStub(managedChannel); MyResponse myResponse = blockingStub.getRealNameByUsername(MyRequest.newBuilder().setUsername("zhangsan").build()); System.out.println(myResponse.getRealname()); System.out.println("----------------"); Iterator |