Spring boot 整合grpc 运用

文章目录

    • GRPC基础概念:
    • Protocol Buffers:
      • proto 基础语法:
        • 调用类型:
    • Spring boot 整合 grpc
      • 项目结构:
      • 整合代码:
        • 父 pom
        • proto 模块
        • 服务端:
        • 客户端:
        • 实际调用:
      • 原生集成

GRPC基础概念:

  • GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x,基于Netty 4.x.

Protocol Buffers:

  • 一个跨语言、跨平台的具有可扩展机制的序列化数据工具。也就是说,我在ubuntu下用python语言序列化一个对象,并使用http协议传输到使用java语言的android客户端,java使用对用的代码工具进行反序列化,也可以得到对应的对象
    1

proto 基础语法:

//指定proto3语法
syntax = "proto3";
//指定作用域
package xxx;
//java_multiple_files = true; 表示在生成Java代码时,每个`.proto`文件都会生成一个独立的Java文件
//声明 rpc 服务接口
//关键字: service 声明需要生成的服务接口"类"
service Greeter {
    // 关键字: rpc 声明服务方法,包括方法名、请求消息(请求体)、相应消息(响应体)
    rpc SayHello(HelloRequest) returns (HelloResponse);
}
//声明请求、响应消息
//关键字: message 声明请求体和响应体
message HelloRequest {
		//标识号 1
    //编号的范围为1 ~ 536,870,911(2^29-1),其中19000~19999不可用。因为Protobuf协议的实现过程中对预留了这些编号
    string name = 1;
		//表示一个人有多个号码
	  repeated string phone = 3;
}
 
message HelloResponse {
    string message = 1;
}
调用类型:
  • Unary RPC 一元RPC调用,也叫简单RPC调用

    rpc SayHello(HelloRequest) returns (HelloResponse);
    
  • 【服务端 Server Stream RPC】流式RPC. 客户端向服务端发送单个请求,服务端以流的方式返回一系列消息。客户端从流中读取消息,直到没有更多的消息。当然,返回的消息当然不是乱序的,gRPC保证单个请求中的消息顺序

    rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
    
  • 【客户端 Client Stream RPC】流式RPC调用。客户端向服务端请求一系列的消息,一旦客户端完成消息写入,就会等待服务端读取所有消息并处理它们。gRPC同样会保证单个请求中消息的顺序性

    rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
    
  • 【双向流式调用 Bidirectional Streaming RPC】就是客户端和服务端均以流的方式进行读写消息。这两个流式完全独立的,因此,服务端和客户端可以按照他们喜欢的方式写入和读取流。比如:服务端可以在等待所有的客户端消息发送到后,再处理;也可以交替读取请求、写入响应信息等。当然,每个流中的消息顺序是可以保证的。

    rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
    

    Channels通道

    gRPC通道提供了一条链接到指定主机和端口号的服务端的链接。他在创建客户端stub的时候使用。客户端可以指定通道参数来修改gRPC的默认行为,例如:打开或者关闭消息压缩。一个通道是有连接和空闲两个状态的

mvn 插件整合,proto编译,生成代码

<build>
        <plugins>
            <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.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.5.1:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}</pluginArtifact>
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <!--设置grpc生成代码到指定路径-->
                    <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>

        </plugins>

        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>

    </build>

在这里插入图片描述

Spring boot 整合 grpc

大致流程:
1

项目结构:

在这里插入图片描述

整合代码:

父 pom
<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>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.17</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <groupId>com.xiaoshu</groupId>
  <artifactId>grpc-demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>grpc-demo</name>
  <modules>
    <module>grpc-server</module>
    <module>grpc-client</module>
    <module>grpc-proto</module>
  </modules>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <grpc.version>2.15.0.RELEASE</grpc.version>
  </properties>

  <!-- 通用依赖 -->
  <dependencies>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.10</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

  </dependencies>

  <dependencyManagement>
    <dependencies>

      <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-spring-boot-starter</artifactId>
        <version>${grpc.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-server-spring-boot-starter</artifactId>
        <version>${grpc.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-client-spring-boot-starter</artifactId>
        <version>${grpc.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

    </dependencies>

  </dependencyManagement>


  <build>

    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>

  </build>

</project>

proto 模块
syntax = "proto3";

package com.ht.meta;
// 生成类的包名
option java_multiple_files = true;
// 生成代码位置
option java_package = "com.meta";
// 定义的所有消息、枚举和服务生成对应的多个类文件,而不是以内部类的形式出现
option java_outer_classname = "HtMetaInfoSyncProto";

service HtMetaInfoSyncService {
  rpc syncMeta (HtMetaSyncRequest) returns (HtMetaSyncResponse) {}
}

//同步类型
enum SyncType {
  ADD  = 0; // 新增
  DEL  = 1; // 删除
  EDIT = 2; // 修改
}

//同步Request
message HtMetaSyncRequest {
  //json内容
  string syncJson = 1;
  //同步类型
  SyncType syncType = 2;
}

//响应Response
message HtMetaSyncResponse {
  //响应码
  string code = 1;
  //提示
  string msg = 2;
}
<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>
    <parent>
        <groupId>com.xiaoshu</groupId>
        <artifactId>grpc-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>grpc-proto</artifactId>
    <packaging>jar</packaging>

    <name>grpc-proto</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-spring-boot-starter</artifactId>
            <version>${grpc.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <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.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.5.1:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}</pluginArtifact>
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <!--设置grpc生成代码到指定路径-->
                    <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>

        </plugins>

        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>

    </build>


</project>

服务端:
<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>
    <parent>
        <groupId>com.xiaoshu</groupId>
        <artifactId>grpc-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>grpc-server</artifactId>
    <packaging>jar</packaging>

    <name>grpc-server</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.xiaoshu</groupId>
            <artifactId>grpc-proto</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>${grpc.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

    </dependencies>

</project>

server:
  port: 8080

spring:
  application:
    name: spring-boot-grpc-server

# gRPC有关的配置,这里只需要配置服务端口号
grpc:
  server:
    port: 9898

服务端代码:

import com.meta.HtMetaInfoSyncServiceGrpc;
import com.meta.HtMetaSyncRequest;
import com.meta.HtMetaSyncResponse;
import com.meta.SyncType;
import com.util.JsonUtil;
import com.vo.HtMetaClusterInfoVo;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import java.util.List;

/**
 * @author 何永豪
 * @className HtMetaSyncService
 * @description TODO
 * @date 2023/11/6 15:25
 */
@Slf4j
@GrpcService
public class HtMetaSyncService extends HtMetaInfoSyncServiceGrpc.HtMetaInfoSyncServiceImplBase {

    @Override
    public void syncMeta(HtMetaSyncRequest request, StreamObserver<HtMetaSyncResponse> responseObserver) {
        String syncJson = request.getSyncJson();
        log.info("接收到json:{}",syncJson);
        List<HtMetaClusterInfoVo> list = JsonUtil.toList(syncJson, HtMetaClusterInfoVo.class);
        SyncType syncType = request.getSyncType();
        int number = syncType.getNumber();
        log.info("同步类型:{}",number);
        HtMetaSyncResponse syncResponse = HtMetaSyncResponse.newBuilder()
                .setCode("1000")
                .setMsg("同步成功").build();
        responseObserver.onNext(syncResponse);
        responseObserver.onCompleted();
    }

}
客户端:
<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>
    <parent>
        <groupId>com.xiaoshu</groupId>
        <artifactId>grpc-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>grpc-client</artifactId>
    <packaging>jar</packaging>

    <name>grpc-client</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.xiaoshu</groupId>
            <artifactId>grpc-proto</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-client-spring-boot-starter</artifactId>
            <version>${grpc.version}</version>
        </dependency>

    </dependencies>

</project>

yml

server:
  port: 8088

spring:
  application:
    name: local-client

grpc:
  client:
    # gRPC配置的名字,GrpcClient注解会用到
    local-grpc-server:
      # gRPC服务端地址
      address: 'static://127.0.0.1:9898'
      enableKeepAlive: true
      keepAliveWithoutCalls: true
      #认证类型,无加密
      negotiationType: plaintext

客户端stub

import com.meta.HtMetaInfoSyncServiceGrpc;
import com.meta.HtMetaSyncRequest;
import com.meta.HtMetaSyncResponse;
import com.meta.SyncType;
import io.grpc.StatusRuntimeException;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;

/**
 * @author xiaoshu
 */
@Service
public class HtMetaInfoSyncClient {

    @GrpcClient("local-grpc-server")
    private HtMetaInfoSyncServiceGrpc.HtMetaInfoSyncServiceBlockingStub stub;


    public String syncMeta(final String json,final SyncType syncType) {
        try {
            HtMetaSyncResponse htMetaSyncResponse = stub.syncMeta((
                    HtMetaSyncRequest.newBuilder()
                            .setSyncJson(json)
                            .setSyncType(syncType)
                            .build()));
            String code = htMetaSyncResponse.getCode();
            String msg = htMetaSyncResponse.getMsg();
            return code+":"+msg;
        } catch (final StatusRuntimeException e) {
            return "FAILED with " + e.getStatus().getCode().name();
        }
    }

}
实际调用:
@Autowired
private HtMetaInfoSyncClient htMetaInfoSyncClient;

@RequestMapping("/htMetaSync")
public String htMetaSync() {
    String json="";
    return htMetaInfoSyncClient.syncMeta(json, SyncType.ADD);
}

原生集成

<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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.xiaoshuzxc</groupId>
    <artifactId>grpc-native-api</artifactId>
    <packaging>jar</packaging>

    <name>grpc-native-api</name>
    <description>grpc原生api整合方式</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <grpc.version>1.29.0</grpc.version>
        <proto.version>3.12.0</proto.version>
        <netty.tcnative.version>2.0.30.Final</netty.tcnative.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-bom</artifactId>
                <version>${grpc.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.xiaoshu</groupId>
            <artifactId>grpc-proto</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty</artifactId>
        </dependency>

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-tcnative-boringssl-static</artifactId>
            <version>${netty.tcnative.version}</version>
            <scope>runtime</scope>
        </dependency>

    </dependencies>
</project>

import org.springframework.stereotype.Service;
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface GrpcService {

}

启动grpc服务监听:

import com.annotation.GrpcService;
import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyServerBuilder;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContextBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.stream.Stream;

/**
 * @author 何永豪
 * @className GrpcServer
 * @description TODO
 * @date 2023/11/7 15:56
 */
@Slf4j
public class GrpcServer implements CommandLineRunner, DisposableBean {

    private Server server;

    @Resource
    private AbstractApplicationContext applicationContext;

    @Resource
    private GrpcProperties grpcProperties;

    @Override
    public void destroy() {
        stop();
    }

    @Override
    public void run(String... args) throws Exception {
        start();
    }

    private SslContextBuilder getSslContextBuilder(){
        SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(new File(grpcProperties.getServerCertPath()), new File(grpcProperties.getServerPrivateKeyPath()));
        sslContextBuilder.trustManager(new File(grpcProperties.getServerTrustCertPath()));
        sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
        return GrpcSslContexts.configure(sslContextBuilder);
    }


    private void start() throws IOException {
        NettyServerBuilder nettyServerBuilder = NettyServerBuilder
                .forPort(grpcProperties.getPort());
//                .sslContext(getSslContextBuilder().build()
//                        );
        scanBeanWithAnnotation(GrpcService.class, BindableService.class)
                .forEach(e->{
                    BindableService bindableService = applicationContext.getBeanFactory().getBean(e, BindableService.class);
                    nettyServerBuilder.addService(bindableService.bindService());
                });
        server = nettyServerBuilder.build().start();
        log.info("grpc start listen {}",grpcProperties.getPort());
        Thread thread = new Thread(() -> {
            try {
                GrpcServer.this.blockUntilShutdown();
            } catch (InterruptedException e) {
                log.error("grpc server stopped");
                throw new RuntimeException(e);
            }
        });
        thread.setDaemon(false);
        thread.start();
    }

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

    private void blockUntilShutdown() throws InterruptedException {
        if (server !=null ){
            server.awaitTermination();
        }
    }

    private <T> Stream<String> scanBeanWithAnnotation(Class<? extends Annotation> annotionType,Class<T> beanType){
        String[] beanNamesForType = applicationContext.getBeanNamesForType(beanType);
        return Stream.of(beanNamesForType).filter(e->{
            BeanDefinition beanDefinition = applicationContext.getBeanFactory().getBeanDefinition(e);
            Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(annotionType);
            if (beansWithAnnotation.containsKey(e)){
                return true;
            }else if (beanDefinition.getSource() instanceof AnnotatedTypeMetadata){
                return AnnotatedTypeMetadata.class.cast(beanDefinition.getSource()).isAnnotated(annotionType.getName());
            }
            return false;
        });
    }

}

服务端:

@Slf4j
@GrpcService
public class HtMetaSyncService extends HtMetaInfoSyncServiceGrpc.HtMetaInfoSyncServiceImplBase {

    @Override
    public void syncMeta(HtMetaSyncRequest request, StreamObserver<HtMetaSyncResponse> responseObserver) {
        String syncJson = request.getSyncJson();
        log.info("接收到json:{}",syncJson);
        SyncType syncType = request.getSyncType();
        int number = syncType.getNumber();
        log.info("同步类型:{}",number);
        HtMetaSyncResponse syncResponse = HtMetaSyncResponse.newBuilder()
                .setCode("1000")
                .setMsg("同步成功").build();
        responseObserver.onNext(syncResponse);
        responseObserver.onCompleted();
    }

}

客户端

import com.config.GrpcProperties;
import com.meta.HtMetaInfoSyncServiceGrpc;
import com.meta.HtMetaSyncRequest;
import com.meta.HtMetaSyncResponse;
import com.meta.SyncType;
import io.grpc.ManagedChannel;
import io.grpc.StatusRuntimeException;
import io.grpc.netty.NettyChannelBuilder;
import lombok.SneakyThrows;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author xiaoshu
 */
@Component
public class HtMetaInfoSyncClient {

    @Resource
    private GrpcProperties grpcProperties;

    @SneakyThrows
    public String syncMeta(final String json,final SyncType syncType) {
        ManagedChannel channel = null;
        try {
            channel=NettyChannelBuilder.
                    forAddress(grpcProperties.getServerIp(),grpcProperties.getPort())
                    //非加密连接
                    .usePlaintext()
                    //加密
                    //.sslContext(grpcProperties.buildClentSslContext())
                    .build();
            HtMetaInfoSyncServiceGrpc.HtMetaInfoSyncServiceBlockingStub stub = HtMetaInfoSyncServiceGrpc.newBlockingStub(channel);
            HtMetaSyncResponse htMetaSyncResponse = stub.syncMeta((
                    HtMetaSyncRequest.newBuilder()
                            .setSyncJson(json)
                            .setSyncType(syncType)
                            .build()));
            String code = htMetaSyncResponse.getCode();
            String msg = htMetaSyncResponse.getMsg();
            return code+":"+msg;
        } catch (final StatusRuntimeException e) {
            return "FAILED with " + e.getStatus().getCode().name();
        }finally {
            if (Objects.nonNull(channel)){
                channel.shutdown();
            }
        }
    }
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 何永豪
 * @className GrpcConfig
 * @description TODO
 * @date 2023/11/7 16:58
 */
@Configuration
public class GrpcConfig {

    @Bean
    @ConditionalOnProperty(value = "grpc.enable",havingValue = "true",matchIfMissing = true)
    public GrpcServer grpcServer(){
        return new GrpcServer();
    }

}
@Component
@ConfigurationProperties(prefix = "grpc")
@Data
public class GrpcProperties {

    private Integer port;

    private String  serverIp;

    private String serverCertPath;

    private String serverPrivateKeyPath;

    private String serverTrustCertPath;

    private String clientCertPath;

    private String clientCertChainPath;

    private String clientPrivateKeyPath;

    /*public SslContext buildClentSslContext() throws SSLException {
        SslContextBuilder sslContextBuilder = GrpcSslContexts.forClient();
        sslContextBuilder.trustManager(new File(clientCertPath));
        sslContextBuilder.keyManager(new File(clientCertChainPath),new File(clientPrivateKeyPath));
        return sslContextBuilder.build();
    }*/

}
server:
  port: 8077

spring:
  application:
    name: grpc-api

grpc:
  #监听端口
  port: 6100
  #目标IP
  server-ip: 127.0.0.1
  #ssl配置
  server-cert-path: /ca/server/server.crt
  server-private-key-path: /ca/server/server.pem
  server-trust-cert-path: /ca/server/ca.crt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/126850.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【uniapp/uview】Collapse 折叠面板更改右侧小箭头图标

最终效果是这样的&#xff1a; 官方没有给出相关配置项&#xff0c;后来发现小箭头不是 uview 的图标&#xff0c;而是 unicode 编码&#xff0c;具体代码&#xff1a; // 箭头图标 ::v-deep .uicon-arrow-down[data-v-6e20bb40]:before {content: \1f783; }附一个查询其他 u…

机器学习 - 决策树:技术全解与案例实战

目录 一、引言二、决策树基础决策树模型概述构建决策树的关键概念特征选择决策树的生成 决策树的剪枝 三、算法研究进阶提升树和随机森林提升树&#xff08;Boosted Trees&#xff09;随机森林&#xff08;Random Forests&#xff09; 进化算法与决策树决策树结构的进化 多目标…

MeterSphere 任意文件读取漏洞(CVE-2023-25814)

MeterSphere 任意文件读取漏洞&#xff08;CVE-2023-25814&#xff09; 免责声明漏洞描述漏洞影响漏洞危害网络测绘Fofa: title"MeterSphere" 漏洞复现1. 构造poc2. 发送数据包3. 查看文件 免责声明 仅用于技术交流,目的是向相关安全人员展示漏洞利用方式,以便更好地…

亚马逊鲲鹏系统能做什么

亚马逊鲲鹏系统是一款能绕过亚马逊智能检测&#xff0c;完全模拟人类真实行为&#xff0c;通过模拟真实的人流量来帮助你提升你的产品排名&#xff0c;让你的产品出现在搜索首页&#xff0c;从而快速提高你的销售业绩的营销工具&#xff01; 主要的功能有批量注册买家号、AI智能…

Java 并发编程面试题——Condition 接口

目录 1.Condition 接口有什么作用&#xff1f;2.如何使用 Condition&#xff1f;3.Condition 中有哪些常用的方法&#xff1f;4.✨Condition 的底层实现原理是什么&#xff1f;4.1.等待队列4.2.等待4.3.通知 &#xff08;1&#xff09;参考书籍&#xff1a; 《Java 并发编程的艺…

RabbitMQ集群配置以及负载均衡配置

RabbitMQ集群配置以及负载均衡配置 环境配置集群配置安装rabbitmq启动rabbitmq开启远程登录添加用户并且授权用户添加数据存放目录和日志存放目录查看端口拷⻉erlang.cookie将mq-2、mq-3作为内存节点加⼊mq-1节点集群中查看集群状态添加一个新的队列 RabbitMq负载均衡配置-HAPr…

VUE element组件生成的全选框如何获取值

//先声明 const Selection ref([]);//获取 const handleSelectCodeForTicket (val) > {console.log(val);// values.value val;Selection.value [];val.forEach((v) > {Selection.value.push(v);});console.log(Selection.value); }; <el-table selection-change…

《QT从基础到进阶·十七》QCursor鼠标的不同位置坐标获取

一些常用鼠标图形&#xff1a; 鼠标光标相对于整个电脑屏幕的位置&#xff1a;QCursor::pos() 当前光标相对于当前窗口的位置&#xff1a;this->mapFromGlobal(QCursor::pos()) void MainWindow::mouseReleaseEvent(QMouseEvent* event) {QPoint pos event->pos(); …

腾讯云真的是良心云!服务器带宽、CPU、硬盘IO性能大揭秘!

本文将通过对腾讯云服务器CVM S5 4核配置的云服务器进行测试&#xff0c;来评估其在带宽、CPU和硬盘IO性能方面的表现。 在云服务器的并发处理中&#xff0c;带宽是一个重要的因素。经过测试&#xff0c;腾讯云的带宽网络表现非常出色&#xff0c;能够跑满带宽&#xff0c;同时…

使用pymysql工具包连接Python与数据库

目录 一、引言 二、pymysql工具包的安装 三、连接数据库 四、执行SQL语句 1、执行查询语句&#xff1a;cursor.execute(sql) 2、插入数据&#xff1a;cursor.execute(sql, values) 3、更新数据&#xff1a;cursor.execute(sql, values) 4、删除数据&#xff1a;cursor.…

选择CRM系统主要看哪些指标?

很多企业都想选择一款好用的CRM客户管理系统&#xff0c;但是面对众多类型、品牌的CRM却犯了难。下面我们来说说&#xff0c;企业要想选到一款适合自己的、好用的CRM系统&#xff0c;主要看哪些指标&#xff1f;这里有6个步骤&#xff0c;可以帮您做到。 第1步&#xff1a;了解…

深度学习的集体智慧:最新发展综述

一、说明 我们调查了来自复杂系统的想法&#xff0c;如群体智能、自组织和紧急行为&#xff0c;这些想法在机器学习中越来越受欢迎。人工神经网络正在影响我们的日常生活&#xff0c;从执行预测性任务&#xff08;如推荐、面部识别和对象分类&#xff09;到生成任务&#xff08…

if...else绝佳替换方案

目录 方法一&#xff1a;提前 return方法二&#xff1a;枚举方案三&#xff1a;Optional 判空方案四&#xff1a;表驱动法方案五&#xff1a;策略模式 工厂方法方案六&#xff1a;责任链模式方案七&#xff1a;Function 方法一&#xff1a;提前 return 假如有如下代码&#x…

2023年【公路水运工程施工企业安全生产管理人员】复审考试及公路水运工程施工企业安全生产管理人员考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 公路水运工程施工企业安全生产管理人员复审考试根据新公路水运工程施工企业安全生产管理人员考试大纲要求&#xff0c;安全生产模拟考试一点通将公路水运工程施工企业安全生产管理人员模拟考试试题进行汇编&#xff0…

人工智能-卷积神经网络(LeNet)

为了能够应用softmax回归和多层感知机&#xff0c;我们首先将每个大小为\(28\times28\)的图像展平为一个784维的固定长度的一维向量&#xff0c;然后用全连接层对其进行处理。 而现在&#xff0c;我们已经掌握了卷积层的处理方法&#xff0c;我们可以在图像中保留空间结构。 同…

学者观察 | 数字经济中长期发展中的区块链影响力——清华大学柴跃廷

导语 区块链是一种全新的分布式基础架构与计算范式&#xff0c;既能利用非对称加密和冗余分布存储实现信息不可篡改&#xff0c;又可以利用链式数据结构实现数据信息可溯源。当前&#xff0c;区块链技术已成为全球数据交易、金融结算、国际贸易、政务民生等领域的信息基础设施…

vue Sts认证后直传图片到阿里云OSS

后端进行sts认证生成临时身份凭证&#xff0c;前端通过凭证直传图片等文件到OSS中 一 OSS配置 增加用户和角色&#xff0c;创建OSS bucket 1.1 添加用户 登录阿里云管理控制台&#xff0c;右侧头像&#xff0c;进入访问控制 点击左侧导航栏的身份管理的用户&#xff0c;点击…

网络溯源-PSEXEC-简单

题干&#xff1a; 我们的入侵检测系统&#xff08;IDS&#xff09;已发出警报&#xff0c;指示涉及使用PsExec的可疑横向移动活动。为了有效响应此事件&#xff0c;您作为 SOC 分析师的角色是分析存储在 PCAP 文件中的捕获网络流量。 攻击者首次攻击成功的计算机源网络IP地址…

23款奔驰GLC260L升级香氛负离子 感受清香四溢

香氛负离子系统是由香氛系统和负离子发生器组成的一套配置&#xff0c;也可以单独加装香氛系统或者是负离子发生器&#xff0c;香氛的主要作用就是通过香氛外壳吸收原厂的香水再通过空调管输送到内饰中&#xff0c;而负离子的作用就是安装在空气管中通过释放电离子来打击空气中…

记录一次数据库内存占满

一&#xff0c;背景及表现 用户普遍反馈业务功能&#xff0c;无法加载出数据&#xff0c;服务挂了 二&#xff0c;数据库指标 三&#xff0c;排查方反馈 排查方反馈&#xff1a;查全量数据导致的&#xff0c;就是没查出来但是一直在查 四&#xff0c;分析 1.应用服务器问题…