gRpc的四种通信方式详细介绍

news2025/1/15 13:10:30

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁
🦄 博客首页——猫头虎的博客🎐
🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐
🌊 《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大小厂~💐

🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

文章目录

  • gRpc的四种通信方式
    • 四种通信方式
    • 简单RPC(一元RPC)
      • 特点
      • 语法
    • 服务端流式RPC
      • 特点
      • 使用场景
      • 语法
      • 关键代码
    • 客户端流式RPC
      • 应用场景
      • proto
      • 开发
    • 双向流式RPC
      • 应用场景
      • 编码
    • **总结**:
    • **参考资料**:
  • 原创声明

gRpc的四种通信方式

在这里插入图片描述

四种通信方式

  1. 简单rpc 一元rpc (Unary RPC)
  2. 服务端流式RPC (Server Streaming RPC)
  3. 客户端流式RPC (Client Streaming RPC)
  4. 双向流RPC (Bi-directional Stream RPC)

摘要
本文详细介绍了gRpc的四种主要通信方式,包括简单RPC、服务端流式RPC、客户端流式RPC和双向流式RPC。每种方式都有其特点和应用场景,以及相应的代码实现。

导语
在分布式系统中,通信是至关重要的。gRpc作为一个高性能、开源和通用的RPC框架,为我们提供了多种通信方式。那么,这些通信方式都有哪些特点和应用场景呢?让我们一起深入了解。

引言
“通信是连接分布式系统的桥梁,而gRpc则为我们提供了这座桥梁的多种形式。从简单的一对一通信到复杂的双向流通信,gRpc都能为我们提供稳定和高效的解决方案。”

简单RPC(一元RPC)

  1. 第一个RPC程序,实际上就是一元RPC

特点

当client发起调用后,提交数据,并且等待 服务端响应。开发过程中,主要采用就是一元RPC的这种通信方式。

在这里插入图片描述

语法

service HelloService{
  rpc hello(HelloRequest) returns (HelloResponse){}
  rpc hello1(HelloRequest1) returns (HelloResponse1){}
}

服务端流式RPC

一个请求对象,服务端可以回传多个结果对象。

特点

在这里插入图片描述

使用场景

client --------> Server
股票标号
<-------
某一个时刻的 股票的行情

语法

service HelloService{
  rpc hello(HelloRequest) returns (stream HelloResponse){}
  rpc hello1(HelloRequest1) returns (HelloResponse1){}
}

关键代码

服务端
public void c2ss(HelloProto.HelloRequest request, StreamObserver<HelloProto.HelloResponse> responseObserver) {
        //1 接受client的请求参数
        String name = request.getName();
        //2 做业务处理
        System.out.println("name = " + name);
        //3 根据业务处理的结果,提供响应
        for (int i = 0; i < 9; i++) {
            HelloProto.HelloResponse.Builder builder = HelloProto.HelloResponse.newBuilder();
            builder.setResult("处理的结果 " + i);
            HelloProto.HelloResponse helloResponse = builder.build();

            responseObserver.onNext(helloResponse);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        responseObserver.onCompleted();
    }
客户端
public class GprcClient3 {
    public static void main(String[] args) {
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9000).usePlaintext().build();
        try {
            HelloServiceGrpc.HelloServiceBlockingStub helloService = HelloServiceGrpc.newBlockingStub(managedChannel);

            HelloProto.HelloRequest.Builder builder = HelloProto.HelloRequest.newBuilder();
            builder.setName("sunshuai");
            HelloProto.HelloRequest helloRequest = builder.build();
            Iterator<HelloProto.HelloResponse> helloResponseIterator = helloService.c2ss(helloRequest);
            while (helloResponseIterator.hasNext()) {
                HelloProto.HelloResponse helloResponse = helloResponseIterator.next();
                System.out.println("helloResponse.getResult() = " + helloResponse.getResult());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            managedChannel.shutdown();
        }
    }
}

监听 异步方式 处理服务端流式RPC的开发
1. api
2. 服务端 
3. 客户端 
   public class GrpcClient4 {
    public static void main(String[] args) {
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9000).usePlaintext().build();

        try {

            HelloServiceGrpc.HelloServiceStub helloService = HelloServiceGrpc.newStub(managedChannel);

            HelloProto.HelloRequest.Builder builder = HelloProto.HelloRequest.newBuilder();
            builder.setName("xiaohei");
            HelloProto.HelloRequest helloRequest = builder.build();

            helloService.c2ss(helloRequest, new StreamObserver<HelloProto.HelloResponse>() {
                @Override
                public void onNext(HelloProto.HelloResponse value) {
                    //服务端 响应了 一个消息后,需要立即处理的话。把代码写在这个方法中。
                    System.out.println("服务端每一次响应的信息 " + value.getResult());
                }

                @Override
                public void onError(Throwable t) {

                }

                @Override
                public void onCompleted() {
                    //需要把服务端 响应的所有数据 拿到后,在进行业务处理。
                    System.out.println("服务端响应结束 后续可以根据需要 在这里统一处理服务端响应的所有内容");
                }
            });

            managedChannel.awaitTermination(12, TimeUnit.SECONDS);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            managedChannel.shutdown();
        }
    }
}

客户端流式RPC

客户端发送多个请求对象,服务端只返回一个结果。

在这里插入图片描述

应用场景

IOT(物联网 【传感器】) 向服务端 发送数据

proto

rpc cs2s(stream HelloRequest) returns (HelloResponse){}

开发

1. api
   rpc cs2s(stream HelloRequest) returns (HelloResponse){}
2. 服务端开发
   public StreamObserver<HelloProto.HelloRequest> cs2s(StreamObserver<HelloProto.HelloResponse> responseObserver) {
        return new StreamObserver<HelloProto.HelloRequest>() {
            @Override
            public void onNext(HelloProto.HelloRequest value) {
                System.out.println("接受到了client发送一条消息 " + value.getName());
            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onCompleted() {
                System.out.println("client的所有消息 都发送到了 服务端 ....");

                //提供响应:响应的目的:当接受了全部client提交的信息,并处理后,提供相应
                HelloProto.HelloResponse.Builder builder = HelloProto.HelloResponse.newBuilder();
                builder.setResult("this is result");
                HelloProto.HelloResponse helloResponse = builder.build();

                responseObserver.onNext(helloResponse);
                responseObserver.onCompleted();
            }
        };
    }
3. 客户端开发
   public class GrpcClient5 {
    public static void main(String[] args) {
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9000).usePlaintext().build();
        try {
            HelloServiceGrpc.HelloServiceStub helloService = HelloServiceGrpc.newStub(managedChannel);

            StreamObserver<HelloProto.HelloRequest> helloRequestStreamObserver = helloService.cs2s(new StreamObserver<HelloProto.HelloResponse>() {
                @Override
                public void onNext(HelloProto.HelloResponse value) {
                    // 监控响应
                    System.out.println("服务端 响应 数据内容为 " + value.getResult());

                }

                @Override
                public void onError(Throwable t) {

                }

                @Override
                public void onCompleted() {
                    System.out.println("服务端响应结束 ... ");
                }
            });

            //客户端 发送数据 到服务端  多条数据 ,不定时...
            for (int i = 0; i < 10; i++) {
                HelloProto.HelloRequest.Builder builder = HelloProto.HelloRequest.newBuilder();
                builder.setName("sunshuai " + i);
                HelloProto.HelloRequest helloRequest = builder.build();

                helloRequestStreamObserver.onNext(helloRequest);
                Thread.sleep(1000);
            }

            helloRequestStreamObserver.onCompleted();

            managedChannel.awaitTermination(12, TimeUnit.SECONDS);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            managedChannel.shutdown();
        }
    }
}

双向流式RPC

客户端可以发送多个请求消息,服务端响应多个响应消息。

在这里插入图片描述

应用场景

聊天室

编码

 1. api
    rpc cs2ss(stream HelloRequest) returns (stream HelloResponse){}
2. 服务端
    public StreamObserver<HelloProto.HelloRequest> cs2ss(StreamObserver<HelloProto.HelloResponse> responseObserver) {
         return new StreamObserver<HelloProto.HelloRequest>() {
             @Override
             public void onNext(HelloProto.HelloRequest value) {
                 System.out.println("接受到client 提交的消息 "+value.getName());
                 responseObserver.onNext(HelloProto.HelloResponse.newBuilder().setResult("response "+value.getName()+" result ").build());
             }

             @Override
             public void onError(Throwable t) {

             }

             @Override
             public void onCompleted() {
                 System.out.println("接受到了所有的请求消息 ... ");
                 responseObserver.onCompleted();
             }
         };
    }
3. 客户端
  public class GrpcClient6 {
    public static void main(String[] args) {
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9000).usePlaintext().build();
        try {
            HelloServiceGrpc.HelloServiceStub helloService = HelloServiceGrpc.newStub(managedChannel);

            StreamObserver<HelloProto.HelloRequest> helloRequestStreamObserver = helloService.cs2ss(new StreamObserver<HelloProto.HelloResponse>() {
                @Override
                public void onNext(HelloProto.HelloResponse value) {
                    System.out.println("响应的结果 "+value.getResult());
                }

                @Override
                public void onError(Throwable t) {

                }

                @Override
                public void onCompleted() {
                    System.out.println("响应全部结束...");
                }
            });


            for (int i = 0; i < 10; i++) {
                helloRequestStreamObserver.onNext(HelloProto.HelloRequest.newBuilder().setName("sunshuai " + i).build());
            }
            helloRequestStreamObserver.onCompleted();

            managedChannel.awaitTermination(12, TimeUnit.SECONDS);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            managedChannel.shutdown();
        }
    }
}

这篇博客简要介绍了gRpc的四种通信方式,包括简单RPC、服务端流式RPC、客户端流式RPC和双向流式RPC,并给出了每种方式的特点、使用场景、语法和关键代码。希望对读者有所帮助。

总结

gRpc的四种通信方式为分布式系统提供了强大的支持。简单RPC适用于常规的请求-响应模式,服务端流式RPC和客户端流式RPC分别允许服务端和客户端发送多个消息,而双向流式RPC则支持双方的双向通信。了解这些通信方式及其应用场景,可以帮助我们更好地设计和实现分布式系统。

参考资料

  1. gRpc官方文档:https://grpc.io/docs/
  2. “Mastering gRpc” by Alex Konrad.
  3. “Distributed Systems with gRpc” by Sarah Allen.

在这里插入图片描述

原创声明

======= ·

  • 原创作者: 猫头虎

作者wx: [ libin9iOak ]

学习复习

本文为原创文章,版权归作者所有。未经许可,禁止转载、复制或引用。

作者保证信息真实可靠,但不对准确性和完整性承担责任

未经许可,禁止商业用途。

如有疑问或建议,请联系作者。

感谢您的支持与尊重。

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

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

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

相关文章

python+selenium的web自动化之针对上传操作的实现方案

一、关于上传操作 ​ 上传有两种情况&#xff1a; 如果是input可以直接输入路径的&#xff0c;那么直接使用send_keys(文件路径)输入路径即可&#xff1b; 非input标签的上传&#xff0c;则需要借助第三方工具&#xff1a;第三方库 pywin32、第三方工具pyautogui等等。 ​ 那…

揭开路由协议隐藏的风险

路由协议在互联网和基于其的服务的运行中发挥着至关重要的作用。然而&#xff0c;许多这些协议的开发都没有考虑到安全问题。 例如&#xff0c;边界网关协议 (BGP) 最初并未考虑对等点之间发生攻击的可能性。过去几十年来&#xff0c;BGP 中的起源和路径验证已投入了大量工作。…

JUC--阻塞队列

目录 问题引出 一.单端阻塞队列&#xff08;BlockingQueue&#xff09; 二.双端阻塞队列&#xff08;BlockingDeque&#xff09; 三.延迟队列&#xff08;DelayQueue&#xff09; 问题引出 由于实现消费者-生产者模型&#xff0c;每一次实现都比较麻烦&#xff0c;比如sych…

2023河南萌新联赛第(六)场:河南理工大学 B - 这是dp题吗

2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学 B - 这是dp题吗 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld 题目描述 小l同学非常喜欢三角形&#x…

淘宝商品优惠券详情item_get_app-获得淘宝app商品详情原数据

item_get_app-获得淘宝app商品详情原数据 taobao.item_get_app 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;调用API接口入口secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09…

等级发布/查询平台

在传统的教学模式下&#xff0c;老师们需要手动把成绩挨个私发给学生家长&#xff0c;这不仅费时费力&#xff0c;还容易出现错误。然而&#xff0c;随着科技的不断发展&#xff0c;易查分系统的出现为教师提供了一个高效准确的成绩发布工具。 系统优势 1. 高效便捷&#xff1a…

【数据结构与算法】弗洛伊德算法

弗洛伊德算法 介绍 和 Dijkstra 算法一样&#xff0c;弗洛伊德&#xff08;Floyd&#xff09;算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。弗洛伊德算法计算图中各个顶点之间的最短路径。迪杰斯特拉算法用于计算图中某一个顶点到其他顶点的最短路径。弗洛伊德算…

贪吃蛇大作战技术报告(JAVA)

完整作品见链接&#xff1a;JAVA贪吃蛇大作战大作业_Java贪吃蛇如何实现向左不能向右资源-CSDN文库 猫猫大作战技术报告 1、项目概述 本项目的编译环境为jdk-19&#xff0c;用到的编译器为Eclipse&#xff0c;采用图形化编程&#xff0c;基于JAVA的Swing库进行界面的绘制&…

解决Pandas KeyError: “None of [Index([...])] are in the [columns]“问题

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

使用ctcloss训练矩阵生成目标字符串

首先我们需要明确 c t c l o s s ctcloss ctcloss是用来做什么的。比如说我们要生成的目标字符串长度为 l l l&#xff0c;而这个字符串包含 k k k个字符&#xff0c;字符串允许的最大长度为 L L L&#xff0c;这里我们认为一个位置是一个时间步&#xff0c;就是一拍&#xff0…

PyTorch三种主流模型构建方式:nn.Sequential、nn.Module子类、nn.Module容器开发实践,以真实烟雾识别场景数据为例

Keras和PyTorch是两个常用的深度学习框架&#xff0c;它们都提供了用于构建和训练神经网络的高级API。 Keras: Keras是一个高级神经网络API&#xff0c;可以在多个底层深度学习框架上运行&#xff0c;如TensorFlow和CNTK。以下是Keras的特点和优点&#xff1a; 优点&#xff…

解决git上传远程仓库时的最大文件大小限制

git默认限制最大的单文件100M&#xff0c;当某个文件到达50M时会给你提示。解决办法如下 首先&#xff0c;打开终端&#xff0c;进入项目所在的文件夹&#xff1b; 输入命令&#xff1a;git config http.postBuffer 524288000 执行完上面的语句后输入&#xff1a;git config…

Stable Diffusion 系列教程 | 图生图基础

前段时间有一个风靡全网的真人转漫画风格&#xff0c;受到了大家的喜欢 而在SD里&#xff0c;就可以通过图生图来实现类似的效果 当然图生图还有更好玩的应用&#xff0c;我们一点一点来探索 首先我们来简单进行一下图生图的这一个实践---真人转动漫 1. 图生图基本界面 和…

代码之美:探索可维护性的核心与实践

为什么可维护性如此重要 项目的长期健康 在软件开发的早期阶段&#xff0c;团队可能会对代码的可维护性不太重视&#xff0c;因为他们更关心的是功能的快速交付。但随着时间的推移&#xff0c;随着代码库的增长和复杂性的增加&#xff0c;不重视代码的可维护性可能会导致严重的…

docker使用安装教程

docker使用安装教程 一、docker安装及下载二、使用教程2.1 镜像2.2 容器2.3 docker安装Redis 一、docker安装及下载 一、安装 安装执行命令&#xff1a;curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 二、启停常用命令 启动docker,执行命令&#xf…

分支和循环语句-C语言(初阶)

目录 一、什么是语句 二、分支语句 2.1 if语句 2.2 switch语句 三、循环语句 3.1 while循环 3.2 for循环 3.3 do...while循环 一、什么是语句 C语言语句有五类&#xff1a;表达式语句、函数调用语句、控制语句、复合语句、空语句。 控制语句用于控制程序的执行流程&#xff0…

在vue3+ts+vite中使用svg图片

目录 前言 步骤 1.安装svg-sprite-loader,这里使用的是6.0.11版本 2.项目的svg图片存放在src/icons下&#xff0c;我们在这里创建两个文件index.ts和index.vue&#xff08;在哪创建和文件名字并没有任何要求&#xff09; 3.在index.ts中加入下列代码(如果报错找不到fs模块请…

Redis的基本操作

文章目录 1.Redis简介2.Redis的常用数据类型3.Redis的常用命令1.字符串操作命令2.哈希操作命令3.列表操作命令4.集合操作命令5.有序集合操作命令6.通用操作命令 4.Springboot配置Redis1.导入SpringDataRedis的Maven坐标2.配置Redis的数据源3.编写配置类&#xff0c;创还能Redis…

ubuntu修改默认文件权限umask

最近在使用ubuntu的过程中发现一个问题&#xff1a; 环境是AWS EC2&#xff0c;登录用户ubuntu&#xff0c;系统默认的umask是027&#xff0c;修改/etc/profile文件中umask 027为022后&#xff0c;发现从ubuntu用户sudo su过去root用户登录查询到的umask还是027&#xff0c;而…

2023-8-22 单调栈

题目链接&#xff1a;单调栈 #include <iostream>using namespace std;const int N 100010;int n; int stk[N], tt;int main() {cin >> n;for(int i 0; i < n; i ){int x;cin >> x;while(tt && stk[tt] > x) tt--;if(tt) cout << st…