brpc之Channel

简介

Channel是brpc的通信类,继承于RpcChannel,RpcChannel是protobuf中的类,用于服务通信

Channel

«abstract»
ChannelBase
+int CheckHealth()
Describable
+void Describe(std::ostream& os, const DescribeOptions&)
Channel
RpcChannel
  • init方法
int Init(butil::EndPoint server_addr_and_port, const ChannelOptions* options);
int Init(const char* server_addr_and_port, const ChannelOptions* options);
int Init(const char* server_addr, int port, const ChannelOptions* options);

RpcChannel

«interface»
RpcChannel
void CallMethod(const MethodDescriptor* method,RpcController* controller, const Message* request,Message* response, Closure* done)

生成服务实现类

服务端

class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {
         protected:
          $classname$() = default;

         public:
          using Stub = $classname$_Stub;

          $classname$(const $classname$&) = delete;
          $classname$& operator=(const $classname$&) = delete;
          virtual ~$classname$() = default;

          static const ::$proto_ns$::ServiceDescriptor* descriptor();

          $virts$;

          // implements Service ----------------------------------------------
          const ::$proto_ns$::ServiceDescriptor* GetDescriptor() override;

          void CallMethod(const ::$proto_ns$::MethodDescriptor* method,
                          ::$proto_ns$::RpcController* controller,
                          const ::$proto_ns$::Message* request,
                          ::$proto_ns$::Message* response,
                          ::google::protobuf::Closure* done) override;

          const ::$proto_ns$::Message& GetRequestPrototype(
              const ::$proto_ns$::MethodDescriptor* method) const override;

          const ::$proto_ns$::Message& GetResponsePrototype(
              const ::$proto_ns$::MethodDescriptor* method) const override;
        };


void $classname$::CallMethod(
            const ::$proto_ns$::MethodDescriptor* method,
            ::$proto_ns$::RpcController* controller,
            const ::$proto_ns$::Message* request,
            ::$proto_ns$::Message* response, ::google::protobuf::Closure* done) {
          ABSL_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$index$]);
          switch (method->index()) {
            case $index$:
            $name$(controller,
                   ::$proto_ns$::internal::DownCast<const $input$*>(request),
                   ::$proto_ns$::internal::DownCast<$output$*>(response), done);
            break;

            default:
              ABSL_LOG(FATAL) << "Bad method index; this should never happen.";
              break;
          }
        }

客户端

class $dllexport_decl $$classname$_Stub final : public $classname$ {
         public:
          $classname$_Stub(::$proto_ns$::RpcChannel* channel);
          $classname$_Stub(::$proto_ns$::RpcChannel* channel,
                           ::$proto_ns$::Service::ChannelOwnership ownership);

          $classname$_Stub(const $classname$_Stub&) = delete;
          $classname$_Stub& operator=(const $classname$_Stub&) = delete;

          ~$classname$_Stub() override;

          inline ::$proto_ns$::RpcChannel* channel() { return channel_; }

          void $classname$_Stub::$name$(::$proto_ns$::RpcController* controller,
                                        const $input$* request,
                                        $output$* response, ::google::protobuf::Closure* done) {
            channel_->CallMethod(descriptor()->method($index$), controller,
                                 request, response, done);
          }

          // implements $classname$ ------------------------------------------
          $impls$;

         private:
          ::$proto_ns$::RpcChannel* channel_;
          bool owns_channel_;
        };

调用

调用是通过CallMethod

void Channel::CallMethod(const google::protobuf::MethodDescriptor* method,
                         google::protobuf::RpcController* controller_base,
                         const google::protobuf::Message* request,
                         google::protobuf::Message* response,
                         google::protobuf::Closure* done)

callid是通过id_create_impl函数来创建。创建Id,设置join_butex , first_ver 和locked_ver

static int id_create_impl(
    bthread_id_t* id, void* data,
    int (*on_error)(bthread_id_t, void*, int),
    int (*on_error2)(bthread_id_t, void*, int, const std::string&)) {
    IdResourceId slot;
    Id* const meta = get_resource(&slot);
    if (meta) {
        meta->data = data;
        meta->on_error = on_error;
        meta->on_error2 = on_error2;
        CHECK(meta->pending_q.empty());
        uint32_t* butex = meta->butex;
        if (0 == *butex || *butex + ID_MAX_RANGE + 2 < *butex) {
            // Skip 0 so that bthread_id_t is never 0
            // avoid overflow to make comparisons simpler.
            *butex = 1;
        }
        *meta->join_butex = *butex;
        meta->first_ver = *butex;
        meta->locked_ver = *butex + 1;
        *id = make_id(*butex, slot);
        return 0;
    }
    return ENOMEM;
}

同步调用

当done为NULL时是同步调用
在这里插入图片描述
Join会等待响应结果

void Join(CallId id) {
    bthread_id_join(id);
}

int bthread_id_join(bthread_id_t id) {
    const bthread::IdResourceId slot = bthread::get_slot(id);
    bthread::Id* const meta = address_resource(slot);
    if (!meta) {
        // The id is not created yet, this join is definitely wrong.
        return EINVAL;
    }
    const uint32_t id_ver = bthread::get_version(id);
    uint32_t* join_butex = meta->join_butex;
    while (1) {
        meta->mutex.lock();
        const bool has_ver = meta->has_version(id_ver);
        const uint32_t expected_ver = *join_butex;
        meta->mutex.unlock();
        if (!has_ver) {
            break;
        }
        if (bthread::butex_wait(join_butex, expected_ver, NULL) < 0 &&
            errno != EWOULDBLOCK && errno != EINTR) {
            return errno;
        }
    }
    return 0;
}

处理响应

是通过ProcessRpcResponse,其调用ControllerPrivateAccessor.OnResponse方法,内部仍然是调用Controller::OnVersionedRPCReturned方法

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

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

相关文章

Sqllab第一关通关笔记

知识点&#xff1a; 明白数值注入和字符注入的区别 数值注入&#xff1a;通过数字运算判断&#xff0c;1/0 1/1 字符注入&#xff1a;通过引号进行判断&#xff0c;奇数个和偶数个单引号进行识别 联合查询&#xff1a;union 或者 union all 需要满足字段数一致&…

《领导的气场——8堂课讲透中国式领导智慧》读书笔记

整体感悟 个人感觉书籍比较偏说教、理论&#xff0c;没有看完。 现仅仅摘录自己“心有戚戚焉”的内容。 经典摘录 管理的本质是通过别人完成任务。有一百件事情&#xff0c;一个人都做了&#xff0c;那只能叫勤劳&#xff1b;有一百件事情&#xff0c;主事的人自己一件也不做&…

子类的继承性

继承性 类有两种重要的成员&#xff1a; 成员变量和方法 子类的成员 ① 自己声明定义 ②从父类继承 ① 成员变量的继 把继承来的变量作为 自己的一个成员变量 &#xff08;如同在子类中直接声明一样&#xff09;&#xff1b; 可被子类中自定义的任何实例方法操作 。 ② 方法…

虚拟机中安装Win98

文章目录 一、下载Win98二、制作可启动光盘三、VMware中安装Win98四、Qemu中安装Win981. Qemu的安装2. 安装Win98 Win98是微软于1998年发布的16位与32位混合的操作系统&#xff0c;也是一代经典的操作系统&#xff0c;期间出现了不少经典的软件与游戏&#xff0c;还是值得怀念的…

【牛客】CM26 二进制插入 HJ60 查找组成一个偶数最接近的两个素数

目录 题目一&#xff1a;二进制插入 题目链接&#xff1a;二进制插入_牛客题霸_牛客网 (nowcoder.com) 解题思路&#xff1a; 代码实现&#xff1a; 题目二&#xff1a;查找组成一个偶数最接近的两个素数 题目链接&#xff1a;查找组成一个偶数最接近的两个素数_牛客题霸_…

【sgPhotoPlayer】自定义组件:图片预览,支持点击放大、缩小、旋转图片

特性&#xff1a; 支持设置初始索引值支持显示标题、日期、大小、当前图片位置支持无限循环切换轮播支持鼠标滑轮滚动、左右键、上下键、PageUp、PageDown、Home、End操作切换图片支持Esc关闭窗口 sgPhotoPlayer源码 <template><div :class"$options.name"…

线程和进程

参考链接&#xff1a; 1.基本概念 进程&#xff1a;Windows系统中&#xff0c;一个运行的xx.exe就是一个进程。例如打开浏览器就是一个进程 线程&#xff1a;进程中的一个执行任务&#xff08;控制单元&#xff09;&#xff0c;负责当前进程中程序的执行。一个进程至少有一个…

无人机|LQR控制算法及其无人机控制中的应用仿真

前言 LQR全称Linear Quadratic Regulator&#xff08;线性二次调节器&#xff09;&#xff0c;顾名思义用于解决形如 x ˙ A x B u y C x D u \begin{aligned}\dot{x}&AxBu\\y&CxDu\end{aligned} x˙y​AxBuCxDu​ 线性时不变系统的一种线性控制方法&#xff0c;…

初识REDHAWK

文章目录 前言一、什么是 REDHAWK?1、概述2、REDHAWK 的应用 二、REDHAWK 的流程管理和交互方法1、流程管理2、数据传输 三、入门1、安装 REDHAWK2、IDE 快速入门①、启动 REDHAWK IDE②、打开 Chalkboard③、创建信号发生器④、测试组件的输入/输出响应 前言 REDHAWK 是一个…

Opencv 绘制线段、矩形、圆形、多边形操作

1、前言 OpenCV提供了许多用于绘制图形的方法 包括绘制线段的line()方法、绘制矩形的 rectangle()方法、绘制圆形的 circle()方法、绘制多边形的 polylines()方法和绘制文字的 putText()方法 本章将依次对上述各个方法进行讲解&#xff0c;并作出相应实验。 因为 OpenCV 中的…

简洁的链式思维(CCoT)提示

原文地址&#xff1a;Concise Chain-of-Thought (CCoT) Prompting 传统的CoT导致了输出令牌使用的增加&#xff0c;而CCoT提示是一种旨在减少LLM响应的冗长性和推理时间的提示工程技术。 2024 年 1 月 24 日 Areas where Chain-Of-Thought-like methodology has been introd…

【C/C++ 学习笔记】函数

【C/C 学习笔记】函数 视频地址: Bilibili 函数结构 返回值类型函数名参数列表函数体语句return 表达式 返回值类型 函数名 (参数列表) {函数体语句;return 表达式; }声明 在函数定义之前声明函数&#xff0c;可以声明多次&#xff0c;但是只能定义依次 返回值类型 函数名…

计算机考研|保姆级择校+资料+全年规划

本科211&#xff0c;研究生上岸某985 计算机考研备考过程中走了不少弯路&#xff0c;希望我的经验能够帮助大家少走弯路 大家决定考研之前&#xff0c;一定要认真思考自己考研的目的是什么&#xff0c;有的人是随大流&#xff0c;别人考研&#xff0c;就跟风考研&#xff0c;有…

JDK 17:Java生态系统的最新巨擘

JDK 17&#xff1a;Java生态系统的最新巨擘 &#x1f680; JDK 17&#xff1a;Java生态系统的最新巨擘 &#x1f680;摘要 &#x1f31f;引言 &#x1f308;模块一&#xff1a;性能优化与提升 &#x1f527;垃圾回收器的改进&#xff1a;JIT编译器的优化&#xff1a;其他性能优…

Visual Basic6.0零基础教学(2)—vb中类的介绍和基本控件的属性

Visual Basic 6.0中类的介绍和基本控件的属性 文章目录 Visual Basic 6.0中类的介绍和基本控件的属性前言一、对象的有关概念1.类2.对象3.对象的三要素4.5. VB程序的执行步骤 二、基本控件属性1.修改控件属性的练习案例 总结 前言 大家好&#xff0c;昨天我们学习了vb的简单介…

python实现生成树

生成树 生成树&#xff08;Spanning Tree&#xff09;是一个连通图的生成树是图的极小连通子图&#xff0c;它包含图中的所有顶点&#xff0c;并且只含尽可能少的边。这意味着对于生成树来说&#xff0c;若砍去它的一条边&#xff0c;则会使生成树变成非连通图&#xff1b;若给…

【学习】pytorch框架的数据管理—— 理解Dataloader

参考&#xff1a;https://spite-triangle.github.io/artificial_intelligence/#/./README 1.标准数据集 使用&#xff1a;以 CIFAR10 数据集为例&#xff0c;其他数据集类似。 # root&#xff1a;数据存放路径 # train&#xff1a;区分训练集&#xff0c;还是测试集 # trans…

前端加密面面观:常见场景与方法解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

vue项目部署服务器,因为跨域设置nginx.config要修改的配置

下面是我在vue项目中vite.config.js设置的配置代理 对于部署项目需要使用nginx进行vue项目的话&#xff0c;需要对nginx的配置文件进行如下修改即可

Linux:线程互斥与同步

目录 线程互斥 锁的初始化 加锁 解锁 锁的初始化 锁的原理 死锁 线程同步 方案一&#xff1a;条件变量 条件变量初始化 等待 唤醒 条件变量的代码示例 基于阻塞队列的生产消费模型 方案二&#xff1a;POSIX信号量 初始化信号量&#xff1a; 销毁信号量 等待信…