《从 RPC 到服务化框架设计.docx》由会员分享,可在线阅读,更多相关《从 RPC 到服务化框架设计.docx(20页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、从RPC到服务化框架设计allendbwu腾讯PCG后台开发工程师目前互联网系统都是微效劳化那么就需要RPC调用因此本文梳理了从RPC根本框架协议到整个效劳化框架体系建立中所包含的知识点重点在于RPC框架以及效劳治理才能的梳理本文定位于一个科普性质的文章在于让大众解析一个全貌。一、RPC根本框架1-1、RPC根本框架理解RPCRPC的概念就是远程经过调用。我们本地的函数调用就是A方法调B方法然后得到调用的结果RPC就是让你像本地函数调用一样进展跨效劳之间的函数调用。互联网开展到如今我们都在讲微效劳效劳都拆分为微效劳了那么相关依赖的调用就会变成跨效劳之间的调用而他们之间的通信方式就是依靠RPC。
2、RPC根底构造RPC协议Nelson的论文ImplementingRemoteProcedureCalls告诉我们RPC协议包括5个局部ClientClient-stubRPCRuntimeServer-stubServer当Client提议一个远程调用时它实际上是调用本地的Stub。本地stub负责将调用的接口、方法以及参数通过约定的协议标准进展编码并通过本地的RPCRuntime进展传输然后将数据包发送到网络上传输出去。当Server端的RPCRuntime收到恳求后交给Server-Stub进展解码然后调用Server端的函数或方法执行完毕就开场返回结果Server-Stub将返回结果编
3、码后发送给ClientClient端的RPCRuntime收到结果发给Client-Stub解码得到结果返回给Client。这里面分了三个层次:对于客户端以及效劳端都以及原来本地调用一样只需要关注自身的业务逻辑。对于Stub层处理双方约定好的语法、语义、封装、解封装。对于RPCRuntime主要处理高性能的传输和网络的错误以及异常。1-2、RPC框架的重点从RPC根底构造中我们总结出RPC框架的重点包括4局部如下1-2-1、数据序列化序列化就是将数据构造或者对象转换成二进制的经过也就是编码的经过序列化后数据才方便进展网络传输反序列化就是在序列化经过中所生成的二进制转换成数据构造或对象的经过将二
4、进制转换为对象后业务才好进展后续的逻辑处理。常见的序列化协议如下ProtoBufIDLJSONXMLHessian2JAVA系常见的RPC框架如gRPC、Thrift、Dubbo、RPCX、Motan等会支持上述协议中的大局部尤其是ProtoBuf以及JSON。目前从性能上以及使用广泛度上来看如今一般推荐使用ProtoBuf当然很多自研的框架里面他们也会自己实现他们自己的序列化协议。1-2-2、网络传输网络通信在数据被序列化为二进制后就可以行网络传输了网络传输就是我们的数据怎么传输到对方效劳器上目前来讲常见的通信传输方式包括TCP、UDP、HTTP(HTTP2.0)、QUIC协议TCP是大局部
5、框架都会默认支持的额外这里要讲明一下RPCX支持QUIC而gRPC支持HTTP2.0。QUICQuickUDPInternetConnection是谷歌制定的一种互联网传输层协议它基于UDP传输层协议同时兼具TCP、TLS、HTTP/2等协议的可靠性与平安性可以有效减少连接与传输延迟更好地应对当前传输层与应用层的挑战。QUIC在应用程序层面就能实现不同的拥塞控制算法不需要操作系统以及内核支持这相比于传统的TCP协议拥有了更好的改造灵敏性非常合适在TCP协议优化遇到瓶颈的业务。1-2-3、RPC调用方式网络传输只是数据传输非常根底的一方面从业务上来看我们提议一次RPC调用那么还需要RPC的调用方
6、式包括如下三大类同步RPC最常用的效劳调用方式提议调用恳求后同步等待结果符合我们开发的一贯认知以及习惯。开发简单、容易维护、容易理解。异步RPC客户端提议效劳调用之后不同步等待响应而是注册监听器或回调函数待接收到响应之后提议异步回调驱动业务流程继续执行实现起来相对复杂但是高并发场景下性能会更好。并行RPC并行效劳调用一次I/O操作可以提议批量调用这个并行的批量恳求一般是通过协程来实现然后同步等待响应这里需要注意这个并行RPC以及stream流式调用是有区别的流式是讲批量发送恳求后可以不必等所有的消息全收到后才开场响应而是接收到第一条消息的时候就可和时的响应。1-2-4、效劳治理RPC协议只是定
7、义了Client与Server之间的点对点调用流程包括stub、通信协议、RPC消息解析等局部。但是在实际应用中远程经过调用的时候还需要考虑效劳的路由、负载平衡、高可用等问题而保障效劳之间的调用就需要进展效劳治理效劳治理根本就涵盖效劳注册以及发现、限流、降级、熔断、重试、失败处理、负载平衡等各种效劳治理策略。到这里RPC框架的重点的4大局部就介绍完毕了如今再来看看常见的RPC框架1-3、常见RPC框架RPC框架就是在RPC协议的根底上来完善一些偏向业务实际应用的功能进而知足不同场景的业务诉求。综合来看目前业界的RPC框架大致有两种不同的侧重方向一种偏向于效劳治理型一种偏向于跨语言调用型。1-3
8、-1、效劳治理型RPC框架业界比拟知名的效劳治理型的RPC框架有Dubbo、DubboX、Motan、RPCX等。Dubbo并且提供了丰富的管理功能是特别优秀的RPC框架。序列化Protobuf、JsonRPC、Hessian2兼容协议gRPC、ThriftTriple协议是Dubbo3的主力协议完好兼容gRPCoverHTTP/2DubboX是基于Dubbo框架开发的RPC框架支持REST风格远程调用并增加了一些新的feature。Motan认使用对java更友好的hessian2进展序列化。通讯协议支持Motan、tcp(默认TCP)。RPCX:支持多种编解码协议如Gob、Json、Mes
9、sagePack、gencode、ProtoBuf等支持常见的效劳治理策略支持TCPHTTPQUIC以及KCP效劳治理型RPC框架的特点是功能丰富提供高性能的远程调用和效劳发现、效劳治理等功能常用于微效劳化的业务系统中对于特定语言的工程可以特别友好的透明化接入是当前业界的主流。但缺点是语言耦合度较高跨语言支持难度较大。1-3-2、跨语言调用型RPC框架业界比拟知名的跨语言调用型的RPC框架有gRPC是Google开发的高性能、通用的开源RPC框架。支持ProtoBuf基于HTTP2支持多中语言业界很多基于gRPC来开发自己的RPC框架美图、华为Thrift是Apache的一个跨语言的高性能的效
10、劳框架也得到了广泛的应用。Hprose跨语言调用型RPC框架的重点是关注于效劳的跨语言调用可以支持我们常见的大局部的语言进展语言无关的调用非常合适于为不同语言提供通用远程效劳的场景但这类框架没有效劳发现、效劳治理等机制使用这些框架的时候需要我们自己来实现效劳发现、效劳治理等相关策略。那么跨语言调用指的是啥意思呢详细是客户端以及效劳端可以在各种环境中运行以及互相通信并且可以用框架支持的任何语言编写参考gRPC官网中的一张图如下比方C的效劳可以调用Ruby的效劳1-3-3、常见RPC框架比照二、通用的效劳化框架设计我们一般讲的微效劳框架包含了RPC框架微效劳体系中最重要的就是RPC框架并且是一般是
11、偏向效劳治理的RPC框架。微效劳需要提供的核心才能包括微效劳架构中通讯的根底协议RPC、效劳发现与注册、负载平衡、容错、熔断、限流、降级、权限、全链路日志跟踪。2-1、微效劳框架的核心才能效劳治理策略2-1-1、效劳注册与发现微效劳后效劳大量增加因此我们一定要可以有一个适宜的方案可以发现对方的所有效劳业界比拟常见的效劳发现的组件如zookeeper、etcd、consul等根本原理就是先将自己的效劳列表到注册中心注册然后再提供效劳发现才能。效劳发现机制有效劳端发现以及客户端发现两种实现方式:效劳端发现形式(server-side):可以通过DNS或带VIP的负载平衡实现。优点是对客户端无侵入性
12、客户端只需要简单的向负载平衡或效劳域名提议恳求无需关系效劳发现的详细细节也不用引入效劳发现的逻辑缺点是不灵敏不方便异化处理并且同时需要引入一个统一的负载平衡器。客户端发现形式(client-side):需要客户端到效劳注册中心查询效劳地址列表然后再决定通过哪个地址恳求效劳。灵敏性更高可以根据客户端的诉求进展知足自身业务的负载平衡但是客户端需要引入效劳发现的逻辑同时依赖效劳注册中心常见效劳注册组件包括zookeeper、Etcd、Consul。java系的一般选择zookeeper而Golang的一般选择consul或者etcd这个也就是各自选择对应的语言。etcd相比而言是用的较多的K8s系统
13、里面也基于是etcd。2-1-2、效劳路由负载平衡效劳路由以及效劳发现严密相关效劳路由一般不会设计成一个独立运行的系统通常情况下是以及效劳发现放在一起实现的。在效劳路由中最关键的才能就是负载平衡。我们一般常见的负载平衡算法有随机路由、轮询路由、hash、权重、最小压力路由、最小连接数路由、就近路由等。从业界来看负载平衡的实现方案一般可以分为三类:效劳端负载平衡:负载平衡器在一台单独的主机上可以采用软负载如NginxLVS等可以以采用硬负载如F5等实现简单存在单点问题所有的流量都需要通过负载平衡器假如负载平衡器存在问题那么直接导致效劳不能正常提供效劳中间经过负载平衡器做代理性能也有一定损耗。客户
14、端负载平衡解决了效劳端负载的单点问题每个客户端都实现了自己的负载功能负载才能以及客户端进程在一起负载平衡要求每个客户端自己实现假如不同的技术栈每个客户端那么需要使用不同的语言实现自己的负载才能。目前业界主流的微效劳框架都是采用客户端负载平衡方案客户端主机独立负载平衡效劳发现以及负载的才能从客户端进程移出客户端进程以及负载平衡进程是2个独立的进程在同一个主机上。也就是没有单点问题假如一个主机的负载平衡器出问题只影响一个节点调用不影响其他的节点负载平衡器本身负载也较小性能损耗较低2-1-3、效劳容错负载平衡以及容错是效劳高可用的重要手段。效劳容错的设计有个根本原那么就是“DesignforFail
15、ure。常见的效劳容错策略如恳求重试、限流、降级、熔断、隔离超时与重试超时机制算是一种最常见的效劳容错形式了我们提议的任何恳求调用都不可能无限等待对方效劳可能因为各种原因导致恳求不能及时响应因此超时机制是最根底并且是必须的。超时可能有网络超时、可以能是对方效劳异常等多种情况。重试一般以及超时形式结合使用适用于对于下游效劳的数据强依赖的场景通过重试来保证数据的可靠性或者一致性不强依赖的场景不建议使用。在对方效劳超时之后可以根据情况进展重试(对方效劳返回异常就不要重试了)。但是一定注意重试不能盲目重试在重试的设计中我们一般都会引入ExponentialBackoff的策略也就是指数级退避每一次重试
16、所需要的sleep时间都会指数增加否那么可能会导致拖累到整个系统。效劳限流限流以及降级用来保证核心效劳的稳定性限流是指限制每个效劳的最大访问量、降级是指顶峰期对非核心的系统进展降级进而保证核心效劳的可用性限流的实现方式计数器方式最简单队列算法常规队列FIFO优先级队列带权重队列漏斗(漏桶)算法LeakyBucket令牌桶算法TokenBucket基于响应时间的动态限流参考TCP协议中算法TCP使用RTT来探测网络的延时以及性能进而设定相应的“滑动窗口的大小分布式限流以及单机限流单机限流单机限流参考上面的实现方式可以发现有多种限流算法可供选择但是业界我们最常用的是漏桶算法及令牌桶算法。假如要对线
17、上并发总数进展严格限定的话漏桶算法可能会更适宜一些。分布式限流集群限流集群限流的情况要更复杂一些一般是中心化的设计。简单的实现可以基于Redis来做但是方案的缺点显而易见每取一次令牌都会进展一次网络开销而网络开销起码是毫秒级所以这种方案支持的并发量是非常有限的。另外一个简单的实现思路是先在各个微效劳节点上实现一个计数器对单位时间片内的调用进展计数单个节点的计数量定期推送汇总然后由中心化的统计效劳来计算这个时间片的总调用量集群限流分析器会拿到这个总调用量并以及预先定义的限流阈值进展比对计算出一个限流比例这个限流比例会通过效劳注册中心下发到各个效劳节点上效劳节点基于限流比例会各自算出当前节点对应的
18、最终限流阈值最后利用单机限流进展流控。分布式限流业界常用的框架包括Hystrix、resilience4j容错降级容错降级可以分为三大类从小到大依次是接口降级最小的降级类别。对非核心接口在需要降级的时候可以直接返回空或异常以减少顶峰期这些非核心接口对资源如CPU、内存、磁盘、网络的占用以及消耗功能降级对非核心功能在需要降级的时候可以直接执行本地逻辑不做跨效劳、跨网络访问可以设置降级开关一键关闭指定功能保全整体稳定还可以通过熔断机制实现。效劳降级对非核心效劳可以通过效劳治理框架根据错误率或响应时间自动触发降级策略还可以通过断路器实现熔断设计来源于日常生活中的电路系统在电路系统中存在一种熔断器Ci
19、rcuitBreaker它的作用就是在电流过大时自动切断电路。熔断器一般要实现三个状态闭合、断开以及半开分别对应于正常、故障以及故障后检测故障是否已被修复的场景。闭合正常情况后台会对调用失败次数进展积累到达一定阈值或者比例时那么自动启动熔断机制。断开一旦对效劳的调用失败次数到达一定阈值时熔断器就会翻开这时候对效劳的调用将直接返回一个预定的错误而不执行真正的网络调用。同时熔断器需要设置一个固定的时间间隔当处理恳求到达这个时间间隔时会进入半熔断状态。半开在半开状态下熔断器会对通过它的局部恳求进展处理假如对这些恳求的成功处理数量到达一定比例那么认为效劳已恢复正常就会关闭熔断器反之就会翻开熔断器。熔断
20、设计的一般思路是在恳求失败N次后在X时间内不再恳求进展熔断然后再在X时间后恢复M%的恳求假如M%的恳求都成功那么恢复正常关闭熔断否那么再熔断Y时间依此循环。在熔断的设计中根据Netflix的开源组件hystrix的设计最重要的是三个模块熔断恳求判断算法、熔断恢复机制、熔断报警熔断恳求判断机制算法根据事先设置的在固定时间内失败的比例来计算。熔断恢复对于被熔断的恳求每隔X时间允许局部恳求通过假设恳求都成功那么恢复正常。熔断报警对于熔断的恳求打异常日志以及监控异常恳求超过某些设定那么报警隔离也就是Bulkheads隔板的意思这个术语是用在造船上的也就是船舱里防漏水的隔板。在效劳化框架的隔离设计中我们
21、同样是采用类似的技术来让我们的故障得到隔离。因此这里的重点就是需要我们对系统进展别离。一般来讲有两种方式一种是以效劳的类型来做别离一种是以用户来做别离。以效劳的种类来做别离的方式比方一个社交APP效劳类型包括账号系统、聊天系统那么可以通过不同系统来做隔离以用户来做别离的方式比方通过策略来实现不同的用户访问到不同的实例2-1-4、集群容错在分布式场景下我们的效劳在集群中的都是有冗余的一个是为容错一个是为了高并发针对大量效劳实例的情况下因此就有了集群容错的设计。集群容错是微效劳集群高可用的保障它有很多策略可供选择包括快速失败Failfast快速失败只提议一次调用失败立即报错。通常用于非幂等性的写操
22、作比方新增记录。失败转移Failover失败自动切换当出现失败重试集群其它效劳实例。通常用于读操作但重试会带来更长延迟。一般都会设置重试次数。失败重试Failback:失败自动恢复后台记录失败恳求定时重发。通常用于消息通知操作。聚合调用Forking:并行调用多个效劳器只要一个成功即返回。通常用于实时性要求较高的读操作但需要浪费更多效劳资源。一般会设置最大并行数。播送调用Broadcast:播送调用所有提供者逐个调用任意一台报错那么报错。通常用于通知所有提供者更新缓存或者日志等本地资源信息。2-2、微效劳框架的根底才能效劳监控以及告警开源代表作PrometheusGrafana遵循OpenMe
23、trics标准根本数据格式分为Gauge、Count、Summary、Histogram分布式效劳Tracing跟踪系统目前有两种协议标准OpenTracing链路跟踪领域的标准目前业界系统支持最多的标准开源代表作jaegerzipkinOpenTelemetry可观测性领域的标准对TraceMetricsLog统一支持的唯一标准。OpenTelemetry由OpenTracing以及OpenCensus合并而成以及OpenTracing是一个互补的形态。天机阁配置中心配置中心用来管理大量微效劳之间的业务配置并且是中心化的统一配置中心来进展管理。远程日志远程日志组件的代表作是ELK系统Elas
24、ticsearch,Logstash,Kibana。在微效劳架构中一个客户端恳求的接入往往涉及到后端一系列效劳的调用怎样将这些恳求串联起来业界常用的方案是采用全局流水号【traceID】串联起来。通过全局流水号【traceID】从日志里面可以拉出整条调用链路。这里关于整体链路又以及分布式效劳Tracing跟踪系统关联起来Tracing可以知道整体链路的恳求质量远程日志traceID可以知道整体链路的日志详情。2-3、微效劳框架依托的自动化运维才能微效劳框架建立ok之后那么大量效劳怎么运维这就依托自动化运维才能包括如下几个方面自动化测试自动化部署生命周期管理业界目前一般采用容器平台微效劳框架K8
25、s容器平台是当今互联网业务的黄金标准2-4、小结自己搭建一个效劳化框架的思路自己搭建一个效劳化框架的思路:首先要确定好根本的RPC通信协议一般会选择开源方案重点关注功能需求的知足度多语言的支持性能以及稳定性社区活泼度、成熟度其次基于开源的RPC框架来搭建而不是完全从0开场。可选的框架包括DubboMotangRPCThrift关于方案的比照这里不再陈述网上可以搜索得到想要表达的是每个公司的情况不一样开发人员的才能以及语言也不一样因此方案选型需要根据自身情况而定没有最好只有最适宜最后Go语言方面gRPC是业界公认的比拟好的RPC框架基于gRPC一些效劳治理策略可以实现一个效劳化框架。这些效劳治理的策略很多也都可以用一些开源的组件。腾讯程序员视频号最新视频