Bootstrap

java中使用grpc入门笔记

一.通过maven导入所需jar包

        <!--grpc服务-->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.28.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.28.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.28.0</version>
        </dependency>

二.定义proto文件

实例:

syntax = "proto3";
package com.csdn;

option java_multiple_files = true;


message GrpcRequest {
  string msg=1;
}

message GrpcResponse {
  string returninfo = 1;
}


service grpcService {
  rpc greet(GrpcRequest) returns (GrpcResponse);
}

相关语法:gRPC之proto语法 - 简书

三.根据proto生成代码,这里介绍两种方式

        第一种利用idea的protobuf插件来生成代码,配置如下:


            <!--Probuff工具-->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <!--suppress UnresolvedMavenProperty -->
                    <protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <!--suppress UnresolvedMavenProperty -->
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.30.2:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
            </plugin>

此处注意,mac m1芯片执行会报错 ,因为protobuf暂不支持m1芯片,推荐两种解决方案:

1.将os.detected.classifier设置为x86的结构

<properties>
        <os.detected.classifier>osx-x86_64</os.detected.classifier>
</properties>

注意查看自己的本地仓库,是否获取到正确的版本

我在测试时,就未获取到这个文件,导致生成不了service代码,只能手动下载后使用指令去生成代码

2.去github上获取源码,重新编译,具体操作详见:Mac M1(Apple Silicon) 安装 protobuf 2.5.0 - 简书

第二种是自己下载对应的jar包,通过命令手动生成,具体操作如下:

windows环境操作:

1.将protoc-3.17.3-windows-x86_64和protoc-gen-grpc-java-1.30.2-windows-x86_64两个文件下载到d盘,并新建test目录用于生成代码

目录结构如下:

---D:

-------protoc-3.17.3-windows-x86_64

-------protoc-gen-grpc-java-1.30.2-windows-x86_64

-------hellogrpc.proto

-------test

2.在d盘目录下打开终端

3.生成model代码

 D:\protoc-3.17.3-windows-x86_64.exe  --proto_path=D:\ --java_out=D:\test hellogrpc.proto

4.生成service代码

 D:\protoc-3.17.3-windows-x86_64.exe --plugin=protoc-gen-grpc-java=D:\protoc-gen-grpc-java-1.30.2-windows-x86_64.exe --proto_path=D:\ --grpc-java_out=D:\test hellogrpc.proto

参数说明

D:\protoc-3.17.3-windows-x86_64.exe //protoc命令所在路径
 --plugin=protoc-gen-grpc-java=*** //使用插件并指定路径
 --proto_path=*  //需要扫描的proto所在目录 
 --grpc-java_out=*  //生成的java代码路径
 hellogrpc.proto  //proto的名称

参考文章:protobuf java service_【java】protoc不生成.proto中的service,只生成model相关类,求助。..._weixin_39807954的博客-CSDN博客

mac环境下:

1.安装protoc

brew install protobuf

2.mac环境下无法直接调用exe文件,需要自己获取源码编译生成protoc-gen-grpc-java文件

//获取grpc-java源码
git clone https://github.com/grpc/grpc-java.git
//切换分支
git checkout git checkout v1.4.x
//进入grpc-java目录编译
./gradlew build

3.编译产生的文件路径为compiler/build/exe/java_plugin/protoc-gen-grpc-java,也可以直接下载mac版本的protoc-gen-grpc-java.exe插件

4.生成model代码

protoc --proto_path=proto所在目录
 --java_out=生成的代码所在目录
 proto文件名

5.生成service代码,注意需要先给下载的protoc-gen-grpc-java.exe授权,如果不授权可能会报错program not found or is not executable:

/Users/dao/Downloads/protoc-gen-grpc-java-1.4.0-osx-x86_64.exe: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable

授权后,可以正常生成service代码,授权代码 chmod 777  protoc-gen-grpc-java-1.4.0-osx-x86_64.exe

protoc
 --plugin=protoc-gen-grpc-java=*** //使用插件并指定路径(刚才编译好的文件路径,或者下载的插件地址)
 --proto_path=*  //需要扫描的proto所在目录 
 --grpc-java_out=*  //生成的java代码路径
 hellogrpc.proto  //proto的名称

四.服务端代码

package test;

import com.csdn.GrpcRequest;
import com.csdn.GrpcResponse;
import com.csdn.grpcServiceGrpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

import java.io.IOException;

public class GrpcServer {
    private int port = 50051;
    private Server server;

    private void start() throws IOException {
        server = ServerBuilder.forPort(port)
                .addService(new grpcImpl())
                .build()
                .start();
        //_log.info("Server started, listening on "+ port);

        Runtime.getRuntime().addShutdownHook(new Thread(){

            @Override
            public void run(){

                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                GrpcServer.this.stop();
                System.err.println("*** server shut down");
            }
        });
    }

    private void stop(){
        if (server != null){
            server.shutdown();
        }
    }

    // block 一直到退出程序
    private void blockUntilShutdown() throws InterruptedException {
        if (server != null){
            server.awaitTermination();
        }
    }


    public  static  void main(String[] args) throws IOException, InterruptedException {

        final GrpcServer server = new GrpcServer();
        server.start();
        server.blockUntilShutdown();
    }


    // 实现 定义一个实现服务接口的类
    private class grpcImpl extends grpcServiceGrpc.grpcServiceImplBase {
        @Override
        public void greet(GrpcRequest req, StreamObserver<GrpcResponse> responseObserver){
            GrpcResponse response = GrpcResponse.newBuilder().setReturninfo("info").build();
            responseObserver.onNext(response);
            responseObserver.onCompleted();
        }
     
    }
}

五.客户端代码

package test;

import com.csdn.GrpcRequest;
import com.csdn.GrpcResponse;
import com.csdn.grpcServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.util.concurrent.TimeUnit;

public class GrpcClient {
    private final ManagedChannel channel;
    public final grpcServiceGrpc.grpcServiceBlockingStub blockingStub;


    public GrpcClient(String host, int port) {
        channel = ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build();
        blockingStub = grpcServiceGrpc.newBlockingStub(channel);

    }


    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }


    public static void main(String[] args) throws InterruptedException {

        try {

            GrpcClient client = new GrpcClient("127.0.0.1", 50051);
            //封装请求体
            GrpcRequest request =
                    GrpcRequest.newBuilder().setMsg("").build();
            GrpcResponse response;
            try {
                //响应体
                response = client.blockingStub.greet(request);

            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                client.shutdown();
            }

        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

;