时钟轮在rpc中的应用

author author     2023-03-01     461

关键词:

分布式环境下,RPC框架自身以及服务提供方的业务逻辑实现,都应该对异常进行合理地封装,让使用方可以根据异常快速地定位问题;而在依赖关系复杂且涉及多个部门合作的分布式系统中,我们也可以借助分布式链路跟踪系统,快速定位问题。

1 Future超时处理案例

以调用端请求超时处理为例,RPC框架如何处理超时请求。

无论同步、异步调用,调用端内部都是异步,调用端在向服务端发消息前会创建一个Future,存储消息标识与Future的映射,当服务端收到消息并处理完毕后向调用端发响应消息,调用端在接收到消息后会根据标识找到这Future,并将结果注给这Future。

这过程中,若服务端没及时响应消息给调用端咋办?调用端如何处理超时请求?

可利用定时任务。每次创建一个Future,记录这Future的创建时间与这个Future的超时时间,并有一个定时任务进行检测,当该Future到达超时时间&&未被处理,就对该Future执行超时逻辑。

2 定时任务实现

2.1 sleep

最简单的。每创建一个Future,都启动一个线程,sleep,到达超时时间后就触发请求超时的处理逻辑。

高并发下,请求超时时间设5s,要创建多少个线程执行超时任务呢?超过10万个线程!

2.2 用一个线程处理所有的定时任务

假设启动一个线程,每100ms扫一遍所有的处理Future超时的任务,当发现一个Future超时,就执行这任务,对这个Future执行超时逻辑。

用得最多,也解决了方式一线程过多的问题。

缺陷

高并发的请求,扫描任务的线程每隔100ms要扫描多少个定时任务?若调用端刚好在1s内发送1万次请求,这1万次请求要在5s后才超时,扫描线程在这5s内就会不停对这1万个任务进行扫描遍历,要额外扫描40多次(每100ms扫描一次,5秒内要扫描近50次),浪费CPU!

使用这些简陋定时任务方案,缺陷就是让CPU做太多额外的轮询遍历操作,浪费CPU。

3 时间轮

只要减少额外扫描操作即可。

如我的一批定时任务是5s后执行,我在4.9s后才开始扫描这批定时任务,就大大节省CPU。可利用时钟轮。

3.1 生活的时钟

时钟轮在RPC中的应用_请求超时

秒针跳动一周=跳动60个刻度后,分针跳动1次;分针跳动60个刻度,时针走动一步。时钟轮实现原理就参考这原理。时钟轮示意图:

时钟轮在RPC中的应用_请求超时_02

时钟轮有:

  • 时间槽
    就相当于时钟的刻度。将每个任务放到对应的时间槽位。
  • 时钟轮
    相当于秒针与分针等跳动的一个周期

时钟轮的运行机制和生活中的时钟也是一样的,每隔固定的单位时间,就会从一个时间槽位跳到下一个时间槽位,这就相当于我们的秒针跳动了一次;时钟轮可以分为多层,下一层时钟轮中每个槽位的单位时间是当前时间轮整个周期的时间,这就相当于1分钟等于60秒钟;当时钟轮将一个周期的所有槽位都跳动完之后,就会从下一层时钟轮中取出一个槽位的任务,重新分布到当前的时钟轮中,当前时钟轮则从第0槽位从新开始跳动,这就相当于下一分钟的第1秒。

4 案例讲解

假设时钟轮10个槽位,时钟一轮周期1s,则每个槽位单位时间100ms,而下一层时间轮的周期就是10s,每个槽位的单位时间也就是1s,并且当前的时钟轮刚初始化完成,即第0跳,当前在第0个槽位。

时钟轮示意图:

时钟轮在RPC中的应用_请求超时_03

任务分配

现有3个任务:

  • 任务A(90ms后执行)
  • 任务B(610ms后执行)
  • 任务C(1秒610ms后执行)

任务添加到时钟轮,任务A被放到第0槽,B第6槽,C放到下一层时间轮的第1槽位,时钟轮任务分布示意图:

时钟轮在RPC中的应用_请求超时_04

执行过程

  • 当任务A刚被放到时钟轮,就被即刻执行,因为它在第0槽,当前时间轮正好跳到第0槽,实际上还没开始跳动,状态为第0跳
  • 600ms后,时间轮已进行6跳,当前槽位第6槽,第6槽位所有任务被取出执行
  • 1s后,当前时钟轮的第9跳已跳完,从新开始第0跳,这时下一层时钟轮从第0跳跳到第1跳,将第1槽位的任务取出,分布到当前的时钟轮,这时任务C从下一层时钟轮中取出并放到当前时钟轮的第6槽位;1秒600毫秒之后,任务C被执行

时钟轮在RPC中的应用_定时任务_05

该案例的时钟轮的扫描周期仍是100ms,但其中的任务并没有被过多重复扫描,完美解决CPU浪费过多问题。

5 时钟轮在RPC中的应用

时钟轮就是用来执行定时任务,在RPC框架中只要涉及到定时相关的操作,就可使用时钟轮。

调用端请求超时处理,就可用到时钟轮,每发一次请求,都创建一个处理请求超时的定时任务放到时钟轮,在高并发、高访问量时,时钟轮每次只轮询一个时间槽位中的任务,节省大量CPU。

调用端与服务端启动超时也可应用时钟轮,以调用端为例,假设我们想要让应用可以快速地部署,例如1分钟内启动,如果超过1分钟则启动失败。我们可以在调用端启动时创建一个处理启动超时的定时任务,放到时钟轮里。

定时心跳

RPC框架调用端定时向服务端发送心跳,来维护连接状态,可将心跳的逻辑封装为一个心跳任务,放到时钟轮。

心跳是要定时重复执行的,而时钟轮中的任务执行一遍就被移除了,对于这种需要重复执行的定时任务我们该如何处理呢?在定时任务的执行逻辑的最后,我们可以重设这个任务的执行时间,把它重新丢回时钟轮。

6 总结

这很好地解决了定时任务中,因每个任务都创建一个线程,导致的创建过多线程的问题,以及一个线程扫描所有的定时任务,让CPU做了很多额外的轮询遍历操作而浪费CPU的问题。

时钟轮的实现机制就是模拟现实生活中的时钟,将每个定时任务放到对应的时间槽位上,这样可以减少扫描任务时对其它时间槽位定时任务的额外遍历操作。

  • 时间槽位的单位时间越短,时间轮触发任务的时间就越精确。例如时间槽位的单位时间是10毫秒,那么执行定时任务的时间误差就在10毫秒内,如果是100毫秒,那么误差就在100毫秒内。
  • 时间轮槽位越多,一个任务被重复扫描的概率就越小,因为只有在多层时钟轮中的任务才会被重复扫描。比如一个时间轮的槽位有1000个,一个槽位的单位时间是10ms,那么下一层时间轮的一个槽位的单位时间就是10s,超过10秒的定时任务会被放到下一层时间轮中,也就是只有超过10s的定时任务会被扫描遍历两次,但若槽位是10个,则超过100ms的任务,就会被扫描遍历两次

视具体业务对时钟轮的周期和时间槽数设置。

只要涉及定时任务,都可应用时钟轮,如调用端的超时处理、调用端与服务端的启动超时以及定时心跳等。

FAQ

时钟轮可以实现延时消息的功能,比如让一个任务几分钟之后发送一条消息出去。在比如可以实现订单过期功能,用户下单10分钟没付款,就取消订单,可以通过时钟轮实现。

时钟轮存取任务的时间复杂度是O(1),相比之下优先队列的时间复杂度是O(logN)。

如果并发线程比较多,单位时间是不是划分很细啊。例如我同时有5个线程几乎之间间隔3到5毫秒,又有3个线程10到100毫秒的,我时钟轮也得调整具体怎么划分的,这么短时间内如何保证时钟轮准确性?

一般都是统一划分,时间轮主要解决是长时间没有触发的问题,不解决实时性。

GWT 应用程序中的 RPC 与 JSON 比较

】GWT应用程序中的RPC与JSON比较【英文标题】:RPCvsJSONcomparisioninGWTapplication【发布时间】:2011-12-1414:27:19【问题描述】:这是一个简单而有力的问题。我有一个应用程序测试,它通过RPC和REST发送1000个CustomDTO列表。我只想知道反序... 查看详情

hadoop中的rpc机制

1. RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越... 查看详情

ntp网络校时服务器(北斗gps校时器)在地铁内网系统中的应用

... NTP网络校时服务器是一种基于网络时间协议(NTP)的时钟同步系统,用于确保地铁车站各个时钟的时间同步。下面是该系统的工作原理: 1.NTP校时服务器:NTP地铁时钟系统需要至少一个NTP时间服务器来提供精确的时间参... 查看详情

ipad pro 中的时钟和字体放大

】ipadpro中的时钟和字体放大【英文标题】:ClockandFontsscalingupinpadpro【发布时间】:2016-02-2614:11:53【问题描述】:我正在开发一个应用程序,首先我使用IpadAir运行该应用程序,然后使用具有相同比例的Ipadpro模拟器运行该应用程序... 查看详情

gps北斗卫星时钟服务器在飞机场内网中的应用

GPS北斗卫星时钟服务器在飞机场内网中的应用GPS北斗卫星时钟服务器在飞机场内网中的应用GPS北斗卫星时钟服务器在飞机场内网中的应用京准电子科技官微——ahjzsz卫星时钟服务器在飞机场内网中可以应用于时间同步、安全监控... 查看详情

gwt rpc 中的 http 错误代码

】gwtrpc中的http错误代码【英文标题】:httperrorcodesingwtrpc【发布时间】:2011-01-1013:04:58【问题描述】:我正在使用一个使用gwt、spring、hibernate的Web应用程序。我正在使用gwtrpcspringRemoteServiceDispatcher进行远程服务映射。目前,如果... 查看详情

时间轮原理及其在框架中的应用(代码片段)

...服务器团队-LiWanghong一、时间轮简介1.1为什么要使用时间轮在平时开发中,经常会与定时任务打交道。下面举几个定时任务处理的例子。1)心跳检测。在Dubbo中,需要有心跳机制来维持Consumer与Provider的长连接,默认的心跳间隔是... 查看详情

龙卷风网络服务器中的 json rpc

】龙卷风网络服务器中的jsonrpc【英文标题】:jsonrpcintornadowebserver【发布时间】:2012-12-0710:07:03【问题描述】:我正在使用带有javascript客户端(使用extjs)的tornadoweb服务器在python中实现web应用程序。在此类应用程序中实现rpc的最... 查看详情

时间轮原理及其在框架中的应用(代码片段)

...效的处理定时任务。一、时间轮简介1.1为什么要使用时间轮在平时开发中,经常会与定时任务打交道。下面举几个定时任务处理的例子。1)心跳检测。在Dubbo中,需要有心跳机制来维持Consumer与Provider的长连接,默认的心跳间隔... 查看详情

jqGrid 中的 JSON RPC

】jqGrid中的JSONRPC【英文标题】:JSONRPCinjqGrid【发布时间】:2011-02-1817:40:46【问题描述】:我正在开发一个使用JSON与服务器进行通信的Web应用程序。我用varjsonStr=\'name:"Rob",time:"2pm"\';jQuery("#name").jqGrid(type:"POST",url:\'ControllerServlet?json... 查看详情

Kivy 中的数字时钟标签

】Kivy中的数字时钟标签【英文标题】:DigitalClockLabelinKivy【发布时间】:2018-07-2815:21:44【问题描述】:过去6周左右一直在玩python,过去两周我一直在尝试学习kivy。很难弄清楚如何更新我用来在我的应用中显示时间的标签。我已... 查看详情

GWTphonegap PhonegapUtil.prepareService RPC 调用导致 Wildfly 中的“405 Method not found”和 Android 应用程序上 Tom

】GWTphonegapPhonegapUtil.prepareServiceRPC调用导致Wildfly中的“405Methodnotfound”和Android应用程序上Tomcat中的“HPPTstatus404”【英文标题】:GWTphonegapPhonegapUtil.prepareServiceRPCcallresultsin"405Methodnotfound"inWildflyand"HP 查看详情

来自 GWT 的 RPC 调用中的异常

】来自GWT的RPC调用中的异常【英文标题】:ExceptioninRPCcallfromGWT【发布时间】:2013-09-2517:34:11【问题描述】:我在运行GWT时遇到异常。上面写着“com.google.gwt.user.server.rpc.UnexpectedException:Servicemethod\'publicabstract”。可能的原因是什么... 查看详情

如何在应用程序运行之间本地检测用户的 iPhone 时钟提前?

】如何在应用程序运行之间本地检测用户的iPhone时钟提前?【英文标题】:HowcanIlocallydetectiPhoneclockadvancementbyauserbetweenappruns?【发布时间】:2011-10-3015:15:09【问题描述】:休闲游戏中的一个常见漏洞是人为地提前系统时钟以在游... 查看详情

使用 mingw64 c++ 编译 imapi2 应用程序时 imapi2.h 中的错误“没有类型的 '__RPC__range' 声明”

】使用mingw64c++编译imapi2应用程序时imapi2.h中的错误“没有类型的\\\'__RPC__range\\\'声明”【英文标题】:errorsinimapi2.hwhencompilingimapi2appwithmingw64c++"declarationof\'__RPC__range\'withnotype"使用mingw64c++编译imapi2应用程序时imapi2.h中的错误... 查看详情

.NET Core 和 Xamarin 中的 RPC

】.NETCore和Xamarin中的RPC【英文标题】:RPCin.NETCoreandXamarin【发布时间】:2018-04-1321:16:17【问题描述】:我正处于使用C#为移动设备构建在线收藏纸牌游戏的早期阶段。游戏客户端本身是使用Xamarin构建的,并且(最终)将在iOS和Andr... 查看详情

在apigility中触发RPC控制器中的REST请求

】在apigility中触发RPC控制器中的REST请求【英文标题】:TriggerRESTrequestinRPCControllerinapigility【发布时间】:2014-12-0214:40:26【问题描述】:考虑到REST和RPC调用之间的差异并将它们应用于apigility我想将注册操作实现为RPC调用,它通过PO... 查看详情

用于 RPC 的 XDR 中的 ssize_t 数据类型

】用于RPC的XDR中的ssize_t数据类型【英文标题】:ssize_tdatatypeinXDRforRPC【发布时间】:2015-07-1701:42:42【问题描述】:我正在编写一个RPC应用程序。我需要在C部分使用ssize_t数据类型,并且需要通过网络发送。在IDL中我应该用什么表... 查看详情