通往创新之巅:互联网技术架构创新案例和实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

t1

架构再升级:向一致性与可预测性的进击

这套策略当然也是有局限性的。业务需求有其内在的复杂性,技术上能做的简化同样有限,而且随着多年的技术债务积累,(重要)客户越来越多,团队也越来越壮大,快速简单的原则有时就不太可行了。一致性和可预测性则愈发重要。因为同时变动的模块有很多且经常互相依赖,如果不能按时按质的完成,就整合不到一起。因此,架构的策略也逐渐从“求快求简”向“求稳求准”过渡。2013年左右是FreeWheel的分水岭。最后的一个快速项目是用LevelDB和Memcached做了一个KV store,来存储用户投放数据,后来因为性能问题存储换成了RocksDB,最后又换到了带有商业支持的Aerospike,因为集群管理、复制和容错之类的工作没有太简单的方案。

架构策略的改变还有一个原因,就是技术基础设施的进一步发展而走向成熟。数年内我们见证了不少技术上的起伏,比如Flash的消亡,Chrome的崛起,移动端更是喊出了Mobile First的口号,Rails已经不再热门,业内将展示都迁移到客户端,而JavaScript就更不必说了,jQuery也已经成为过去时,AngularJS经历了一个起伏的周期,ReactJS已经成为了半个缺省配置,GCC的版本已经升级到7,新的项目都至少用上了C++ 11。在大数据方面,Hadoop 2也推出一段时间了。在Cloud和集群管理方面,AWS/Docker已经非常流行,而Kubernetes也抢占了很大的份额。唯一的例外可能是Python 2,基本上还活着。要适应新的架构策略,我们也需要升级系统的基础设施。

FreeWheel在2014年开始讨论和准备基础技术架构的升级,之后就开始逐步实施。相应的方向选择其实相当主流化,无非就是搜索引擎上最为热门的几个:

• 容器化和服务化管理平台。前者是Docker,后者在Kubernetes出现以后就很自然了。同时我们还开始尝试把系统迁移到AWS上。

• UI系统的前后端分离,前端往浏览器端展示迁移,后端则API服务化。前者选用了ReactJS,关于后者曾经有过讨论。我们从2012年开始尝试Golang。Golang从语言、库、社区、支持工具各个方面都不错,但是有工程师提议想尝试Elixir。考虑到一致性以及之前对Erlang的体验,这个基本没有争论,很快就决定采用Go,并且同样是出于一致性的考虑,决定使用gRPC和Protocol来标准化。

• 数据处理,Hadoop显然是缺省选择了。这里值得一提的有两点:第一是缺省用Golang而不是Java,这点是考虑到Golang是公司层面的缺省选择,并且我们没有太多Java的经验;第二是尽量避免使用ETL流程,而是存储最细粒度的数据,动态地通过SQL生成结果。这点考虑主要是基于之前对数据维护成本的经验。维护大量的中间数据(ETL的结果)对于数据一致性的验证和检查,需求变动的响应,以及数据的导入,都有很高的要求。而随着计算成本的降低,在原始数据上查询是很自然的想法。我们用Presto搭建Log查询系统从而验证了这个思路。此系统应该是内部使用最多的系统。

• 广告服务器和预测系统。该方面的技术基础改变不大,主要是模块化,并且尽量使用更新的工具,比如编译器和静态检查工具。我们从GCC 4.1升级到GCC 4.8,之后更是直接切换到了Clang。同时新的代码都用上了C++ 11。预测系统也有一些改进,包括对机器学习的利用,C++11以及对基于Hadoop数据平台的尝试。同时,一些新的内部支撑服务,我们都开始缺省用Golang来实现。

架构升级还在进行中,大致到2018年年底完成。风险和质量显然是这次升级的最关键考虑因素。如前所述,一致性和可预测性是我们目前最关注的两点。对于前者,我们使用一致的技术栈(缺省使用Golang),更多形式化的定义(数据库Schema, Log和API的Protocol Buffer定义等),更多的测试(包括单元测试和回归测试等),以及更强的Code Review来保证。而对于后者,主要是通过更多的量化,包括更多的指标评估和更多的监控来保证,比如延迟、吞吐量,数据大小等。更实时的数据,更多对系统的洞察,其实都是业界的趋势。当然,架构升级在进行中,也遇到了不少问题,比如需求的变动、计划的变化、依赖服务的不稳定性,还有人员的变化等等。我们所做的,也就是在设计的时候尽量简化,留有余量,在执行的时候开阔思路及时调整。