我们的产品架构

本文是我在中生代技术群分享的话题《创业一年经历的技术风雨》中的第一部分《产品架构与技术选型》的第一部分。

整体架构

我们的产品代号为Mort(这个代号来自电影《马达加斯加》那只萌萌的大眼猴),是基于大数据平台的商业智能(BI)产品。产品架构如下所示:

我们选择了Spark作为我们的大数据分析平台。基于目前的应用场景,主要使用了Spark SQL,目前使用的版本为Spark 1.5.0。我们有计划去同步升级Spark最新版本。

在研发期间,我们从Spark 1.4升级到1.5,经过性能测评的Benchmark,性能确有显著提高。Spark 1.6版本在内存管理方面有明显的改善,Execution Memory与Store Memory的比例可以动态分配,但经过测试,产品的主要性能瓶颈其实是CPU,因为产品的数据分析功能属于计算密集型。这是我们暂时没有考虑升级1.6的主因。

从第一次升级Spark的性能测评,以及我们对这一年来Spark版本演进的观察,我们对Spark的未来充满信心,尤其是Tungsten项目计划,会在内存管理、代码生成以及缓存管理等多方面都会有所提高,对于我们产品而言,算是“坐享其成”了。

由于我们要分析的维度和指标是由客户指定的,这就需要数据分析的聚合操作是灵活可定制的。因此,我们的产品写了一个简单的语法Parser,用以组装Spark SQL的SQL语句,用以执行分析,最后将DataFrame转换为我们期待的数据结构返回给前端。

但是,这种设计方案其实牵涉到两层解析的性能损耗,一个是我们自己的语法Parser,另一个是Spark SQL提供的Parser(通过它将其解析为DataFrame的API调用)。我们考虑在将来会调整方案,直接将客户定制的聚合操作解析为对DataFrame的API调用(可能会使用新版本Spark的DataSet)。

微服务架构

我们的产品需要支持多种数据源,对数据源的访问是由另外一个standalone的服务CData完成的,通过它可以隔离这种数据源的多样性。这相当于一个简单的微服务架构,目前仅提供两个服务,一个服务用于数据分析,一个服务用于对客户数据源的处理:

未来,我们的产品不止限于现有的两个服务,例如我正在考虑将定期的邮件导出服务独立出来,保证该服务的独立性,避免受到其他功能执行的影响。因为这个功能一旦失败,可能会对客户的业务产生重要影响。

然而,我们还是在理智地控制服务的粒度。我们不希望因为盲目地追求微服务架构,而带来运维上的成本。

元数据架构

我们的产品需要存储元数据(Metadata),用以支持Report、Dashboard以及数据分析,主要的数据模型结果如图所示:

针对元数据的处理逻辑,我们将之分为职责清晰的三层架构。自上而下分别为REST路由层、应用服务层和元数据资源库层。

  • REST路由层:将元数据视为资源,响应客户端的HTTP请求,并利用Spray Route将请求路由到对应的动词上。路由层为核心资源提供Router的trait。这些Router只负责处理客户端请求,以及服务端的响应,不应包含具体的业务逻辑。传递的消息格式为Json格式,由Spray实现消息到Json数据的序列化与反序列化。
  • 应用服务层:每个应用服务对应元数据资源的操作用例。由于Mort对元数据的操作并没有非常复杂的业务逻辑,因此这些服务实际上成为了Router到Repository的中转站,目的是为了隔离REST路由层对元数据资源库的依赖。每个服务都被细分为Creator、Editor、Fetcher与Destroyer这样四个细粒度的trait,并放在对应服务的同一个scala文件中。同时,应用服务要负责保障元数据操作的数据完整性和一致性,因而引入了横切关注点(Cross Concern Points)中的事务管理。同时,对操作的验证以及权限和授权操作也会放到应用服务中。
  • 元数据资源库层:每个资源库对象都是一个Scala Object,并对应着数据库中的元数据表。这些对象中的CRUD操作都是原子操作。事实上我们可以认为每个资源库对象就是元数据的访问入口。在其实现中,实际上封装了scalikejdbc的访问逻辑。

REST路由层和应用服务层需要接收和返回的消息非常相似,甚至在某些场景中,消息结构完全相同,但我们仍然定义了两套消息体系(皆被定义为Case Class)。逻辑层与消息之间的关系如下图所示:

在REST路由层,所有的消息皆以Request或Response作为类的后缀名,并被定义为Scala的Case Class。在应用服务层以及元数据资源库层使用的消息对象则被单独定义在Messages模块中。此外,元数据资源库层还会访问由ScalikeJDBC生成的Model对象。

原文发布于微信公众号 - 逸言(YiYan_OneWord)

原文发表时间:2016-04-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码洞

深入理解RPC——RPC在企业服务中的核心价值

随着企业 IT 服务的不断发展,单台服务器逐渐无法承受用户日益增长的请求压力时,就需要多台服务器联合起来构成「服务集群」共同对外提供服务。同时业务服务会随着产品...

541
来自专栏架构师之旅

Mysql在大型网站的应用架构演变

写在最前: 本文主要描述在网站的不同的并发访问量级下,Mysql架构的演变 可扩展性 架构的可扩展性往往和并发是息息相关,没有并发的增长,也就没有必要做高可扩展...

1668
来自专栏JAVA高级架构

浅谈架构之路:前后端分离模式

前言:分离模式   对前后端分离研究了一段时间,恰逢公司有一个大项目决定尝试使用前后端分离模式进行,便参与其中。该项目从2016年初立项至今,平平稳稳得度过,但...

3746
来自专栏JAVA高级架构

Java程序员该如何突破瓶颈,成长为优秀的架构师

732
来自专栏Java技术

为什么说程序员到了不得不掌握RPC的时候了!

随着企业 IT 服务的不断发展,单台服务器逐渐无法承受用户日益增长的请求压力时,就需要多台服务器联合起来构成「服务集群」共同对外提供服务。同时业务服务会随着产品...

802
来自专栏企鹅号快讯

分库分表架构实践

作者介绍: 丁浪,现就职于某垂直电商平台,担任技术架构师。关注高并发、高可用的架构设计,对系统服务化、分库分表、性能调优等方面有深入研究和丰富实践经验。热衷于技...

2529
来自专栏Coding01

「转」论微服务架构

微服务现在辣么火,业界流行的对比的却都是所谓的Monolithic单体应用,而大量的系统在十几年前都是已经是分布式系统了,那么微服务作为新的理念和原来的分布式系...

654
来自专栏架构师之路

服务通过缓存传递数据,绝不推荐

《服务通过缓存传递数据,是否可行》一文引发一个服务之间“通过缓存传递数据”设计合理性的讨论。 ? 如上图: service-A将数据放入cache servic...

2844
来自专栏ThoughtWorks

Web App性能优化之亮剑|洞见

自计算机诞生以来,系统性能问题亘古未变,从指令级优化到集成系统的优化,可谓愈来愈复杂。每种类型的性能问题即便出现的场景不尽相同,但依然有一些性能优化模式,久经沙...

3236
来自专栏飞总聊IT

苹果公司开源FoundationDB的简单分析

美国时间 2018年4月19日,苹果公司宣布开源FoundationDB。FoundationDB 本来是一个开源项目,于2015年被苹果收购以后,其代码从Gi...

952

扫描关注云+社区