proto protobuf
syntax = "proto3";
// go 生成檔案所在包
option go_package = "proto";
option java_multiple_files = true;
// java 生成檔案所在包
option java_package = "com.bocloud.autorelease.hello";
// java 生成檔案類名稱
option java_outer_classname = "HelloProto";
option objc_class_prefix = "HL";
package hello;
service Hello {
// 接口 1
rpc SayHello (HelloRequest) returns (HelloResponse) {}
// 接口 2
rpc SayOperation (WatchObject) returns (HelloResponse) {}
}
// 資料結構
message WatchObject{
ServiceObject service = 1;
DeployObject deploy = 2;
string verb = 3;
}
// 資料結構
message ServiceObject{
string name = 1;
string namespace = 2;
map<string, string> labels = 3;
}
// 資料結構
message DeployObject{
string name = 1;
string namespace = 2;
map<string, string> labels = 3;
}
// 資料結構.
message HelloRequest {
string name = 1;
}
// 資料結構
message HelloResponse {
string message = 1;
}
初始化 go 用戶端
1:生成代碼
需要注意的地方:
- 需要在 proto 檔案目錄生成,先安裝 protoc 指令
protoc --go_out=plugins=grpc:./ ./hello.proto
2:生成代碼以後的目錄層級
- proto 是我的 proto 檔案以及生成的檔案所在的目錄
- test 是我的測試用戶端,client.go 是我調用 java 服務端的檔案
- go.mod go 依賴
3:測試 client.go
package main
import (
"auth-release/proto"
"context"
"google.golang.org/grpc"
"log"
)
const (
Address string = "127.0.0.1:50051"
)
func main() {
// 連接配接伺服器
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
log.Fatalf("net.Connect err: %v", err)
}
// 建立用戶端
grpcClient := proto.NewHelloClient(conn)
req := proto.HelloRequest{Name: "Tom"}
// 調用 Server
res, err := grpcClient.SayHello(context.Background(), &req)
if err != nil {
log.Fatalf("Call Route err: %v", err)
}
// 列印傳回值
log.Println(res)
}
4:go 依賴
差點忘記說,go.mod 中的依賴
github.com/golang/protobuf v1.4.2
google.golang.org/grpc v1.28.1
google.golang.org/protobuf v1.23.0
初始化 java 服務端
1:添加依賴
必須添加下面這些依賴,不然生成之後會出現錯誤。
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.23.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.23.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.23.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.23.1:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
2:生成代碼
需要注意的地方:
- proto 檔案所在的目錄需要與 java、resource 目錄等級相同。如下所示,proto 目錄就是我 proto 檔案的目錄
- 複制完檔案之後直接将 target 清理了 mvn clean 添加依賴之後,直接
即可 為什麼生成的目錄是這樣的?因為早在 porto 檔案中已經定義了 java 檔案的生成目錄,以及生成名稱, 下面兩行maven clean install
option java_package = "com.bocloud.autorelease.hello";
option java_outer_classname = "HelloProto";
然後複制這些檔案到你項目中
3:添加 server 端
package com.bocloud.autorelease.server;
import com.bocloud.autorelease.hello.*;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import static io.grpc.stub.ClientCalls.asyncUnaryCall;
public class HelloServer {
private Server server;
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
server = ServerBuilder.forPort(port)
.addService(new HelloIml()) //這裡可以添加多個子產品
.build()
.start();
System.out.println("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
try {
HelloServer.this.stop();
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
System.err.println("*** server shut down");
}
});
}
private void stop() throws InterruptedException {
if (server != null) {
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
}
}
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();
}
private static class HelloIml extends HelloGrpc.HelloImplBase{
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
// super.sayHello(request, responseObserver);
HelloResponse helloResponse=HelloResponse.newBuilder().setMessage("Hello "+request.getName()+", I'm Java grpc Server").build();
responseObserver.onNext(helloResponse);
responseObserver.onCompleted();
}
@Override
public void sayOperation(WatchObject request,
io.grpc.stub.StreamObserver<HelloResponse> responseObserver) {
System.out.println("Deployment" +"="+ request.getDeploy().toString());
System.out.println("Service" +"="+ request.getService().toString());
System.out.println("operation" +"="+ request.getVerb());
HelloResponse helloResponse=HelloResponse.newBuilder().setMessage("Watch operation"+request.getVerb()+", I've responded").build();
responseObserver.onNext(helloResponse);
responseObserver.onCompleted();
}
}
}
運作測試
1:啟動 server
10:18:37.447 [main] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
10:18:37.447 [main] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
10:18:37.447 [main] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
Server started, listening on 50051
啟動成功,并且監聽在
50051
端口
2:指定 client 調用
2020/09/11 10:21:03 message:"Hello Tom, I'm Java grpc Server"
Process finished with exit code 0
執行成功。上面我寫了兩個接口,大家可以嘗試調用另一個接口試試。