GRPC CPP 开发单向Stream服务器

news2025/1/12 8:44:27

 上周提到我们要给llama.cpp增加一个grpc入口,这是最终成果仓库,等待进一步测试后提交合并。

今天讲讲GRPC CPP开发的麻烦事情。

参考文档

Quick start | C++ | gRPC,参考文档就是官方的这篇文档了,安装grpc可以参考我上一篇文章,GRPC C++ windows下的简易安装方法icon-default.png?t=N4P3https://blog.csdn.net/baijiafan/article/details/130935982?spm=1001.2014.3001.5501

可以看的示例仓库

动手前其实没有想到grpc cpp开发和golang差这么多,下面是我主要参考的两个例子,都是官方库里的例子,但具体目录不同。

grpc/examples/cpp/helloworld at master · grpc/grpc · GitHubicon-default.png?t=N4P3https://github.com/grpc/grpc/tree/master/examples/cpp/helloworld

example下的这个例子,是入门的例子,对应的proto是

grpc/helloworld.proto,这个例子作为第一次做CPP的GRPC编程入口可以,先可以用来了解基础的架构。如果只是用简单的调用模式,应该就足够了。

但是要做stream还不太够

stream要看对应的hellostreamingworld.proto,stream版本的示例是个双向stream,对应有两个版本的实现:

async版本

使用async api,这个api的详细介绍在下文,参考greeter_async_***的实现,这个async的实现,说实话,我没怎么看懂,似乎把很多GRPC底层的状态变化都交给了上层处理,过程中遇到了几次搞不清楚的状况后,被我抛弃了,我也不建议使用C++的同学参考。

Asynchronous-API tutorial | C++ | gRPC

callback版本

使用callback api,这是个2021年提交的proporal对应的实现方式,我个人觉得更为简单,逻辑更为清楚。

proposal/L67-cpp-callback-api.md at master · grpc/proposal · GitHub

这个版本的实现参考greeter_callback_*的实现即可,他把主要的流程隐藏了,对于实现方只需要实现对应的callback函数即可,整体逻辑性更强。

单向stream的实现方式

如果是双向stream,参考上面的示例应该差不多了,但是单向的还不行,上面的例子还不行。下面是官方库里另一个目录的示例,可以参考,里面的代码很详细。

grpc/test_service_impl.cc at master · grpc/grpc · GitHub

因为我们是单向stream,我下面详细讲讲单向的写法

单向stream写法

对应定义如下:

service LlamaGoService {
    rpc Answer(Job) returns (stream Output){}
}

主要的代码部分包括:

启动服务

void RunServer(uint16_t port, LlamaServerContext *llama)
{
  //监听地址
  std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
  //对应的service的实现类
  LlamaServiceImpl service(llama);
  //这个可选
  grpc::EnableDefaultHealthCheckService(true);
  ServerBuilder builder;
  //去掉了tls检查,生产版本请修改
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  //注册服务
  builder.RegisterService(&service);
  // 启动五福
  std::unique_ptr<Server> server(builder.BuildAndStart());
  std::cout << "Server listening on " << server_address << std::endl;
  //监听服务
  server->Wait();
}

上述代码中,主要就是启动服务,并把具体的service逻辑指向了一个具体的实现类LLamaServiceImpl。

LLamaServiceImpl实现类


class LlamaServiceImpl final : public LlamaGoService::CallbackService
{

  class Reactor : public grpc::ServerWriteReactor<Output>
  {
  public:
    Reactor(CallbackServerContext *ctx, const Job *request)
        : ctx_(ctx), request_(request), 
    {
      if (...) //正常情况
      {
        NextWrite();
      }
      else
      {
        Finish(grpc::Status::OK);
      }
    }
    void OnDone() override
    {
      delete this;
    }
    void OnWriteDone(bool /*ok*/) override
    {
      NextWrite();
    }
    void OnCancel() override
    {
      FinishOnce(Status::CANCELLED);
    }

  private:
    CallbackServerContext *const ctx_;
    const Job *const request_;
    std::mutex finish_mu_;
    bool finished_{false};
    Output response;

    void NextWrite()
    {
      if (not_finish)
      {
        std::lock_guard<std::mutex> l(finish_mu_);
        //设置业务内容
        response.set_output(result);
        StartWrite(&response);
      }
      else
      {
        {
          std::lock_guard<std::mutex>
              l(finish_mu_);
          if (!finished_)
          {
            response.set_status(llama::Status::FINISHED);
            StartWriteLast(&response, grpc::WriteOptions());
          }
        }
        FinishOnce(Status::OK);
      }
    }

    void FinishOnce(const Status &s)
    {
      std::lock_guard<std::mutex> l(finish_mu_);
      if (!finished_)
      {
        Finish(s);
        finished_ = true;
      }
    }
  };

public:
  LlamaServiceImpl()
  {
  }

  ServerWriteReactor<Output> *Answer(
      CallbackServerContext *context, const Job *request)
  {
    Reactor *reactor = new Reactor(context, request);
    return reactor;
  }

private:
};

上面这个代码可以作为单向s2c stream的一个参考实现,他主要包含两个部分,一个是主类LlamaServiceImpl,主要的功能是在客户端调用对应的函数(这里是Answer的时候,初始化一个Reactor类),这个类必须是单向s2c stream要求的ServerWriteReactor<T>的派生类。

第二个类Reactor是单向s2c stream实现的主要功能类。这个类的功能逻辑实际是通过不断地调用StartWrite来实现异步消息发送:

 初始化函数调用一次NextWrite之后就返回自身给grpc框架,grpc框架完成这次stream消息发送后,掉Reactor的OnWriteDone函数,告诉业务类,上次消息写完了,这时业务判断是否写完,如果没有,继续调NextWrite,继续写,然后继续回调,依此循环。

按我们踩坑的经验,还有个有意思的地方,可能是太久不写C++,对变量生命周期有误解,NextWrite里调用StartWrite的response不能是函数类声明变量,必须是类成员变量。指针或对象都可以。但是如果参数传的是函数内声明变量,就无法正常发送消息。

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

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

相关文章

Pycharm:通过git拉取仓库代码并创建项目环境

一、使用pycharm打开空的文件夹 使用菜单栏&#xff1a;在 PyCharm 的菜单栏中&#xff0c;选择 "File"&#xff08;文件&#xff09;菜单&#xff0c;然后选择 "Open"&#xff08;打开&#xff09;或 "Open Folder"&#xff08;打开文件夹&…

Hive3.1.3

文章目录 1、Hive入门1.1 Hive简介1.2 Hive本质1.3 Hive架构原理 2、Hive安装2.1 Hive安装地址2.2 Hive安装部署2.2.1 安装Hive(最小化)2.2.2 启动并使用Hive 2.3 MySQL安装2.3.1 安装MySQL2.3.2 配置MySQL 2.4 配置Hive元数据存储到MySQL2.4.1 配置元数据到MySQL2.4.2 验证元数…

校验表格中的多个表单

要实现的效果是: 点击保存回校验当前页面的所有输入框 首先 分成两个上下两个子组件, 上面的子组件是一个表单包括规则名称和区域 下面的子组件是一个表格,表格可以是多行的,需要校验每一行的输入框 父组件调用两个子组件的校验方法, 第一个子组件可以直接校验,第二个子组件在…

深度学习笔记之循环神经网络(十)基于循环神经网络模型的简单示例

深度学习笔记之循环神经网络——基于循环神经网络模型的简单示例 引言文本表征&#xff1a; One-hot \text{One-hot} One-hot向量简单示例:文本序列的预测任务数据预处理过程生成文本数据遍历数据集&#xff0c;构建字典抓取数据&#xff0c;创建训练样本、标签字符特征与数字特…

Uni-app学习从0到1开发一个app——(2)windowns环境搭配

文章目录 0 引入1、使用HBuilderX构建工程2、使用vscode2.1 官方推荐的使用2.2 如何使用 3、总结 0 引入 工欲善其事必先利其器介绍两种开发小程序的方法&#xff0c;个人倾向于第一种&#xff0c;后续演示的的工程也是基于前者&#xff0c;毕竟官方的更有说服力。 1、使用HBu…

基于yolov5开发构建枪支刀具等危险物品检测识别系统

安全始终是重如泰山的事情&#xff0c;安全事件如果能够做到早发现早制止可能结果就会完全不一样了&#xff0c;本文的核心目的很简单&#xff0c;就是想基于目标检测模型来尝试构建枪支刀具等危险物品检测识别系统&#xff0c;希望基于人工智能手段来打击犯罪行为&#xff0c;…

【JavaSE】Java基础语法(四十三):反射

文章目录 概述&#xff1a;1. java.lang.Class1.1 获取 Class 对象1.2 通过反射创建对象1.3 通过反射获取类的属性、方法和注解等1.3.1 反射获取构造方法1.3.2 反射通过构造器创建对象1.3.3 反射获取成员方法1.3.4 反射获取属性 2. 工具类操作3. 反射是如何破坏单例模式的4. 反…

linux0.12-12-2-buffer

基本上看完赵老师中文解释&#xff0c;都可以自己写这部分的代码。 [622页] 12-2 buffer.c程序 从本节起&#xff0c;我们对fs/目录下的程序逐一进行说明和注释。按照本章第2节中的描述&#xff0c; 本章的程序可以被分成4个部分&#xff1a; 高速缓冲管理&#xff1b; 文件…

基于ATC89C51单片机的超市临时储物柜密码锁设计

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87855870?spm=1001.2014.3001.5503 源码获取 摘 要 随着微机测量和控制技术的迅速发展与广泛应用,以单片机为核心的电子密码锁的设计研发与应用在很大程度上改善了人们的…

windows 部署多个tomcat

去官网下载tomcat&#xff0c;地址&#xff1a;Apache Tomcat - Apache Tomcat 8 Software Downloads 选择对应的版本下载&#xff0c;下载完成后&#xff0c;直接解压文件&#xff0c; 修改第二个解压的tomcat的catalina.bat 和 startup.bat和service.bat文件的配置&#x…

iptables 基础

iptables防火墙 主要实现数据包的过滤、封包重定向和网络地址转换&#xff08;NAT&#xff09;等功能 iptables&#xff1a;用户空间的命令行工具&#xff0c;用于管理配置netfilter&#xff1a;真正实现功能的是netfilter运行在内核空间 iptables的4表5链 链&#xff1a;通过…

想管好数据资源,不妨了解大数据分析开源框架

在如今快节奏的时代中&#xff0c;办公自动化早已成为各行各业的发展趋势和方向。随着业务量的激增&#xff0c;数据资源也不断增多&#xff0c;如果没有一套完善的大数据分析开源框架&#xff0c;那这么多的数据资源就不能很好地利用和发挥其价值&#xff0c;如果采用专业的大…

基于AT89C52单片机的交通灯设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87855439?spm1001.2014.3001.5503 源码获取 一、实验目的 掌握单片机的综合应用设计。加强对单片机和汇编语言的认识&#xff0c;充分掌握和理解设计各部分的工作…

华为防火墙双机热备外线vrrp地址和接口地址非同网段

主防火墙FW1: HRP_Mdis current-configuration 2023-06-02 15:51:48.270 08:00 !Software Version V500R005C10SPC300 sysname USG6000V1 l2tp domain suffix-separator undo info-center enable ipsec sha2 compatible enable undo telnet server enable undo telnet ipv6 se…

Office Visio 2007安装教程

哈喽&#xff0c;大家好。今天一起学习的是Visio 2007的安装&#xff0c;这是一个绘制流程图的软件&#xff0c;用有效的绘图表达信息&#xff0c;比任何文字都更加形象和直观。Office Visio 是office软件系列中负责绘制流程图和示意图的软件&#xff0c;便于IT和商务人员就复杂…

ROS:客户端Client的编程实现

目录 一、话题模型二、创建功能包三、创建代码并编译运行&#xff08;C&#xff09;3.1步骤3.2创建客户端Client代码3.3编译 四、运行 一、话题模型 Sever端是海龟仿真器/turtlesim&#xff0c;Client端是待实现的程序&#xff0c;其作为Response的节点&#xff0c;并产生Requ…

wav格式怎么转换?介绍三个转换wav格式的方法

在音乐制作或者编辑过程中&#xff0c;可能需要将录制的音频文件转换成特定的格式以便于后期处理。例如&#xff0c;你可能拍摄了一段演奏视频&#xff0c;想要提取其中的音频&#xff0c;并将其转换为wav或者flac等无损格式&#xff0c;以便于进行音频编辑和修复。那么你知道w…

【正点原子STM32连载】 第二十四章 OLED显示实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十…

VMWare安装Ubuntu

VMWare安装Ubuntu 安装前 准备 访问https://cn.ubuntu.com/download(下载需要版本/以16.04为例)操作系统上安装VMWare 基本安装 下载映像文件后&#xff0c;按照一步一步操作即可安装注意选中映像文件安装结束&#xff0c;登录进入系统可看到以下画面 设置语言环境 进入系…

OpenMMLab-AI实战营第二期-课程笔记-Class 2:人体姿态估计与MMpose

Class 2&#xff1a;人体姿态估计与MMpose 文章目录 Class 2&#xff1a;人体姿态估计与MMpose**人体姿态估计概述****what?****下游任务** **2D 姿态估计****主流算法****基于回归坐标的方法****基于热图&#xff08;heatmap&#xff09;的方法** **多人姿态估计****基于回归…