高性能远程通信框架grpc基本使用

news2024/11/23 21:50:22

文章目录

  • 一、了解grpc
  • 二、关于protobuf
  • 三、试玩grpc
    • 3.1整个工程目录
    • 3.2 proto文件编写
    • 3.3 使用maven protobuf插件转换.proto文件
    • 3.4 Grpc服务端业务实现类
    • 3.5 pom参考
    • 3.6 grpc client调用

一、了解grpc

谷歌开源远程进程调用框架,支持多语言系统间通信,适用于各种分布式系统,使用http2协议并使用protobuf系列化通信数据,高性能。nacos2开始也集成了grpc,用于nacos server与nacos client间通信。grpc还支持了client-server双向流,两个流可独立不阻塞进行连续读写。

二、关于protobuf

如果只是protobuf作为序列化方案,建议使用protostuff(基于protobuf),不用写proto文件。grpc官方的quickstart都是直接使用protobuf,故这里暂不研究是否有grpc+protostuff方案。Java 有maven插件进行proto文件生成Java文件,故不用单独去安装proto了,但proto基本语法还得了解。

三、试玩grpc

官方的quickstart不是基于springboot的,故这里就参考这位大佬的JAVA使用gRPC
,为方便使用,这里server,client都在同一个工程里。如果要分开,则在独立项目中引入grpc-client-spring-boot-starter 等依赖并,并copy需要的类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,UserServiceGrpcprotobuf: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 pom参考

springboot3有点问题,暂用2.7.9版本springboot

<?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 client调用

  • 基于grpc server的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 server (yml里配置了URL等)。这里使用定时任务来触发调度。 注意注入的“userClient”需要与yml 自定义的client名一致(如果调用多个grpc server,这个自定义名就是用来区别调用哪个grpc server滴)。
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());
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百分点科技跻身中国智慧应急人工智能解决方案市场前三

近日&#xff0c; 全球领先的IT市场研究和咨询公司IDC发布了《中国智慧应急解决方案市场份额&#xff0c;2022》报告&#xff0c;数据显示&#xff0c;2022年中国智慧应急整体市场为104亿元人民币。其中&#xff0c;智慧应急人工智能解决方案子市场备受关注&#xff0c;百分点科…

小主机折腾记16

7月折腾了 1.2500s&#xff0c;2550k&#xff0c;e3 1225的性能测试 结果如下图 总结如下&#xff1a; a.2500s e3 1225 2390t 差别不大 b.1333频率相对1066频率内存提升12%左右 c.为什么少了2550k&#xff0c;因为装上去风扇尬转&#xff0c;没画面&#xff0c;我猜是因为…

Shell脚本学习-Shell函数

函数的作用就是将程序里多次被调用的相同代码组合起来&#xff08;函数体&#xff09;&#xff0c;并为其取一个名字&#xff0c;即函数名。其他所有想重复调用这部分代码的地方都只需要调用这个名字就可以了。当需要修改这部分代码时候&#xff0c;只需要修改函数体内的这部分…

【网络编程】select

主旨思想 首先要构造一个关于文件描述符的列表&#xff0c;将要监听的文件描述符添加到该列表中 调用一个系统函数(select)&#xff0c;监听该列表中的文件描述符&#xff0c;直到这些描述符中的一个或者多个进行I/O操作时&#xff0c;该函数才返回 这个函数是阻塞函数对文件描…

vue 图片回显标签

第一种 <el-form-item label"打款银行回单"><image-preview :src"form.bankreceiptUrl" :width"120" :height"120"/></el-form-item>// 值为 https://t11.baidu.com/it/app106&fJPEG&fm30&fmtauto&…

一篇五分生信临床模型预测文章代码复现——Figure 10.机制及肿瘤免疫浸润(二)

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

语音合成是什么?如何进行语音合成TTS数据采集?

我们在上一篇讲到语音数据采集分为常见的两种语音数据采集类型&#xff0c;一个是语音识别数据&#xff08;ASR&#xff09;&#xff0c;另一个是语音合成&#xff08;TTS&#xff09;。这一期中&#xff0c;我们将介绍语音合成技术是什么&#xff0c;如何采集语音合成数据和制…

【有趣的设计模式】23 种设计模式详解和场景分析

前言 七大设计原则 1、单一原则&#xff1a;一个类只负责一个职责 2、开闭原则&#xff1a;对修改关闭&#xff0c;对扩展开放 3、里氏替换原则&#xff1a;不要破坏继承关系 4、接口隔离原则&#xff1a;暴露最小接口&#xff0c;避免接口过于臃肿 5、依赖倒置原则&#xff1…

完美解决ubuntu系统QtCreator无法输入中文

在Ubuntu18 上安装搜狗输入法&#xff0c;启用fcitx输入系统之后Qt Creator 无法输入中文&#xff0c;原因是缺少fcitx的支持库libfcitxplatforminputcontextplugin.so。解决办法 1 查找是否安装相关库 $ dpkg -L fcitx-frontend-qt5 | grep .so /usr/lib/x86_64-linux-gnu/qt…

语义检索系统【二】:基于无监督训练SimCSE+In-batch Negatives策略有监督训练的语义索引召回

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

//编写程序数一下 1到 100 的所有整数中出现多少个数字9

//编写程序数一下 1到 100 的所有整数中出现多少个数字9 int main() {int i;int count 0;//用来计数for (int i 1; i < 100; i) {if (i % 10 9 || i / 10 9)count;}printf("1到 100 的所有整数中出现%d个数字9\n", count);

[openCV]基于拟合中线的智能车巡线方案V1

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表"""newDir d…

Day10-NodeJS和NPM配置

Day10-NodeJS和NPM 一 Nodejs 1 简介 Nodejs学习中文网:https://www.nodeapp.cn/synopsis.html Nodejs的官网:https://nodejs.org/ 概念:Nodejs是JavaScript的服务端运行环境.Nodejs不是框架,也不是编程语言,就是一个运行环境. Nodejs是基于chrome V8引擎开发的一套js代码…

mac电脑访问windows共享文件夹连接不上(设置445端口)

前提&#xff1a;首先需要保证mac和windows都在同一局域网内&#xff0c;如果不在肯定是连不上的&#xff0c;就不用往下看了。 事情是这样的&#xff0c;公司入职发了mac电脑&#xff0c;但是我是window重度用户&#xff0c;在折腾mac的过程中&#xff0c;有许多文件需要从wi…

当系统接口要加入新方法时,我真后悔没有早点学学Java设计模式

假设系统中有一个接口&#xff0c;这个接口已经被10个实现类实现了&#xff0c;突然有一天&#xff0c;新的需求来了&#xff0c;其中5个实现类需要实现同一个方法。然后你就在接口中添加了这个方法的定义&#xff0c;想着一切都很完美。 当你在接口和其中5个实现类中加完这个…

java(Collection类)

文章目录 Collection接口继承树Collection接口及方法判断删除其它 Iterator(迭代器)接口迭代器的执行原理 foreach循环Collection子接口1&#xff1a;ListList接口特点List接口方法List接口主要实现类&#xff1a;ArrayListList的实现类之二&#xff1a;LinkedListList的实现类…

【python】我用python写了一个可以批量查询文章质量分的小项目(纯python、flask+html、打包成exe文件)

web 效果预览&#xff1a; 文章目录 一、API 分析1.1 质量分查询1.2 文章url获取 二、代码实现2.1 Python2.11 分步实现2.12 一步完成2.13 完整代码 2.2 python html2.21 在本地运行2.22 打打包成exe文件2.23 部署到服务器 一、API 分析 1.1 质量分查询 先去质量查询地址&a…

处理nacos、tomcat、nginx日志增长过快问题

1.nacos日志清理 修改nacos-logback.xml 将日志级别改为error级&#xff0c;减少info级日志产生量 将<maxHistory>调整为2以下&#xff0c;将 <totalSizeCap>调整为2GB左右 比如&#xff1a; [rootiZ0jlapur4hqjezy8waee0Z logs]# ll -h total 2.1G -rw-r--r-…

mysql忘记密码重置密码步骤

1.使用管理员权限打开cmd窗口&#xff0c;winr后输入cmd&#xff0c;然后按CtrlShiftEnter. 2.停止mysql服务&#xff0c;如上图net stop mysql 3.找到mysql安装目录下的my.ini文件&#xff0c;使用管理员权限打开 4.在[mysqld]下面新增一行skip-grant-tables 5.启动mysql服务…

新的恶意软件 WikiLoader 针对意大利组织

研究人员发现了一种新的恶意软件&#xff0c;名为 WikiLoader 恶意软件。之所以这样命名&#xff0c;是因为它向维基百科发出请求&#xff0c;希望得到内容中包含 "The Free "字符串的响应。 WikiLoader 恶意软件的主要目标是意大利企业及组织。 WikiLoader 是一种…