Thrift RPC改进—更加准确的超时管理
前言:
之前我们组内部使用Thrift搭建了一个小型的RPC框架,具体的实现细节可以参考我之前的一篇技术文章:https://www.cnblogs.com/kaiblog/p/9507642.html
相关代码的下载地址:https://github.com/zhangkai253/simpleRPC
在我们的RPC框架中,通过设置socket的timeout属性来控制超时时间,但是这个参数的设置无法保证对超时时间的准确控制,因为只要在超时时间范围内,该socket接收到了1个字节的数据,TimeoutException就不会被抛出。
在我们的日常业务中,竟然会出现设置了300ms超时时间,结果耗时3秒的情况。于是,我们开始寻找更好的解决方案。
方案一:
使用线程池设置超时时间,该方案简单直接,不过多进行叙述。
方案二:
修改底层的TTransport.readAll方法,在其中设置超时时间
Thrift中的TTransport负责进行数据的传输,其基本的类结构图如下所示:

我们本次的改进任务主要关心如下几个类:

我们的RPC框架底层使用了TFastFramedTransport来执行传输任务,这个类是TFramedTransport类的改进版本,两个类在消息格式上面是一致的,都是通过读取4个字节的消息头来解决拆包和粘包的问题。
只是底层buffer的使用方式上面有所不同,在读取数据的时候TFramedTransport类使用的是TMemoryInputTransport,而TFastFramedTransport则使用的是AutoExpandingBufferReadTransport。

通过上面的流程,我们可以看到数据的传输主要是通过在Tsocket中重写TTransport的readAll方法,可以有效地控制超时时间。
方案三:
使用TAsyncClient来替代现在的client,利用TAsyncClientManager来进行超时时间管理,下面我们看看TAsyncClientManager是如何管理请求的。这个问题的答案,我们可以直接从相关的源码中获得,
public void run() {
while (running) {
try {
try {
// 当Thrift请求发送的时候,如果请求设置了超时时间,则会被放到
// timeoutWatchSet中
if (timeoutWatchSet.size() == 0) {
// 如果没有设置了超时时间的请求,则无限期低等待下去
selector.select();
} else {
// 从timeoutWatchSet中取出距离当前最近的过期时间
long nextTimeout = timeoutWatchSet.first().getTimeoutTimestamp();
long selectTime = nextTimeout - System.currentTimeMillis();
if (selectTime > 0) {
// 如果过期时间大于当前时间,则等待剩余时间
selector.select(selectTime);
} else {
// 如果过期时间小于等于当前时间,则立即返回
selector.selectNow();
}
}
} catch (IOException e) {
LOGGER.error("Caught IOException in TAsyncClientManager!", e);
}
transitionMethods();
timeoutMethods();
startPendingMethods();
} catch (Exception exception) {
LOGGER.error("Ignoring uncaught exception in SelectThread", exception);
}
}
try {
selector.close();
} catch (IOException ex) {
LOGGER.warn("Could not close selector. This may result in leaked resources!", ex);
}
}
上述三种方案都可以很好地实现RPC框架对超时时间的控制。大家可以根据自己的使用场景选择合适的解决方案。
如果想进一步沟通和讨论的小伙伴,可以加群聊或者微信进一步交流哈。

Thrift RPC改进—更加准确的超时管理的更多相关文章
- C++服务器设计(四):超时管理机制设计
前四章介绍了系统层的设计,从这一章开始进入服务层的设计. 连接断开 在常见的服务器场景中,客户端断开连接的方式为被动关闭.即作为客户端请求完服务器的服务后,选择主动关闭同服务器的连接.在服务器的角度看 ...
- 如何用istio实现请求超时管理
前言 在前面的文章中,大家都已经熟悉了Istio的故障注入和流量迁移.这两个方面的功能都是Istio流量治理的一部分.今天将继续带大家了解Istio的另一项功能,关于请求超时的管理. 首先我们可以通过 ...
- thrift RPC 框架的自我搭建
安装thrift rpc 安装的系统是Centos 7 未成功的方法 :(原因没找到,但是还是要记录下) 安装依赖库 yum install automake libtool flex bison ...
- thrift rpc通信
thrift rpc通信 框架 别人的简历: 负责抓取程序的开发和维护,对抓取内容进行数据提取.整理.1.定向数据抓取程序的维护和开发,了解了Sqlite数据库.Thrift服务和多线程的开发调试.2 ...
- Thrift RPC Golang、C++ Example
Thrift RPC Example 运行 请直接使用即可,无需拉取任何依赖包. cd $GOPATH/src git clone https://github.com/hunterhug/thrif ...
- idou老师教你学Istio 07: 如何用istio实现请求超时管理
在前面的文章中,大家都已经熟悉了Istio的故障注入和流量迁移.这两个方面的功能都是Istio流量治理的一部分.今天将继续带大家了解Istio的另一项功能,关于请求超时的管理. 首先我们可以通过一个简 ...
- Thrift RPC实战(三) thrift序列化揭秘
本文主要讲解Thrift的序列化机制, 看看thrift作为数据交换格式是如何工作的? 1.构造应用场景: 1). 首先我们先来定义下thrift的简单结构. 1 2 3 4 5 namespace ...
- libevent源码学习(11):超时管理之min_heap
目录min_heap的定义向min_heap中添加eventmin_heap中event的激活以下源码均基于libevent-2.0.21-stable. 在前文中,分析了小顶堆min_h ...
- 使用Thrift RPC编写程序(服务端和客户端)
1. Thrift类介绍 Thrift代码包(位于thrift-0.6.1/lib/cpp/src)有以下几个目录: concurrency:并发和时钟管理方面的库processor:Processo ...
随机推荐
- RabbitMD大揭秘
RabbitMD大揭秘 欢迎关注H寻梦人公众号 通过SpringBoot整合RabbitMQ的案例来说明,RabbitMQ相关的各个属性以及使用方式:并通过相关源码深刻理解. Queue(消息队列) ...
- 【Java面试】简单说一下你对序列化和反序列化的理解
Hi,大家好,我是Mic 一个工作4年的粉丝,投了很多简历 好不容易接到一个互联网公司的面试邀约. 在面试第一轮就被干掉了,原因是对主流互联网技术理解太浅了. 其中就有一个这样的问题:"简单 ...
- CF487E Tourists 题解
题目链接 思路分析 看到这道题首先想到的此题的树上版本.(不就是树链剖分的板子题么?) 但是此题是图上的两点间的走法,自然要想到是圆方树. 我们先无脑构建出圆方树. 我们先猜测:设后加入的节点权值为 ...
- 2022省选前联考 AVL树/平衡树
题目描述 pks 得到了一棵 \(N\) 个节点,权值为 \(1\sim N\) 的 \(AVL\) 树,他觉得这棵树太大了,于是他想要删掉一些节点使得最后剩下的树恰好有 \(K\) 个节点.如果 p ...
- Pytorch从0开始实现YOLO V3指南 part4——置信度阈值和非极大值抑制
本节翻译自:https://blog.paperspace.com/how-to-implement-a-yolo-v3-object-detector-from-scratch-in-pytorch ...
- java中的内存划分和一个数组的内存图
内存概述 内存是计算机中的重要原件,临时存储区域,作用是运行程序.我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存 Java虚拟机要运行程序 ...
- SpringBoot快速整合通用Mapper
前言 后端业务开发,每个表都要用到单表的增删改查等通用方法,而配置了通用Mapper可以极大的方便使用Mybatis单表的增删改查操作. 通用mapper配置 1.添加maven: <depen ...
- Vue 路由懒加载, VueRouter一步完成Vue的路由懒加载 一行代码搞定懒加载
Vue Router路由配置中的component里面配置即可 1 // 路由懒加载的方式加载组件 2 3 component: () => import('@/views/Detail'), ...
- 了解有哪几个C标准&了解C编译管道
下列哪个不是C标准.参考:C语言标准 小知识:C语言标准的发展 K&R C: 1978年,丹尼斯·里奇(Dennis Ritchie)和布莱恩·科尔尼干(Brian Kernighan)出版了 ...
- 多云部署多主模式的MGR集群,每个云一个MGR 节点,满足业务单元化改造的需求
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 本 ...