专栏首页C++开源框架源码分析腾讯开源框架TarsCpp-rpc设计分析-client(一)
原创

腾讯开源框架TarsCpp-rpc设计分析-client(一)

前言

Tars是腾讯开源的微服务平台,包含了一个高性能的rpc框架和服务治理平台,TarsCpp是其C++版本。对于以C++为主要开发语言,同时还想深入了解rpc和微服务框架具体实现的同学来说,Tars是一个极佳的选择。

想像一下,如果你自己来设计一个rpc-client,都应该考虑哪些因素?

  • 一个高效、可靠的调度器(epoll模型)
  • 如何设计同步调用、异步调用
  • 使用适当的协议来发送请求、解析结果
  • 提供不同的选择服务节点的策略,包括但不限于轮询、hash、权重等
  • 管理服务节点状态,包括不限于节点是否已经连接,是否正在连接中,连接是否超时,是否需要重连,连接超时时间设置,连接重连时间设置等
  • 如何可靠的接收请求、发送结果,请求量怎么控制,接收到1.5个请求怎么办,请求发送完迟迟没收到结果怎么办

这些问题都可以从tars-rpc-client中寻找到实现答案

1 rpc-client概要设计

学习源码的一个重要目的是学习“别人家”模块或项目的设计思路,设计思路的珍贵之处在于其超脱了项目甚至语言的层次,可以迁移到其他地方。

tar-rpc-client主要由4个组件构成:ServantProxy,ObjectProxy,CommunicatorEpoll,AsyncProcThread,其中:

  • ServantProxy:直接与使用者交互,提供简便易用接口
  • ObjectProxy:封装网络层收发细节
  • CommunicatorEpoll:提供收发调度功能
  • AsyncProcThread:提供异步调用功能

四个组件的关系见图1。

图1
  • 在主线程里,ServantProxy是工头,它承接客户需求并加以整理,然后按照一定顺序分给众小弟们(一个小弟是一个ObjectProxy)
  • 小弟ObjectProxy在调度线程中依赖CommunicatorEpoll中的epoll模型高效有序的干活
  • 如果是同步调用,ServantProxy会在主线程中等待,直到ObjectProxy在调度线程中完成请求发送和结果接收
  • 如果是异步调用,主线程不会阻塞,主线程中注册的回调函数在回调线程AsyncProcThread中被执行
  • 一个小弟ObjectProxy对应一个CommunicatorEpoll,一个ServantProxy可以对应多个ObjectProxy
  • 一个CommunicatorEpoll可以对应多个AsyncProcThread

2 CommunicatorEpoll概要设计

CommunicatorEpoll在rpc-client设计中处于核心地位,它确认了client信息流的调度方式。

CommunicatorEpoll是一个封装后的epoll模型,CommunicatorEpoll设计巧妙之处在于将客户调用函数的动作也作为了epoll的触发条件。下面以图2说明CommunicatorEpoll的设计架构

图2

CommunicatorEpoll将epoll\_wait中得到的消息分为两类,一类是处理ObjectProxy消息,另外一类是处理EPOLLIN、EPOLLOUT、EPOLLERR消息。

最核心的系统调用函数也列在了图2上,包括紫色的epoll\_wait和epoll\_ctl、绿色的connect、send和readv。

图2中展示了一个最简单的函数调用流程,下面的序号对应了图2中箭头里的序号

  1. 当用户调用ServantProxy::Hello方法时候,ServantProxy将这个方法包含的内容组成一个msg
  2. 通过ObjectProxy将msg注册到CommunicatorEpoll中。
  3. epoll\_wait获取了通知,处理msg
  4. 链接server端,成功后获取connent fd
  5. 将connect fd注册到CommunicatorEpoll中
  6. 发送请求
  7. 接收结果

2.1 同步call

rpc\_client一般有两种基本的调用方式,sync\_call和async\_call,即同步call和异步call。先看下同步call的实现机制。

同步call实现机理较简单,只需要主线程、调度线程配合就能实现。见图3.

图3
  1. 主线程调用函数后阻塞等待调度线程的信号通知,
  2. 调度线程收到结果后,主备发送信号通知
  3. 发送信号通知
  4. 主线程接收到信号后,本次调用结束

2.2 异步call

异步call需要主线程、调度线程、回调线程三个组件,见图4

图4
  1. 主线程调用完方法后直接结束
  2. 调度线程接收到结果后,放入回调线程的队列\_msgQueue中
  3. 回调线程循环等待\_msgQueue中的msg,当有msg进入时,会使用pop\_front取出
  4. 调用回调函数处理msg

未完--待续

下一篇文章会继续ObjectProxy的设计思路

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ananas RPC源码分析-在net库基础上使用protobuf实现rpc(二)

    第一篇文章也说到了,net库设计比较“干净”,在其基础上设计rpc框架比较方便。本节一起看下ananas怎样使用protobuf自带的rpc模板,在net库上完...

    路小饭
  • 微信phxrpc源码分析(六)--收发流管理

    收发流管理在网络库中处于一个非常重要的位置,与其他rpc框架不同,phxrpc在这方面可谓独辟蹊径,将socket与iostream和streambuf结合起来...

    路小饭
  • 微信phxrpc源码分析(一)-网络库框架分析

    phxrpc是微信后台团队推出的一个非常简洁小巧的RPC框架。前段时间看Tars rpc框架有些“审美疲劳”,拿phxrpc换换脑子。

    路小饭
  • 【行业应用】如果,这就是大数据……

    中国什么时候才能有自己的《纸牌屋》?或许已经为时不远了。印象中,离互联网很远的娱乐圈,已经开始利用大数据进行各种尝试了。 前几天,黑豆碰到了老夏,他就正在做这样...

    小莹莹
  • 活动 | 如何从 0 到 1 打造一个爆款小程序?

    对创业者而言,相比如今各大应用市场 app 的红海,高昂研发成本和用户不堪重负的手机内存。

    知晓君
  • H3C Telnet

    [H3C]telnet server enable  一定要先开启telnet功能

    用户2398817
  • Linux笔记(一):CentOS-7安装

    free赖权华
  • h3c telnet 级别

    我们现在来介绍一下H3C路由器的配置,这次我们讲解的方面是关于telnet远程控制的相关内容。下面我们来对配置H3C telnet的具体过程进行一下讲解。首先我...

    用户2398817
  • Python面试题之Python中的lambda map filter reduce zip

    map()将函数func应用于序列seq中的所有元素。在Python3之前,map()返回一个列表,列表中的每个元素都是将列表或元组“seq”中的相应元素传入函...

    Jetpropelledsnake21
  • 聊聊DAG的共识和牛逼的hashgraph

    可能因为IOTA和byteball的原因,一提到DAG,很多人就会担心DAG可能有中心化的问题。包括iota依赖validator节点,byteball依赖wi...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动