百分点大数据技术团队:可插拔 OSS 架构设计和实战经验
编者按:随着互联网、大数据和人工智能等技术的发展,信息资源得到最大程度的共享,但随之而来的海量文件存取的功能和性能问题也日渐突出。在政务领域解决方案中,对象存储往往扮演着非常重要的角色,如全国各地的健康宝的头像和核酸报告文件或图片的高速并发存取,不同地区应用接口和后端存储的快速适配等。
百分点科技基于海外多个项目的建设经验,沉淀出基于 HBase 和 Ceph 的混合对象存储服务,能够有效解决海量文件高速存储的问题,并通过写事件通知,将小文件内容传输至 Kafka,实现下游系统以顺序方式读取文件,提升系统整体的吞吐性能。
一、背景介绍
百分点科技早期的 OSS 整体架构如下图所示,客户端通过 LVS 代理向 OSS 服务上传文件,OSS 服务会根据文件大小路由到不同的存储服务。
由于数据分布广,所以 OSS 服务部署在不同的数据中心,每个中心 OSS 服务(包含存储服务)的集群规模从十几台到五六十台服务器不等,共存储十余 PB 的文件数据。
虽然老版 OSS 通过了海量数据的考验,但针对不同场景仍有不足,具体表现如下:
针对演示环境或中小规模数据场景,HBase 和 Ceph 的混合方案显得过于笨重,对于这类场景,本地文件系统或单节点的 MinIO 即可满足需求;
老版架构层面缺乏设计,仅完成特定场景下的基本功能,不同功能的代码耦合性太强,很难扩展,比如文件类型探测,基于文件元数据的存储路由等;
老版不管文件大小,均使用字节数组存储所有文件,对内存占用过大。
为提升效益,百分点大数据技术团队对老版 OSS 进行了改造升级,新版 OSS 不仅拥有出色的文件存取能力,而且更加灵活,具体亮点功能如下:
全局插件化设计,扩展能力非常好;
高性能的文件类型识别,支持数千种类型,并且支持自定义分类接口;
基于元数据的链式过滤,如基于文件类型或其它元数据对文件进行过滤;
动态限流控制,防止单台 OSS 服务节点压力过大;
动态路由控制,如基于元数据动态路由至后端存储;
支持大量的存储插件,可以基于不同场景进行差异化配置;
丰富的事件通知,如读写通知,读写错误通知,读写性能通知等;
支持 Office 及 PDF 等文档的内容提取;
支持自定义文件元数据信息并保存;
性能增强,充分展现后端存储及网络的 IO 能力。
二、应用设计
1. 整体设计
针对老版 OSS 的痛点,并围绕 OSS 服务功能本身,百分点科技重新设计了 OSS 服务,新版 OSS 的架构如下图所示:
服务编排
Processor 用于编排文件读写逻辑,可调用 Router、Detector、Filter、Storage 和 Notification 接口。所有用户 API 的请求均重定向至 Processor,由 Processor 统一管理。
文件分类
在老版 OSS 服务中,一大使用痛点是文件类型是不可知的,强依赖客户端提供的仅仅几种文件类型信息。因此,在新版设计中,百分点科技引入了文件类型探测的功能,能够探测出文件的具体类型,比如图片会识别为 image/jpg、image/png 等不同的细分类型。
链式过滤
在老版 OSS 服务中,不管文件类型和大小以及来源,上传文件是全部存储的,但是在客户实际使用中,可能只会用到特定部分的数据,所以,百分点科技增加了根据来源,文件类型等的过滤链,过滤到用不到的文件。如果之前不需要某种类型文件,现在需要了,修改过滤规则即可。
动态路由
在老版 OSS 服务中,我们使用 HBase+Ceph 作为后端的存储服务,使用文件大小来决定是存入 HBase 还是 Ceph。但这个逻辑的实现代码耦合性很强,想要增加其他的规则很麻烦。因此,在新服务中将这个功能抽取成路由插件,可以自定义规则实现动态路由。
内容提取
在老版 OSS 服务中,对于 office 和 PDF 类等文档,在 ES 中是索引不到文档内容的,在新服务中,我们在上传文件时增加了文件类型的探测,如果探测到是 office 和 PDF 类等文档,则通过 Tika 提取出内容,最终内容存入到 ES 中就可以检索了。
2. API 接口设计
API 层主要设计了如下几个 API:
上传接口
POST /upload?file_id=eb42cf02-9865-11ec-b909-0242ac120002&file_name=Meeting.pdf
下载接口
GET /download?file_id=eb42cf02-9865-11ec-b909-0242ac120002
批量下载接口
GET /batchDownload{"fileIds": "eb42cf02-9865-11ec-b909-0242ac120002, 629fe326-9868-11ec-b909-0242ac120002"}
配额查询
GET /getAvailableTokens
3. 类接口设计
这样通过接口的方式实现了各个组件的定义,具体的功能实现在具体组件的实现中实现,具有很大的灵活性和扩展性。
如上面类关系图所示,存储可以选择 HBase 或者 S3 协议兼容型的存储。同时,各个组件的选择用配置参数的方式配置在配置文件中,这样切换不同类型存储或者不同消息通知等组件的时候,修改配置文件就可以实现。
4. 配置设计
服务的配置基于 SpringBoot 的 YML 配置文件进行配置,但是为了灵活控制服务各插件的行为和功能,我们使用了 SpringBoot 动态注入 Bean 的方式类来生成具体的插件。比如关于路由器的配置如下:
具体代码如下:
public class SizeBasedRouter implements Router {
private String id;
private String smallFileStorageId;
private String largeFileStorageId;
}
@Bean(name = "router")
@Scope("singleton")
public Router router() throws Exception {
Map<String, Object> config = processorProperties.getRouter();
String klass = MapUtils.getString(config, "class");
Object object = newObject(klass, config);
return (Router) object;
}
private <T> T newObject(String className, Map<String, Object> properties) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
Assert.hasLength(className, "Class property is mandatory");
Class klass = Class.forName(className);
Object object = klass.newInstance();
BeanUtils.populate(object, properties);
return (T) object;
}
5. 插件设计
Processor
Processor 用于编排文件读写逻辑,可调用 Router,Detector,Filter,Storage 和 Notification 接口。所有用户 API 的请求均重定向至 Processor,由 Processor 统一管理。
类图如下:
Detector
Detector 用于文件类型识别。本系统提供 FastDetector,CustomDefaultDetector, ExtraOfficeDetector, FastStringDetector, StringDetector,TokenDetector 和 TextDetector 等。
基于 Tika 类型探测的基础上进行扩展,通过 Stream 头尾字节,综合运用了 Tika 自身和自定义的扩展探测能力,可以实现对上传文件类型的快速探测,不同文件类型的探测能力达到 10w/s,甚至 100w/s。
其中,带 Fast 前缀的为优化版本, 适合海量数据的文件类型探测,单线程探测性能在每秒数万至百万级别。
类图如下:
Filter
Filter 用于文件过滤,因为很多文件是没有价值的图片/js/css/二进制文件等,为了提高 OSS 的整体效率,实现了基于网站和类型的文件过滤功能。
文件过滤正则示例:
"*:+|+text/html|+text/xml|+text/plain|+application/*json*|+application/*xml*|+application/*form*|+message/*|+multipart/*
+application/pdf|+application/*office*|+application/*word*|+application/*excel*|+application/*powerpoint*
+application/*document*|+application/zip|+application/rar|-*/*"
类图如下:
RateLimiter
RateLimiter 用于限流,根据既定规则在请求过载的时候进行限流。类图如下:
Router
Router 用于对读写请求进行路由,以实现大小文件分发、按类型分发等功能,可同时路由到多个存储以实现读负载均衡或双写等特殊场景。此外,Router 方法可返回 null 值,表示该对象被过滤。可包括 SingleRouter,SizeBasedRouter。如果在写时路由变量多于读时路由变量,则可能需要使用缓存记录文件 ID、文件路径及存储 ID 间的关系。
类图如下:
Storage
Storage 用于调用实际的存储组件进行读写,已兼容 HBase,FastDFS 和 Ceph、 SeaweedFS、MinIO 等兼容 S3 协议存储,如果要实现一个服务目前不支持的后端存储,只需要实现相应后端存储的 Storage 插件即可。
类图如下:
Notification
Notification 用于调用各类通知组件,用于读写事件、错误及性能问题的通知,如果需要对文件进行进一步处理,也可以通过 Spark 或者 Flink 消费 Kafka 中的数据进行处理。
类图如下:
6. 监控设计
OSS 服务监控主要使用 Prometheus+Grafana 实现,各组件使用各自 Exporter,或者自身作为 Endpoint 为 Prometheus 提供监控数据,Grafana 负责监控展示。通过监控能够观测到集群的整体运行情况,及时告警出现的问题,方便问题排查。
整体 OSS 服务的监控架构如下:
业务监控
主要是用来监控 OSS 的吞吐情况,如下图,显示的是 OSS 每秒上传文件的个数。
应用系统监控
主要是监控 OSS 服务的内存使用和垃圾回收情况。
后端存储监控
因为使用 HBase 和 Ceph 作为混合存储,因此后端存储监控也分为 HBase 和 Ceph 的监控。
HBase 监控如下图:
Ceph 监控如下图:
三、性能测试
1. 测试目标
通过 Jmeter 进行压力测试,得出 OSS 服务对于不同类型、不同大小文件的吞吐情况,以验证新版 OSS 服务是否达到设计之初的目标,并将测试数据用作后续 OSS 集群规划的重要依据;在压测的过程中通过 Jprofiler 进行观测,找出性能瓶颈点并进行优化,最终提高服务的整体性能。
2. 测试工具
性能压测工具:Apachejmeter
性能分析工具:Jprofiler
监控工具:Prometheus+Grafna
3. 测试环境
组件共使用了 6 台机器,OSS 服务单独使用一台,HBase、Ceph 和 Kafka 部署在 5 台服务器上,具体部署情况如下:
4. 软件版本
5. 测试用例
对于不同类型和大小的测试用例,在 File Path 中指定相应的文件,URL 中最后一个字段为文件名,使用 Jmeter 提供的 UUID 函数随机生成不同的文件名以使文件存入 HBase 不同的 Region 里面。
不同类型的文件分为不同 Jmeter 脚本,如下图所示:
通过对不同类型文件的上传测试可以得出不同类型文件的吞吐情况,因为新版 OSS 服务增加了对无用类型文件的过滤,所以即使相同大小的两个文件,如果其中一个文件被 Filter 组件过滤掉,两个文件的吞吐量会相差很大。
6. 测试结果
在文件没被过滤的情况下,性能基本与老版 OSS 性能持平,不同的文件大小下各有差异;
在多类型文件混合负载测试,性能达到 78,000/s,远远优于老版 OSS,并且在过滤掉数据后能节省不少存储空间。
具体各类型文件的测试结果如下:
结语
新版可插拔 OSS 架构设计不仅拥有出色的文件存取能力,而且更加灵活,文件存储服务是百分点科技常用场景之一,结合数据特点,部署灵活可扩展并且高性能的文件存储服务,不但能更好地满足客户需求,也能在一定业务场景下节省大量的存储服务器,是对相关业务整体解决方案的一大助力。
目前,该方案已经投入到百分点科技 CBB(Common Building Block)等项目建设中,相信随着实践经验的累积和技术的不断优化升级,百分点科技将会为客户提供更加完善的 OSS 服务。
关注公众号:百分点科技,了解更多资讯。
评论