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
添加依赖之后,直接maven clean install
即可
为什么生成的目录是这样的?因为早在 porto 文件中已经定义了 java 文件的生成目录,以及生成名称, 下面两行
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
执行成功。上面我写了两个接口,大家可以尝试调用另一个接口试试。