高性能リモート通信フレームワーク grpc の基本的な使い方

1. grpcを理解する

Google のオープンソースのリモート プロセス呼び出しフレームワークは、多言語システム間の通信をサポートし、さまざまな分散システムに適しており、http2 プロトコルを使用し、protobuf を使用して通信データを高性能にシリアル化します。 nacos2 には、nacos サーバーと nacos クライアント間の通信用の grpc も統合されています。 grpc はクライアントとサーバーの双方向ストリームもサポートしており、2 つのストリームはブロックすることなく独立して連続的に読み書きできます。

2.protobufについて

シリアル化ソリューションとして protobuf のみを使用する場合は、proto ファイルを作成せずに protostuff (protobuf に基づく) を使用することをお勧めします。 grpc の公式クイックスタートは protobuf を直接使用しているため、当面は grpc+protostuff ソリューションがあるかどうかは検討しません。 Java には、proto ファイルから Java ファイルを生成するための Maven プラグインがあるため、proto を個別にインストールする必要はありませんが、proto の基本構文を理解する必要があります。

3. grpc を試してみる

公式のクイックスタートはスプリングブートに基づいていないため、ここではこのボスのJAVA は gRPC を使用している
を参照します。便宜上、サーバーは次のとおりです。 、クライアントはすべて同じプロジェクト内にあります。分離したい場合は、 grpc-client-spring-boot-starter などの依存関係を独立したプロジェクトに導入し、必要なクラス com.example.demo.protogen.UserServiceGrpc,com.example.demo.protogen.User などをコピーします。

3.1 プロジェクトディレクトリ全体

ここに画像の説明を挿入します

3.2 protoファイルの書き込み

proto里放file.proto,message.proto文件如下

syntax = "proto3";

package protogen;
option java_package = "com.example.demo.protogen";

message File {
  string name = 1;
  int32 size = 2;
}
syntax = "proto3";
package protogen;

import "file.proto";

option java_multiple_files = true;
option java_package = "com.example.demo.protogen";

message User {
  reserved 6 to 7;
  reserved "userId2";
  int32 userId = 1;
  string username = 2;
  oneof msg {
    string error = 3;
    int32 code = 4;
  }
  string name = 8;

  UserType userType = 9;
  repeated int32 roles = 10;

  protogen.File file = 11;
  map<string, string> hobbys = 12;
}

enum UserType {
  UNKNOW = 0;
  ADMIN = 1;
  BUSINESS_USER = 2;
};

service UserService {
  rpc getUser (User) returns (User) {}
  rpc getUsers (User) returns (stream User) {}
  rpc saveUsers (stream User) returns (User) {}
}

service FileService {
  rpc getFile(User) returns(File) {}
}

3.3 Maven protobuf プラグインを使用して .proto ファイルを変換する

protogen 内のファイルはすべて生成されます。プラグインは、このディレクトリを読み取り、protogen フォルダに生成するように構成されています。図に示すようにプラグイン ボタンをクリックすると、protobuf:compile は実際に proto.exe を通じて .proto ファイルから Java ファイルを生成します。ただし、 FileServiceGrpc,UserServiceGrpc は です。 protobuf:compile-custom生成され、残りはprotobuf:compile生成されます。

3.4 Grpcサーバー業務実装クラス

UserServiceImpl.java

package com.example.demo.grpc.server;

import com.example.demo.protogen.User;
import com.example.demo.protogen.UserServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;

/**
 * @author Kone
 * @date 2022/1/29
 */
@GrpcService
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
    
    
    @Override
    public void getUser(User request, StreamObserver<User> responseObserver) {
    
    
        System.out.println(request);
        User user = User.newBuilder()
                .setName("response name")
                .build();
        responseObserver.onNext(user);
        responseObserver.onCompleted();
    }

    @Override
    public void getUsers(User request, StreamObserver<User> responseObserver) {
    
    
        System.out.println("get users");
        System.out.println(request);
        User user = User.newBuilder()
                .setName("user1")
                .build();
        User user2 = User.newBuilder()
                .setName("user2")
                .build();
        responseObserver.onNext(user);
        responseObserver.onNext(user2);

        responseObserver.onCompleted();
    }

    @Override
    public StreamObserver<User> saveUsers(StreamObserver<User> responseObserver) {
    
    

        return new StreamObserver<User>() {
    
    
            @Override
            public void onNext(User user) {
    
    
                System.out.println("get saveUsers list ---->");
                System.out.println(user);
            }

            @Override
            public void onError(Throwable throwable) {
    
    
                System.out.println("saveUsers error " + throwable.getMessage());
            }

            @Override
            public void onCompleted() {
    
    
                User user = User.newBuilder()
                        .setName("saveUsers user1")
                        .build();
                responseObserver.onNext(user);
                responseObserver.onCompleted();
            }
        };
    }
}

3.5ポン参考

springboot3 は不具合があるので、当面は springboot バージョン 2.7.9 を使用します。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/> 
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
        <protobuf.version>3.23.4</protobuf.version>
        <grpc.version>1.26.0</grpc.version>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>${protobuf.version}</version>
        </dependency>
        <!-- grpc server和spring-boot集成框架 -->
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>2.14.0.RELEASE</version>
        </dependency>

        <!-- grpc client和spring-boot集成框架 -->
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-client-spring-boot-starter</artifactId>
            <version>2.14.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

    <build>

        <!-- os系统信息插件, protobuf-maven-plugin需要获取系统信息下载相应的protobuf程序 -->
        <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>
                    <!--os.detected.classifier属性是通过如上os-maven-plugin插件获取的-->
                    <protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
                    </protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
                    </pluginArtifact>

                    <!-- proto文件目录 -->
                    <protoSourceRoot>${project.basedir}/src/main/java/com/example/demo/proto</protoSourceRoot>
                    <!-- 生成的Java文件目录,这里指定到这一级就可以咯,proto文件有基于package指定 -->
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <clearOutputDirectory>false</clearOutputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.6 grpc クライアント呼び出し

  • grpcサーバーのURLに基​​づく直接呼び出し
package com.example.demo;

import com.example.demo.protogen.User;
import com.example.demo.protogen.UserServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.util.Iterator;

public class FramelessGrpcClient {
    
    

    public static void main(String[] args) {
    
    
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9090).usePlaintext().build();
        UserServiceGrpc.UserServiceBlockingStub userService = UserServiceGrpc.newBlockingStub(managedChannel);
        User user = User.newBuilder()
                .setUserId(100)
                .putHobbys("pingpong", "play pingpong")
                .setCode(200)
                .build();
        System.out.println("get response-------->");
        System.out.println(userService.getUser(user));
        Iterator<User> users = userService.getUsers(user);
    }
}
  • Spring IOCからBeanを注入してgrpcサーバーを呼び出します(URL等はymlで設定します)。ここでは、スケジュールされたタスクを使用して、スケジュールをトリガーします。挿入された「userClient」は、yml のカスタム クライアント名と一致している必要があることに注意してください (複数の grpc サーバーが呼び出される場合、このカスタム名はどの grpc サーバーが呼び出されるかを区別するために使用されます)。
package com.example.demo;

import com.example.demo.protogen.User;
import com.example.demo.protogen.UserServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Iterator;

/**
 * TODO
 *
 * @author majun
 * @version 1.0
 * @since 2023-08-02 20:19
 */
@Component
@EnableScheduling
public class SpringbootGrpcClient {
    
    
    @GrpcClient("userClient")
    private UserServiceGrpc.UserServiceBlockingStub userService;


    @Scheduled(fixedDelay = 10000)
    public void test() {
    
    
        User user = User.newBuilder()
                .setUserId(100)
                .putHobbys("pingpong", "play pingpong")
                .setCode(200)
                .build();
        System.out.println("get response-------->");
        System.out.println(userService.getUser(user));

        Iterator<User> users = this.userService.getUsers(user);
        while (users.hasNext()) {
    
    
            System.out.println(users.next());
        }
    }
}

おすすめ

転載: blog.csdn.net/qq_39506978/article/details/132070946