天天看点

gRPC Golang 客户端调用 Java 服务

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:生成代码以后的目录层级

gRPC Golang 客户端调用 Java 服务
  • 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
    gRPC Golang 客户端调用 Java 服务
    添加依赖之后,直接

    maven clean install

    即可
    gRPC Golang 客户端调用 Java 服务
    为什么生成的目录是这样的?因为早在 porto 文件中已经定义了 java 文件的生成目录,以及生成名称, 下面两行
option java_package = "com.bocloud.autorelease.hello";
option java_outer_classname = "HelloProto";
           

然后复制这些文件到你项目中

gRPC Golang 客户端调用 Java 服务

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
           

执行成功。上面我写了两个接口,大家可以尝试调用另一个接口试试。