gRPC基本使用(一)--java與go之間的相互調用 原 薦

gRPC是一個高性能、開源、通用的RPC框架,面向移動和HTTP/2設計。gRPC 默認使用 protocol buffers,這是 Google 開源的一套成熟的結構數據序列化機制。

Protocol Buffers 是一種輕便高效的結構化數據存儲格式,可以用於結構化數據串行化,或者說序列化。它很適合做數據存儲或 RPC 數據交換格式。可用於通訊協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。

簡介

本文只是根據gRPC相關資料文檔編寫的Java Spring Boot 與 Golang 語言相關調用的示例。

詳細內容

編寫proto文件

使用proto3語法。文件user_provider.proto

需要使用proto文件,來自動生成不同語言的相關接口、類、對象等。

// user service provider

// proto語法版本
syntax = "proto3";

// 可選參數 設置java package
option java_package = "cn.lpe234.grpc.grpcdemo.grpc";

// 定義對外暴露的服務
service UserProvider {

    // 根據用戶id獲取用戶信息的服務(具體服務/函數)
    rpc getByUserId(UserIdRequest) returns (UserVoReplay) {}
}

// 請求
message UserIdRequest {
    uint64 id = 1;          // 用戶id 類型爲Long
}

// 響應
message UserVoReplay {
    uint64 id = 1;          // 用戶id
    string username = 2;    // 用戶名稱
}

Java Spring Boot 相關

使用Maven作爲項目的依賴管理及編譯構建工具。當前使用Maven插件,在編譯時根據proto文件自動生成服務編寫時所需的Class類。

需要將*.proto放置在 xxProject/src/main/proto文件夾下,才能被插件讀取到。也就是proto文件夾需要跟javaresources文件夾並列才行(或許可通過修改配置信息修改proto文件存儲位置,未做深究~)。

Maven配置

項目精簡的pxm.xml配置文件。

<!-- grpc 依賴版本 -->
<properties>
        <grpc.version>1.14.0</grpc.version>
</properties>

<!-- grpc 依賴jar包 -->
<dependencies>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty</artifactId>
        <version>${grpc.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>${grpc.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-core</artifactId>
        <version>${grpc.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>${grpc.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-server-spring-boot-starter</artifactId>
        <version>2.0.1.RELEASE</version>
    </dependency>
</dependencies>

<!-- grpc build 插件 -->
<build>
    <extensions>
        <extension>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>1.4.1.Final</version>
        </extension>
    </extensions>
    <plugins>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.5.0</version>
            <configuration>
                <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}</pluginArtifact>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>compile-custom</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

理論上,此時執行 mvn -DskipTests=true compile,即可正常生成gRPC相關的Class類。

target
├── generated-sources
│   ├── annotations
│   └── protobuf
│       ├── grpc-java
│       │   └── cn
│       │       └── lpe234
│       │           └── grpc
│       │               └── grpcdemo
│       │                   └── grpc
│       │                       └── UserProviderGrpc.java
│       └── java
│           └── cn
│               └── lpe234
│                   └── grpc
│                       └── grpcdemo
│                           └── grpc
│                               └── UserProviderOuterClass.java

gPPC服務提供編寫

使用註解(@net.devh.springboot.autoconfigure.grpc.server.GrpcService)的方式對外提供服務,類似Dubbo服務中的註解方式。

package cn.lpe234.grpc.grpcdemo.grpcprovider;

import cn.lpe234.grpc.grpcdemo.grpc.UserProviderGrpc;
import cn.lpe234.grpc.grpcdemo.grpc.UserProviderOuterClass;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;

/**
 * Grpc服務暴露
 *
 * @author lpe234
 * @datetime 2018/11/24 14:36
 */
@Slf4j
@GrpcService(UserProviderGrpc.class)
public class UserProvider extends UserProviderGrpc.UserProviderImplBase {

    @Override
    public void getByUserId(UserProviderOuterClass.UserIdRequest request, StreamObserver<UserProviderOuterClass.UserVoReplay> responseObserver) {
        // super.getByUserId(request, responseObserver);

        // 獲取請求數據
        long userId = request.getId();
        log.debug("grpc request: userId=" + userId);

        // 構造返回數據
        UserProviderOuterClass.UserVoReplay.Builder userVoReplayBuild = UserProviderOuterClass.UserVoReplay.newBuilder();
        userVoReplayBuild.setId(userId);
        userVoReplayBuild.setUsername("hello world");
        UserProviderOuterClass.UserVoReplay userVoReplay = userVoReplayBuild.build();

        // 做出響應
        responseObserver.onNext(userVoReplay);
        responseObserver.onCompleted();
    }
}

gRPC對外服務暴露相關配置

application.xml文件。需配置綁定的地址和監聽的端口。

# grpc
grpc:
  server:
    address: 0.0.0.0
    port: 10081

運行

如果一切順利的話,啓動Spring Boot項目。可看到控制檯日誌輸出:

2018-11-24 16:51:16.999  INFO 60266 --- [           main] n.d.s.a.g.server.NettyGrpcServerFactory  : Registered gRPC service: UserProvider, bean: userProvider, class: cn.lpe234.grpc.grpcdemo.grpcprovider.UserProvider
2018-11-24 16:51:17.124  INFO 60266 --- [           main] n.d.s.a.grpc.server.GrpcServerLifecycle  : gRPC Server started, listening on address: 0.0.0.0, port: 10081
2018-11-24 16:51:17.141  INFO 60266 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 10080 (http) with context path ''
2018-11-24 16:51:17.145  INFO 60266 --- [           main] c.l.grpc.grpcdemo.GrpcDemoApplication    : Started GrpcDemoApplication in 2.246 seconds (JVM running for 2.721)

可看到:gRPC Server started, listening on address: 0.0.0.0, port: 10081。說明服務啓動正常~

Golang相關

新建項目 grpc-demo並 創建子文件夾 grpc-demo/proto,然後將 最開始的user_provider.proto拷貝進去(由於proto文件定義了RPC調用的所有細節,即所有服務提供或調用均需要保持版本的相同。拷貝似乎有些不妥~)。

生成Golang gRPC調用相關文件

該步驟,需要一些相關依賴~

protoc --go_out=plugins=grpc:. user_provider.proto 

執行成功後,會在該文件夾下生成 user_provider.pb.go 文件。

服務調用

在項目的 src目錄下,新建main.go文件。

備註: 地址直接硬編碼畢竟是不好的,暫不考慮服務註冊發現相關內容,知道這塊應該有更好的解決方案即可~

package main

import (
	"google.golang.org/grpc"
	pb "proto"
	"context"
	"log"
)

func main() {
	// java spring boot 暴露的grpc服務接口
	const addr = "127.0.0.1:10081"


	// 連接服務
	conn, err := grpc.Dial(addr, grpc.WithInsecure())
	if err != nil {
		log.Panic(err)
	}

	// 確保連接最終被關閉
	defer conn.Close()

	// 建立遠程調用客戶端
	client := pb.NewUserProviderClient(conn)
	reply, err := client.GetByUserId(context.Background(), &pb.UserIdRequest{Id: 1})
	if err != nil {
		log.Panic(err)
	}

	// 輸出結果
	log.Println("user info:", reply.Id, reply.Username)
}

運行

執行後,可分別在服務調用和提供者日誌中看到如下內容:

# Golang
2018/11/24 17:10:12 user info: 1 hello world
# Spring Boot
2018-11-24 17:10:12.123 DEBUG 60266 --- [ault-executor-1] c.l.g.g.grpcprovider.UserProvider        : grpc request: userId=1

完結

至此,已完成了Java提供服務,Golang調用服務。

項目源碼:https://github.com/lpe234/grpc-demo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章