为什么需要服务化
当网站流量很小的时候,通常全部功能都部署在一起。等访问量增加到一定程度,把单一应用拆分成几个应用就好了。但随着业务的发展,应用越来越多,越来越复杂,开发团队规模也越来越大,会出现如下几个棘手的问题。
1.代码重复率高。例如 A 产品有一个功能,用户反馈很不错。B 产品也想加进来,这时候 B 产品的工程师会有两种选择:
- 为了快速验证产品,拷贝了 A 的代码再改一改就上线了。拷贝别人的代码,尤其没有非常清晰了解其代码意图时,未来出问题的概率非常高,维护成本也很高。
- 重新实现一遍。需要花费的时间多,还有一个隐患是未来几乎不可能融合两个产品,一般需要重新对 A 和 B 梳理后重新实现。
笔者曾经见过某个功能模块,在不同产品线和同一产品线不同页面有十几个版本。每次需求改动都要对这些模块进行同步修改,到最后不得不花费很大的精力使用统一的实现替换它们。
2.运维成本高。业务没有拆分,哪怕是一个功能模块的小改动也需要对整个业务重新部署上线。
3.可靠性很差。网站页面通常集合了多个产品线的功能,应用之间的交互和依赖不可避免,其中一个产品线出了问题就可能造成全站都不可用。
4.团队协作差。公司越大,推动一些公共技术架构越困难,团队越分越散,最后的结果是很难协调一起开发,大家各自为营。
解决办法如下:
- 业务拆分。把巨无霸业务分拆成一系列小的业务。
- 业务隔离。拆分的业务可以独立地部署、扩容、升级等。
- 业务解耦。通过服务化、订阅/发布机制等手段让应用调用关系解耦。
- 明确业务划分。明确服务调用方和开发维护方职责,通过服务化作为技术契约的约束等方式,让团队间的沟通和共享工作更顺畅。
- 减少重复开发。通过熟悉产品代码的人把关,减少相似功能的立项,再加上一些代码检查工具,减少重复代码。
服务化的划分常常有两种维度:
- 根据业务。比如,豆瓣电影是一个产品线。把豆瓣电影独立成一个服务,被其他产品线使用。整个豆瓣主站再也不会由于一个产品线的问题而让全站不可用。
- 根据功能。豆瓣的读书、音乐、电影等产品线都有长评这个功能。把长评功能独立出来,被这些产品线使用。服务化之后,那些只需要长评功能的产品线不再需要依赖庞大复杂的豆瓣电影服务,直接调用长评服务即可。
RPC 框架
RPC(Remote Procedure Call,远程过程调用)是一个计算机通信协议,此协议允许进程间通信。RPC 框架屏蔽了底层的传输方式(TCP/UDP)、序列化和反序列化(XML/JSON/二进制)等内容,使用框架只需要知道被调用者的地址和接口就可以了,无须额外地为这些底层内容编程。
目前主流的 RPC 框架有如下几种。
- Thrift:Facebook 开源的跨语言框架,在豆瓣内应用广泛。
- Avro:Hadoop 的子项目。
- gRPC:Google 基于 HTTP/2 和 Protobuf 的通用框架。
这个时候可能你会产生疑问:使用 RESTful API 也可以实现和远程服务的通信,为什么要选择 RPC 呢?我们从如下两个方面对比:
- 资源粒度。RPC 就像本地调用方法,RESTful API 每一次添加接口都可能需要额外地组织开放接口的数据,这相当于在应用视图中再写了一次方法调用。而且它还要维护开放接口的资源粒度、权限等。
- 流量消耗。RESTful API 在应用层使用 HTTP 协议,哪怕使用轻型、高效、传输效率更高的 JSON 也会消耗较大的流量,而 RPC 的协议一般使用二进制编码,大大降低了数据的大小,减少流量消耗。
对接异构第三方服务时,通常选用 HTTP/RESTful 等公有协议;对于内部的服务调用,应该选择性能更高的二进制私有协议。
服务化带来的问题
服务化之后,客户端和服务端的交互一般变成了远程网络通信,序列化和反序列化、网络传输等工作势必增加性能损耗,所以客户端在请求中尽量不要包含不需要的服务调用,同时也需要对请求合理地合并来减少网络请求。
服务调用链越复杂,出现问题时就越不好定位,这需要一个分布式跟踪系统帮助我们准确地判断问题。它追踪每个请求的完整调用链路,收集调用链路上每个服务的性能数据。豆瓣服务化的实时分布式跟踪系统 Shuai 是基于 Twitter 开源的 Zipkin(http://bit.ly/2bq57b0 )和 Google 的 Dapper 论文等实现的纯 Python 系统。Zipkin 和 Shuai 都可以把搜集的数据用瀑布的方式在 Web 页面上直观地展示出来,从 Shuai 上能很方便地看到调用链路上每一步做的事情、服务接口信息、使用的代码的具体位置、执行代码所花费的时间等。Shuai 还能生成各种指标图,支持高级查询等。
微服务架构
微服务架构是一种架构模式,它提倡将应用分解为非常小的、原子的微服务,尤其现在云计算、Docker 容器、移动互联网等技术快速发展,并被大量应用,也让微服务这种架构风格越来越受关注,为人使用。
微服务架构的好处如下:
- 每个微服务都专注实现一个特定功能,界限明确。比如上面说的长评功能。
- 微服务可以独立地开发、持续集成和部署。新功能上线周期非常短。
- 可以用不同的开发语言来开发。
- 微服务易于理解,由于功能相对单一,代码量很少,开发人员容易修改和维护,新的团队成员也可以很快融入到开发中。
- 微服务相对没有历史包袱,更容易采用最新的技术(如框架、编程语言、编程实践等)。
但是它也有如下的缺点:
- 显著增加运维成本,因为需要做多得多的配置、部署、扩展和监控的工作。
- 服务数量级别很大,管理整个系统很麻烦。
- 微服务依赖可能影响开发、测试和上线的效率,尤其是集成测试不可避免大量服务的依赖,这需要花费更多的精力来保证接口能正常调用。举个例子,假设有 A、B、C 三个服务,A 依赖 B,B 依赖 C。原来单个服务中直接整合变化,重新部署就可以了,在微服务中需要考虑相关改变对不同服务的影响,还要多考虑修改和上线的顺序。
- 选择不同的开发语言时,如果对性能也有较高的要求,会造成整体链路上的复杂度就呈指数级上升。通常应该标准化一个主要的技术栈(解决 80%的主要问题),只在特殊情况下允许少量的差异化生产(20%的特殊情况)。
微服务更适合规模较大的公司或者研发团队。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论