雪球首席架构师唐福林:雪球服务化实践历程

服务化的话题在两三年前很热,众多公开场合都在说,最开始是亚马逊、Twitter,紧接着就是国内的淘宝、微博都在谈服务化。在这之后,感觉这个话题慢慢趋向过时,之所以有这样的感觉一是大公司或因人员流动或其他各种关系大家做的服务化都大致相似,二是当下并没有大量的创业公司有这样需求。其实每年都会有一些正在从小到大的成长,这个过程中总会碰到服务化的问题,是绕不过的。

当一些初创公司遇到人员、业务、流量等膨胀之时,还是需要有类似的解决方案来借鉴。遇到这样的问题,如何解决,马上解决还是缓一缓再做。每当这个时候,看淘宝怎么做,微博怎么做其实并不适合初创公司的场景。因为所面临的问题不一样,如人数,背景做事方式等都有所不同。在由高招主办的“CTO训练营”活动现场,雪球首席架构师唐福林分享了其公司在面对这个问题的时候是如何做的。他表示,这其实痛定思痛或说是反思。雪球的解决方案也并不是很理想,但可以给大家做一个前车之鉴。

关于雪球,关于唐福林

演讲开始,唐福林简单介绍了雪球的发展和自身的经历。

雪球,一个聪明的投资者的社区,有Web1.0:新闻资讯,股价信息,K线图、Web2.0:SNS 订阅,分享,聊天、Web3.0:移动APP,交易闭环等业务,还有非互联网业务,如做资产管理,私募工场,是一个典型的创业公司。雪球当前员工数刚好过100,其中技术人员占50%。现在的技术栈由Java,Scala,Akka,Finagle,Nodejs,Docker ,Hadoop组件组成。当前是租用IDC机房自建私有云,正在往“公私混合云”方向发展。

[[165041]]

唐福林,雪球首席架构师,负责雪球大数据体系建设及服务性能与稳定架构优化工作。曾任微博平台资深架构师,微博技术委员会成员,深度参与微博快速增长期的性能和稳定性问题解决。

雪球服务化历程

在讲雪球服务化历程之前,唐福林简单介绍了雪球公司业务的发展历程,如下图:

雪球首席架构师唐福林:雪球服务化实践历程插图

服务化历程之雪球技术发展

上图为,以2012年初为基准,雪球的团队人数,服务个数和代码行数的增长趋势。

服务化历程之技术演进

唐福林表示,最初整个雪球服务是在一个大一统的工程里实现,内部命名为Snowball ,就是滚雪球的意思。 Snowball系统从 2012年到2013年初一直运转良好。但随着2013年业务的膨胀,代码的增长,团队的扩张,渐渐出现了很多问题,比如重复代码,比如代码不够规范,比如测试困难,比如沟通成本越来越高,比如不相干的功能在实现上存在耦合等。

  • 针对业务膨胀。开始了模块化改造,将底层基础模块抽取成公共库,做到代码级的服用;
  • 针对代码量增长过快。采取了一种在国内互联网公司不太常见的措施:引入一种描述能力更强的语言 scala。简单来说,它是一种 jvm 上的混合语言,混合了面向对象编程和函数式编程两种方式,它的编译器其实就是一个 jar 包,源码会被编译成跟 java 一样的 bytecode,然后在 jvm 上运行。在 scala 中,可以无缝的调用绝大多数 java 的库。scala 语言的描述能力很强,平均下来,同样的逻辑,scala 语言实现大概会是 java 实现长度的 1/5 到 1/10 的样子。
  • 针对团队的扩张。开始推行一种工程师文化:鼓励大家使用新的更好的技术和工具,鼓励大家制造更多的工具和轮子,鼓励大家交流分享。

唐福林在演讲中说到:“在那个时候,推行工程师文化的两个重大结果,一是在线上服务和基础设施层引入了 scala,二是在基础设施层引入了 docker 。这两个决策在现在看来,当时的引入肯定是没有经过深思熟虑的,后来的一路上也是踩了不少坑,当然也付出了很大的时间和精力代价。但是当回过头去看的时候,还是很庆幸引入了这些基础设施,它们既帮助雪球完成了功能,方便了部署,也帮助雪球在技术上有了积累,在团队上有了进步”。

随着时间的推移,虽然采取了上述一系列的措施,问题有了一定程度的缓解。但随着业务继续加速膨胀,代码加速增长,团队加速扩展,问题还是不可避免的越来越严重。这时候雪球到了一个大的关口:流量增长到一定程度,代码模块之间开始互相影响,一个模块的性能问题很快扩散到影响全站访问,git 分支合并开始频繁出现冲突,开发迭代速度明显受影响。另外一个比较严重的问题是,不同的模块带进来的第三方依赖偶尔产生冲突,解决起来很麻烦。面对这样的严重的问题,雪球很对采取了进一步的对症下药:

  • 对稳定性,性能互相影响的问题,标准解法是切分流量单独部署
  • 代码合并冲突,第三方依赖的标准解法就是:服务化拆分。

唐福林在演讲中说到:“对于像雪球这样的小公司,服务器不多,服务化拆分后会严重增加部署成本,包括线上和测试环境。针对这个问题,当时采取的办法是:Docker 容器化。现在大家可能觉得这也是一个标准解法了。但在两年前,Docker 的版本号还小于 1.0,这样的选择,不能不说是具有相当的前瞻性的”。

服务化历程之服务化框架选择

做服务化,就面临一个服务化框架的问题。自己开发的选项是早早就被放弃了,毕竟公司所有技术人员加起来,都不如淘宝开发 dubbo 的团队人多。 选一个现有的?因为已经引入了部分 scala 业务代码,rpc 框架也必须要支持 scala 才行。理论上,所有纯粹的 java rpc 框架,scala 也都能用,但是,想要以纯粹的 scala 的方式写代码的话,调用java方法和处理java的参数,返回值对象的时候,都需要转一下才行。另外一个考虑因素就是,这个框架必须是开源的,经历过大厂验证过的。最后,选定了 finagle 。

雪球首席架构师唐福林:雪球服务化实践历程插图1

服务化历程 - Finagle 介绍

Finagle支持多协议适配,对 client 端和 server 端来说,它具备标准的连接池,失败检测重试,负载均衡,监控统计,追踪,分区 etc。

它的编程模型如下:

  • 所有的客户端操作都返回一个 Future,也就是说,所有操作都是异步的,可以往 Future 里面放 callback 回调,也可以把多个 Future 串起来。
  • 所有的服务抽象成一个个的 Service:每个 service 的输入都是接收一个 request,返回都是一个 Future[Response]。
  • 所有的策略实现都是一个个的 Filter,Filter 是包装在 service 外面的。

服务化历程之尝试、推广、升级、服务治理、收尾

唐福林表示,Fnagle看起来功能强大,又非常符合当时的各种期望。于是,就引入雪球。之后经过尝试、推广、升级、服务治理和收尾等环节,直到2015年9月,Finagle架构如下如:

雪球首席架构师唐福林:雪球服务化实践历程插图2

2015年9月 Finagle架构图

未来与微服务化

当前这个方案最大的问题,还是在于开发团队的hold程度,简单来说,Scala是一门会用不难,会用好还是挺难的编程语言,所以,用它写业务逻辑问题不大,但用它来写基础设施,那就需要一个精炼的技术小组才能搞定了。而 finagle 呢,Twitter 的那些开源代码开发人员,那是相当的炫技,有的时候,团队里对 finagle 最精通的人,也会忍不住连连赞同。

唐福林演讲中说到:“雪球的 scala 技术团队免不了有一些人员更替,有转产品的,有转管理的,有转去做另外的业务项目的,导致后面的框架升级和二次开发力量严重不足。加上 finagle 自己迭代速度快,向后兼任又差,整个一个 no zuo no die why you try 的感觉”。于是,唐福林个人花了差不多两周的时间,做了一个简单版本 rpc 框架的尝试。得益于在微博做 motan 框架的经验和教训,框架开发很快,开发出来后,拿给整个技术团队做讨论的时候,才发现问题很多:再后来,团队在针对 rpc 框架的接下来需求的讨论过程中,越讨论越觉得方向有一些偏:大家对基础设施需求的重点并不是在 rpc 调用框架,而更多在于:大量的小服务,开发业务逻辑的便捷性,升级基础包的便捷性,单节点的运行状态,数据收集,监控报警的便捷性等等。于是,在未来,会把接下来服务化工作的重点定义成:微服务化,具体来说,就是开发并维护一个满足雪球自己业务需要的微服务容器。

思考和教训

当服务到了一定程度,做服务化是肯定的。但不建议自己做服务化框架,可以找一个比较成熟一点的东西来做。稳定性和可用性是一个最重要的工作。做服务化拆分时会引起稳定性和可用性下降,更何况如果拆了很多个不同的服务,由不同的人去维护,很容易出问题,所以一定要重视单个节点的一致性。 可以尝试新技术,但要保证技术先进性与技术栈一致性。之后,唐福林还从技术深度与技术新鲜度、团队扩张和成员更替、个人兴趣和团队合作等方面分享了很多宝贵的经验。

在演讲最后,唐福林提到了细节和规范。他说:“想要用好一个框架,有很多细节需要仔细注意的。如 finagle 的重试逻辑,跟我们平常说的不太一样,retry=3 的时候,并不是重试三次,而是加上第一次尝试,一共三次,也就是说重试2次。 在使用开源框架的时候,首先遵守框架本身的规范,开源社区的规范,然后在这个基础上,制定自己(小团队)的规则,或者叫使用约定。规则成熟后,最后形成固定的(公司大团队)的规定。”

了解更多训练营内容:http://x.

THE END