阿里妹导读:2017年的双十一圆满结束了,1682亿的成交额再一次刷新了记录,而HSF(High Speed Framework,分布式服务框架)当天调用量也突破了3.5万亿次,调用量是2016年双十一的三倍多。为了这不平凡的一天中,HSF经历了一年多的磨练,从架构升级到性能优化,从可用性提升到运维提升,完成了从2.1到2.2的全面升级,截止到双十一开始的一刻,HSF2.2在全网机器占比超过75%,并成功接受了大促考验。
从HSF2.1到HSF2.2的目标是提升HSF框架的扩展性、易用性和性能,相当于将原有HSF推倒了重新来过,因此涉及到的内容众多,这里不做展开,我们仅从架构升级、性能优化和运维提升三个方面来聊一下HSF2.2做了什么,有什么能帮到大家,以及如何解决了双十一的一些问题。
架构升级
HSF2.1主要被用户抱怨的一点就是扩展性不强,比如:不少用户想拦截调用请求但无法方便做到,只好退而求其次,使用代理来包装HSF的客户端或者服务端,这样做一来显得繁琐,二来出现问题不易排查。不光是用户的扩展支持的不好,框架自身对不同的开源组件适配也显得力不从心,比如:支持ZooKeeper作为注册中心的方案一直难以实施,原因在于框架内部与ConfigServer耦合过于紧密。无论是用户还是框架的维护者,都受限于现有架构,这是HSF需要改变的地方。
HSF2.2的架构与原有版本有了显著变化,首先是层与层之间的边界清晰,其次组件之间的关系职责明确,最后是扩展可替换的思想贯穿其中,下面我们先看一下新的架构:
可以看到HSF2.2从宏观上分为了三个域:框架、应用和服务,其中框架是对上层多个应用做支撑的基础,而服务属于具体的某个应用,从这种划分可以看出,HSF2.2是天然支持多应用(或多模块)部署的。每个域中,都有各自的功能组件,比如:服务域中的InvocationHandler就是对服务调用逻辑的抽象,通过扩展其中的ClientFilter或者ServerFilter完成对客户端或者服务端的调用处理工作,这里只是罗列了主要的功能组件和扩展点,以下是对它们的说明:
服务 ,对应于一个接口,它可以提供服务或者消费服务
应用 ,对应于一个应用或者一个模块,它管理着一组消费或者发布的服务
框架 , 对应于框架底层支持,它统一管理着线程、链接等资源
分类介绍了HSF2.2的主要组件后,我们来看看架构的改变,扩展性的提升,能够为业务方,为他们更好的支持双十一带来什么。
纯异步调用拦截器
HSF异步future调用被业务方越来越多的使用,但是eagleeye对future调用的耗时统计上一直不准,因为future调用返回的是默认值,所以业务看到的是一次飞快的调用返回,它真实的耗时该如何度量?信息平台承载了集团的众多内部服务业务,一直苦于没有办法全面的监控HSF的调用记录,也无法做到异常报警,难道还要让所有的使用方配置代理?
HSF2.2设计的InvocationHandler组件以及扩展,完美的解决了这个问题,我们近距离观察一下InvocationHandler以及其扩展,以客户端调用场景为例:一次调用是如何穿过用户扩展的调用拦截器的。
可以看到,HSF2.2定义的调用拦截器不是一个简单的正向invoke过程,它还具备响应回来时的逆向onResponse过程,这样一来一回很好的诠释了HSF同步调用异步执行的调用模型。用户可以通过在一次调用中计算invoke和onResponse之间的时差来获得调用的正确耗时,而不用关心HSF调用是同步还是异步,用户也可以扩展一个调用拦截器穿插在其中,用于监控HSF的调用内容,而不用让应用方做任何代码上的改造。
多应用支持
多模块部署一直是业务方同学探索的热点,从合并部署开始,HSF就有限的支持了多应用部署,但是一直没有将其融入到架构中。在HSF2.2中,应用不仅仅是作为托管服务的容器而是成为核心领域,多应用序列化的难题,就在应用层解决。
(模块在HSF2.2中也会被认为是一个应用,以下提到模块或者应用可以认为是一个概念。)
HSF2.2支持多个应用部署的结构如下图所示:
可以看到,HSF2.2框架域处于最底层,它向上为应用提供了线程、连接等多种资源的支持,而应用能够发布或者订阅多个服务,这些服务能够被应用统一管理,也支持更加精细化的配置,层与层的司职明确让HSF具有了良好的适应性。
性能优化
RPC流程中,序列化是开销很大的环节。尤其现在业务对象都很复杂,序列化开销更不容小觑。
下面先介绍下今年HSF针对Hessian的几个优化点。也感谢分享思路和反馈问题的坤谷、道延和昕辰三位同学。
优化1:元数据共享
hessian序列化会将两种信息写到输出流:
1.元数据:即类全名,字段名
2.值数据:即各个字段对应值(如果字段是复杂类型,则会递归传递该复杂类型的元数据和内部字段的值数据)
在hessian1协议里,每次写出Class A的实例时,都会写出Class A的元数据和值数据,就是会重复传输相同的元数据。针对这点,hessian2协议做了一个优化就是:在“同一次序列化上下文”里,如果存在Class A的多个实例,只会对Class A的元数据传输一次。该元数据会在对端被缓存起来重复使用,下次再序列化Class A的对象时,只需要先写出对元数据的一个引用句柄(缓存中的index,用一个int表示),然后直接写出值数据即可。接受方通过元数据句柄即可知道后面的值数据对应的类型。
这是一个极大的提升。因为编码字段名字(就是字符串)所需的字节数很可能比它对应的值(可能只是一个byte)更多。
不过在官方的hessian里,这个优化有两个限制:
1.序列化过程中类型对应的Class结构不能改变
2.元数据引用只能在“同一个序列化上下文”,这里的“上下文”就是指同一个HessianOutput和HessianInput。因为元数据的id分配和缓存分别是在HessianOutput和HessianInput里进行的
限制1我们可以接受,一般DO不会再运行时改变。但是限制2不太友好,因为针对每次请求的序列化和反序列化,HSF都需要使用全新构造的HessianOutput和HessianInput。这就导致每次请求都需要重新发送上次请求已经发送过的元数据。
针对限制2,HSF实现了跨请求元数据共享,这样只要发送过一次元数据,以后就再也不用发送了,进一步减少传输的数据量。实现机制如下:
1.修改hessian代码,将元数据id分配和缓存的数据结构从HessianOutput和HessianInput剥离出来。
2.修改HSF代码,将上述剥离出来的数据结构作为连接级别的上下文保存起来。
3.每次构造HessianOutput和HessianInput时将其作为参数传入。这样就达了跨请求复用元数据的目的。
该优化的效果取决于业务对象中,元数据所占的比例,如果“精心”构造对象,使得元数据所占比例很大,那么测试表现会很好,不过这没有意义。我们还是选取线上核心应用的真实业务对象来测试。从线上tcp dump了一个真实业务对象,测试同学以此编写测试用例得到测试数据如下:
1.新版本比老版本CPU利用率下降10%左右
2.新版本的网络流量相比老版本减少约17%
线上核心应用压测结果显示数据流量下降一般在15%~20%之间。
优化2:UTF8解码优化
hessian传输的字符串都是utf8编码的,反序列化时需要进行解码。hessian现行的解码方式是逐个字符进行。代码如下:
private int parseUTF8Char() throws IOException { int ch = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
if (ch < 0x80)
return ch;
else if ((ch & 0xe0) == 0xc0) {
int ch1 = read();
int v = ((ch & 0x1f) 3;
for (int i = 0; i < numLongs; i++) {
long currentOffset = baseOffset + _offset; long test = unsafe.getLong(_buffer, currentOffset);
if ((test & 0x8080808080808080L) == 0L) { _chunkLength -= 8;
toRead -= 8;
for (int j = 0; j < 8; j++) { _sbuf.append((char)(_buffer[_offset++])); }
} else {
break;
}
}
for (int i = 0; i < toRead; i++) { _chunkLength--;
int ch = (_buffer[_offset++] & 0xff);
if (ch < 0x80) { _sbuf.append((char)ch);
} else if ((ch & 0xe0) == 0xc0) {
int ch1 = read();
int v = ((ch & 0x1f)
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?