HSF原理分析

1. HSF的基本概念

HSF全称为High-Speed Service Framework,旨在为淘系的应用提供一个分布式的服务框架,HSF从分布式应用层面以及统一的发布/调用方式层面为你们提供支持,从而能够很容易的开发分布式的应用以及提供或使用公用功能模块,而不用考虑分布式领域中的各类细节技术,例如远程通信、性能损耗、调用的透明化、同步/异步调用方式的实现等等问题。java

2. 知识准备

2.1 对象的序列化

对象的序列化过程在RPC过程当中是很重要的一个环节,序列化对于远程调用的响应速度、吞吐量、网络带宽消耗等一样也起着相当重要的做用。
在HSF1.0时只支持两种序列化方式:java 和 hessian,在HSF2.0以后就支持了五种序列化方式:java、hessian、hessian二、json、kyro。
可是目前版本中经常使用的序列化方式仍是java 和 hessian两种。 若是想细致的了解也能够多作了解。web

2.2 动态代理

对于消费方来讲,所存在的只有一个接口,虽然底层的实现原理咱们知道,可是为了在使用时的高度透明,在JAVA语言层面上的表现形式则是经过动态代理的方式实现的,不少的逻辑都在InvocationHandler 中处理的。关于如何实现动态代理,还动态代理的一些使用的细节也能够稍做了解。编程

2.3 网络通讯NIO

若是在网络传输过程当中,采起普通的BIO,会有不少的问题存在,例如若是调用端有多个请求过来,那么就得须要多个线程去处理,每一个线程都使用独立的链接,在远端的提供者端有对应的多个线程来执行相应的服务。这种方式会使得调用者和提供者之间创建大量的链接,并且是阻塞的方式,链接并不能获得充分的利用(摘自《大型网站系统与JAVA中间件》)。采用NIO则就能够避免这样的损耗,可是HSF在使用时并非采用直接的NIO编程,而是经过第三方的框架Netty。json

3. HSF 实现原理

3.1 提供服务的大体流程以下:

  • server启动时候向configserver注册
  • client启动时候向configserver请求list
  • client缓存list,发现不可用的server,从缓存中remove
  • configserver经过心跳包维护可用server的list
  • list有更新的时候,configserver经过带version的报文通知client更新

从以上几个问题出发,看下HSF的实现方式。缓存

3.2 HSF的总体实现方式

从图中能够看出,HSF的实现方式能够理解为是C/S的架构,可是和传统的C/S架构相比仍是有很大的不一样,HSF没有真正的服务器,每一个应用均可以成为服务的调用方和提供方。具体工做方式以下:服务器

ConfigServer:远程调用对端的地址就是由ConfigServer 来推送的,这样用户只须要配置本身的服务端或者消费端,不须要对本身的地址进行管理。网络

Diamond:持久化的配置中心,用于配置服务调用的规则。架构

服务:服务是调用方和提供方交流的依凭,通常是一个接口,表示一个业务行为以及相关的数据含义。经过使用HSFApiProviderBean可以暴露一个服务,将机器的地址注册到configserver,而且可以经过12200端口进行服务提供,经过HSFApiConsumerBean可以包装出一个客户端,它是服务接口的一个代理,而且它从configserver上订阅了服务的地址列表,可以在这个列表上完成随机调用,作到负载均衡与HA((High Available,高可用性群集)。负载均衡

网络通讯:HSF的底层网络通讯是使用netty框架实现的,是基于epoll的NIO的网络通信框架,HSF在此使用的是长链接,经过合理的服务部署及负债均衡,基本不存在I/O方面的限制。框架

4. HSF设计架构

关于HSF的架构基本能够理解为C/S结构设计方式。(虽然HSF没有本身的服务器)
Server端除了configServer外还有一个diamond用来保存一些持久化的配置信息,这里不进行过多的介绍。

Client是HSF的重点,下面是各模块的功能介绍:
Proxy:这一层主要负责接口的代理。基本上全部的RPC框架都会用到代理模式,相信你们不陌生。须要注意的是HSF的代理层还进行了软负载和单元化的处理。
Remoting:这一层是HSF的应用层协议,定义了报文格式,各个字段的含义等信息,内容比较多,以后单独写一篇文章来介绍。
Processer:这一层主要是处理HSF自身的业务逻辑,包括埋点、限流、鉴权等。
Netty:上面三层会将一次服务调用或者服务返回包装成一个报文,而后经过这层传输。

HSF调用流程

上图是HSF整个的调用过程,从左向右看:
第一条线路至关于consumer进行服务调用的过程,首先通过proxy层,将请求通过代理类包装出去;而后是Remoting层进行协议的包装,(处理HSF自身的业务逻辑,包括埋点、限流、鉴权等)最后io层发送出去。
第二条线路至关于provider将结果返回后解析的过程,与上一流程恰好相反。
右边的provider两条调用流程相信你们都能按照上面的过程理解,就不一一讲解了。

5. HSF处理请求流程

5.1 HSF提供端初始化

5.2 HSF消费端初始化

5.3 消费方请求到提供方,响应一次调用

5.4 实现细节

心跳检测:
一、客户端主动关闭链接:客户端第一次与服务端创建连接后,就会周期性(27s)发送心跳包的callback调用,若是连续三次收不到服务端的心跳包回应,客户端主动关闭连接
二、服务端主动关闭链接:当链接59s没有调用(对方网络不可用,或者full gc过久),至关于两次(2*27s)收不到心跳包的时间

从上图能够看出RPC要解决如下几个问题:

如何解决网络通讯问题,主要是经过在客户端和服务器之间创建TCP链接,远程过程调用的全部交换的数据都在这个链接里传输。链接能够是按需链接,调用结束后就断掉,也能够是长链接,多个远程过程调用共享同一个链接。

如何解决寻址问题,客户端如何找到制定的服务端,也就是保证准确有效的完成一次服务调用的前提。

参数的传递及服务端在收到客户端请求后如何实现其具体功能并返回,因为网络传输协议是二进制的,内存中的参数值必需要解决序列化,反序列化,以及对半包,粘包的处理。

6. HSF的优势:

6.1 服务的自动注册、发现

经过注册中心,实现服务的注册/注销与服务的发现。当服务启动后,会调用publish来将服务发布到中心,而服务的消费者,经过调用订阅接口传入的监听器来更新服务提供者列表。HSF提供了三种注册中心实现,分别是ConfigServer,Zookeper,和配置文件模式。

这里仅对Zookeper进行分析,ZookeeperMetadataAddressService 实现了上述接口,在初始化中实例化了一个ZookeeperRegistry来进行管理,其使用了一个封装了zookeperclient的实例-ZkclientZookeeperClient,在注册服务的时候根据url参数中的Constants.DYNAMIC_KEY来肯定建立Persistent节点仍是Ephemeral节点,Ephemeral节点生命周期与本机链接绑定,这样就能够实现本机离线后的服务自动注销的功能。

6.2 服务提供者与消费者之间长链接

HSF采用长链接方式进行通讯,相比短链接,长链接更具性能优点,避免链接重复建立与销毁带来的缓冲区申请与释放。HSF抽象了链接AbstractClient(Client),并采用了netty框架做为底层实现。netty是一个性能很是优秀的通讯框架,基于Reactor模式,内部采用了管线模式来解耦不一样层次的逻辑之间的耦合问题。HSF为了强化TCP链接的可用性,增长HeartBeat功能,使用了一个Netty提供的 HashedWheelTimer 的定时任务调度器来执行心跳包的发送(补充:此HashedWheelTimer原理采用轮片式的桶结构,避免每次操做对所有任务的迭代操做,只对将要到期的桶进行操做,此原理也可用于缓存系统设计,在须要进行垃圾回收的状况下只须要按照桶为单位进行内存回收)。

6.3 非侵入性

HSF最大优势是非侵入性,它使用了JAVA的Proxy机制来实现这一特色,在经过xml配置文件配置Consumer的时候,其实是调用了 HSFApiConsumerBean ,在它的初始化方法中,读取了配置的实现接口,并在ProcessComponent中用一个封装了Proxy注册功能,并实现了InvocationHandler接口的类HSFServiceProxy去管理。使用者在本身的代码中无需作任何特殊处理,就像使用本地方法同样去调用其方法。

6.4 版本管理

这一特性能够很灵活的帮助上线运营的服务在升级过程当中避免服务不可用的状况。

6.5 服务治理

能够经过网页可视化查看、管理、测试服务的可用。

6.6 扩展灵活

能够接入自动服务降级功能(熔断) - 根据配置或服务的执行结果,在调用级控制服务是否调用执行,避免服务总体瘫痪,提高服务的可用性。

参考:
https://blog.csdn.net/qq_16681169/article/details/72512819

相关文章
相关标签/搜索