Java的GRPC

Ho1d_F0rward發表於2024-09-01

環境配置

<?xml version="1.0" encoding="UTF-8"?>  
<project xmlns="http://maven.apache.org/POM/4.0.0"  
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    <modelVersion>4.0.0</modelVersion>  
  
    <groupId>org.example</groupId>  
    <artifactId>JAVA-GRPC</artifactId>  
    <version>1.0-SNAPSHOT</version>  
  
    <properties>        <maven.compiler.source>17</maven.compiler.source>  
        <maven.compiler.target>17</maven.compiler.target>  
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
    </properties>    <dependencies>        <!-- gRPC core library -->  
        <dependency>  
            <groupId>io.grpc</groupId>  
            <artifactId>grpc-netty</artifactId>  
            <version>1.56.0</version> <!-- 使用最新版本 -->  
        </dependency>  
        <dependency>            <groupId>io.grpc</groupId>  
            <artifactId>grpc-protobuf</artifactId>  
            <version>1.56.0</version>  
        </dependency>        <dependency>            <groupId>io.grpc</groupId>  
            <artifactId>grpc-stub</artifactId>  
            <version>1.56.0</version>  
        </dependency>        <!-- Protocol Buffers -->  
        <dependency>  
            <groupId>com.google.protobuf</groupId>  
            <artifactId>protobuf-java</artifactId>  
            <version>3.24.0</version> <!-- 使用最新版本 -->  
        </dependency>  
        <dependency>            <groupId>javax.annotation</groupId>  
            <artifactId>javax.annotation-api</artifactId>  
            <version>1.3.2</version>  
        </dependency>    </dependencies>  
  
    <build>        <extensions>            <extension>                <groupId>kr.motd.maven</groupId>  
                <artifactId>os-maven-plugin</artifactId>  
                <version>1.6.2</version>  
            </extension>        </extensions>        <plugins>            <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.19.2:exe:${os.detected.classifier}</protocArtifact>  
                    <pluginId>grpc-java</pluginId>  
                    <!--suppress UnresolvedMavenProperty -->  
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.44.1:exe:${os.detected.classifier}</pluginArtifact>  
                </configuration>                <executions>                    <execution>                        <goals>                            <goal>compile</goal>  
                            <goal>compile-custom</goal>  
                        </goals>                    </execution>                </executions>            </plugin>        </plugins>    </build>  
  
</project>

程式碼生成

// 宣告版本  
syntax = "proto3";   
  
//服務方法,接受客戶端引數,返回服務端響應  
service SayHello {  
  rpc SayHello(HelloRequest) returns (HelloResponse) {}  
}  
  
//類似結構體  
message HelloRequest {  
  string username = 1;  
  int64 code = 2;  
}  
  
message HelloResponse {  
  string responseMsg = 1;  
}

然後點選idea的maven為所有專案生成原始碼並更新資料夾,來生成對應的java程式碼。

客戶端

程式碼示例

public class Main {  
    public static void main(String[] args) {  
        // 建立 gRPC 連線  
        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 2333)  
                .usePlaintext() // 使用明文傳輸  
                .build();  
  
        // 建立客戶端存根  
        SayHelloGrpc.SayHelloBlockingStub stub = SayHelloGrpc.newBlockingStub(channel);  
  
        // 建立請求  
        Hello.HelloRequest request = Hello.HelloRequest.newBuilder()  
                .setUsername("World java")  
                .setCode(12345)  
                .build();  
  
        // 傳送請求並接收響應  
        Hello.HelloResponse response = stub.sayHello(request);  
        System.out.println("Response: " + response.getResponseMsg());  
  
        // 關閉通道  
        channel.shutdown();  
    }  
}

ManagedChannel建立

ManagedChannel 是 gRPC Java 中用於與 gRPC 伺服器進行通訊的主要介面。它提供了一種安全且高效的方式來管理連線。

// 建立 gRPC 連線
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 2333).usePlaintext().build();

這裡usePlaintext()代表使用明文進行傳輸。

存根建立

SayHelloGrpc.SayHelloBlockingStub stub = SayHelloGrpc.newBlockingStub(channel);

方法呼叫

我們有了存根,那麼呼叫方法就很簡單了。

Hello.HelloRequest request = Hello.HelloRequest.newBuilder()  
        .setUsername("World java")  
        .setCode(12345)  
        .build();  
  
// 傳送請求並接收響應  
Hello.HelloResponse response = stub.sayHello(request);  
System.out.println("Response: " + response.getResponseMsg());

建立對應的請求和回應物件,然後透過存根呼叫方法即可。

服務端

程式碼示例

  
public class HelloServer extends SayHelloGrpc.SayHelloImplBase {  
  
    @Override  
    public void sayHello(Hello.HelloRequest req, StreamObserver<Hello.HelloResponse> responseObserver) {  
        String message = "Hello " + req.getUsername() + "\nYour code is: " + req.getCode();  
        Hello.HelloResponse response = Hello.HelloResponse.newBuilder()  
                .setResponseMsg(message)  
                .build();  
  
        // 傳送響應  
        responseObserver.onNext(response);  
        responseObserver.onCompleted();  
    }  
  
    public static void main(String[] args) throws IOException, InterruptedException {  
        // 建立 gRPC 伺服器  
        Server server = ServerBuilder.forPort(2333)  
                .addService(new HelloServer())  
                .build()  
                .start();  
  
        System.out.println("Server started on port 2333...");  
  
        // 等待伺服器停止  
        server.awaitTermination();  
    }  
}

服務端建立

public static void main(String[] args) throws IOException, InterruptedException {  
    // 建立 gRPC 伺服器  
    Server server = ServerBuilder.forPort(2333)  
            .addService(new HelloServer())  
            .build()  
            .start();  
  
    System.out.println("Server started on port 2333...");  
  
    // 等待伺服器停止  
    server.awaitTermination();  
}

這裡類似於客戶端的存根建立,我們這裡建立服務端並進行服務繫結。

服務建立

public class HelloServer extends SayHelloGrpc.SayHelloImplBase {  
  
    @Override  
    public void sayHello(Hello.HelloRequest req, StreamObserver<Hello.HelloResponse> responseObserver) {  
        String message = "Hello " + req.getUsername() + "\nYour code is: " + req.getCode();  
        Hello.HelloResponse response = Hello.HelloResponse.newBuilder()  
                .setResponseMsg(message)  
                .build();  
  
        // 傳送響應  
        responseObserver.onNext(response);  
        responseObserver.onCompleted();  
    }

直接繼承生成的對應類,然後我們在對應的方法中填寫對應的邏輯即可。這裡的StreamObserver<Hello.HelloResponse> responseObserver類有常用的3個方法:

  • onNext(HelloResponse response): 用於傳送一個響應物件到客戶端。
  • onCompleted(): 指示所有響應已經傳送完成,客戶端可以結束處理。
  • onError(Throwable t): 用於在發生錯誤時向客戶端報告錯誤。

相關文章