35 | 微博Service Mesh实践之路(上)

上一期我们聊了 Service Mesh 的代表作 Istio,由于 Istio 的设计理念非常新,并且它诞生在微服务容器化和 Kubernetes 云平台火爆之后,所以从设计和实现上,Istio 都天生对云原生应用更友好。

但是现实是不是也是那么美好呢?对于一个已经上线运行多年的业务系统来说,要想从经典的微服务架构走上 Istio 这条看似完美的道路并不容易,各种内部基础设施的定制化以及业务稳定性优先准则等因素,都注定了大多数公司要走出一条自己的 Service Mesh 实践之路。今天就来回顾下微博是如何一步步走向 Service Mesh 的。

跨语言服务调用的需求

在前面讲过,微博的服务化框架采用的是自研的 Motan,Motan 诞生于 2013 年,出于微博平台业务单体化架构拆分为微服务改造的需求,在结合当时的开源服务化框架和自身实际的需求,选择了采用自研的方式。而且由于微博平台的业务采用的是 Java 语言开发,所以 Motan 早期只支持 Java 语言。后期随着微博业务的高速发展,越来越多的 PHP 业务开始登上舞台,于是在微博的流量体系中,主要是三股服务之间的相互调用:一个是 Java 与 Java 语言,一个是 PHP 和 Java 语言,一个是 PHP 和 PHP 语言。Java 应用之间的调用采用的是 Motan 协议,而 Java 应用与 PHP、PHP 与 PHP 应用之间采用的都是 HTTP 协议。我回忆了一下当时一次 PHP 与 Java 之间的 HTTP 调用过程,大致需要经过 DNS 解析、四层 LVS 负载均衡、七层 Nginx 负载均衡,最后才能调用 Java 应用本身。

从上面这张图可以看出,一次 HTTP 调用的链路相当长,从我的实践来看,经常会遇到好几个问题。

第一个问题:中间链路损耗大。由于一次 HTTP 调用要经过 DNS、LVS、Nginx 这三个基础设施,每一层都会带来相应的损耗。我曾经在线上就碰到过因为 DNS 解析延迟、LVS 带宽打满引起的网络延迟,以及 Nginx 本地磁盘写满引起的转发延迟等各种情况,造成接口响应在中间链路的损耗甚至超过了接口本身业务逻辑执行的时间。

第二个问题:全链路扩容难。由于微博业务经常要面临突发热点事件带来的流量冲击,所以需要能够随时随地动态扩缩容。其实在应用本身这一层扩容并不是难点,比较麻烦的是四七层负载均衡设备的动态扩缩容,它涉及如何评估容量、如何动态申请节点并及时修改生效等,要完成一次全链路扩容的话,复杂度非常高,所以最后往往采取的办法是给四七层负载均衡设备预备足够的冗余度,在峰值流量到来时,只扩容应用本身。

第三个问题:混合云部署难。专栏前面我讲过微博的业务目前采用的是混合云部署,也就是在内网私有云和公有云上都有业务部署,同样也需要部署四七层负载均衡设备,并且要支持公有云上的请求经过 DNS 解析后要能够转发到公有云上的负载均衡设备上去,避免跨专线访问带来不必要的网络延迟和专线带宽占用。

因此,迫切需要一种支持跨语言调用的服务化框架,使得跨语言应用之间的调用能够像 Java 应用之间的调用一样,不需要经过其他中间链路转发,做到直接交互,就像下图描述的那样。

Yar 协议的初步尝试

为此,微博最开始考虑基于 Motan 框架进行扩展,使其支持 PHP 语言的 Yar 协议,下面是扩展后的架构图。这个架构的思路是 PHP 客户端的服务发现通过 Nginx 来支持,经过 Nginx 把 PHP 的 Yar 协议请求转发给服务端,由于 Motan 框架中了适配 Yar 协议,服务端会把 PHP 的 Yar 协议请求转换成 Motan 请求来处理,处理完后再转成 Yar 协议的返回值经过 Nginx 返回给客户端。

但这种架构主要存在两个问题。

第一个问题:Motan 协议与 Yar 协议在基本数据结构和序列化方式的支持有所不同,需要经过复杂的协议转换。

第二个问题:服务调用还必须依赖 Nginx,所以调用链路多了一层,在应用部署和扩容时都要考虑 Nginx。

gRPC 会是救命稻草吗

时间往后推演,gRPC 横空出世,它良好的跨语言特性,以及高效的序列化格式的特性吸引了我们,于是便开始考虑在 Motan 中集成 gRPC,来作为跨语言通信的协议。当时设计了下图的架构,这个架构的思路是利用 gRPC 来生成 PHP 语言的 Client,然后在 Motan 框架中加入对 gRPC 协议的支持,这样的话 PHP 语言的 Client 就可以通过 gRPC 请求来调用 Java 服务。

但在我们的实际测试中,发现微博的业务场景并不适合 gRPC 协议,因为 gRPC 协议高度依赖 PB 序列化,而 PHP 对 PB 的兼容性不是很好,在微博的业务场景下一个接口返回值有可能超过几十 KB,此时在 PHP Client 端 PB 数据结构解析成 JSON 对象的耗时甚至达到几十毫秒,这对业务来说是不可接受的。而且 gRPC 当时还不支持 PHP 作为 Server 对外提供服务,也不满足微博这部分业务场景的需要。

代理才是出路

考虑到 PHP 语言本身没有常驻内存控制的能力,在实现服务注册和发现以及其他各种服务框架功能时,仅靠 PHP-FPM 进程本身难以实现,因此需要一个统一常驻内存的进程来帮助完成服务框架的各种功能。一开始我们考虑过使用本地守护进程和 OpenResty 的 Timer 来实现服务发现,但其他服务框架的功能不太好实现,比如专栏前面提到的各种复杂的负载均衡策略、双发、熔断等。为此,我们希望通过一个 Agent 也就是代理,来帮助 PHP 进程来完成服务框架的各种功能,PHP 进程本身只需要负责运行业务逻辑的代码,以及最简单的 Motan 协议解析。基于这个思路,当时我们设计了下面这个架构,它的思路就是在 PHP 进程的本地也部署一个 Agent,PHP 进程发出去的请求都经过 Agent 进行处理后,再发给对应的 Java 应用。

向 Service Mesh 迈进

2017 年,就在开始采用 Agent 方案对业务进行改造,以支持 PHP 应用调用 Java 应用服务化的时候,Service Mesh 的概念突然火热起来,并随着 Istio 的发布风靡业界。相信经过前面对 Service Mesh 的讲解,一定会发现这里的 Agent 不恰恰就是 Service Mesh 中的 SideCar 吗?没错,我们跨语言调用的解决方案竟然与 Service Mesh 的理念不谋而合。借鉴 Service Mesh 的思想,我们也对 Agent 方案进一步演化,不仅客户端的调用需要经过本地的 Agent 处理后再转发给服务端,服务端在处理前也需要经过本地的 Agent,最后再由服务端业务逻辑处理,下面是它的架构图。如此一来,业务只需要进行集成最简单的 Motan 协议解析,而不需要关心其他服务框架功能,可以理解为业务只需要集成一个轻量级的 Client 用于 Motan 协议解析,而繁杂的服务框架功能全都由 Agent 来实现,从而实现业务与框架功能的解耦。

从上面的图中可以看出,这个架构与上一期我们聊的 Istio 大体思路相同,但是区别还是很明显的,可以概括为以下几点:

都通过 SideCar 方式部署的代理来实现流量转发,Istio 里使用的是 Envoy,而 Weibo Mesh 采用的是自研的 Motan-go Agent。这里有一个很明显的区别是,Weibo Mesh 中业务代码还需要集成一个轻量级的 Client,所以对业务有一定的倾入性;而 Istio 采用的是 iptables 技术,拦截网络请求给 Envoy,所以业务无需做任何变更,更适合云原生应用。在微博的业务场景下,由于大部分业务并不是云原生应用,都是部署在物理机或者虚拟机集群之中的,所以需要根据自己的业务特点来决定 SideCar 的部署方式。而且 Weibo Mesh 中的轻量级 Client 除了实现基本的 Motan 协议的解析功能之外,还添加了一些业务需要的特性,比如为了防止 Agent 不可用,在本地保存了一份服务节点的本地快照,必要时 Client 可以访问本地快照获得节点的地址,直接向服务节点 Server 发起调用,而不需要经过 Agent 转发处理,只不过这个时候就丧失了 Agent 的服务治理功能。

Weibo Mesh 和 Istio 都具备服务治理功能,只不过 Istio 是通过 Control Plane 来控制 Proxy 来实现,并且 Control Plane 包括三个组件 Pilot、Mixer 以及 Citedar,三者各司其职。而 Weibo Mesh 是通过统一的服务治理中心来控制 Agent,从而实现服务治理的。这是因为微博本身的各种基础设施大部分是自研的,比如注册和配置中心是自研的 Vintage、监控系统是自己基于 Graphite 改造的、容器平台 DCP 以及负责容量评估的 Diviner 也是自研的,为此需要一个统一的地方把这些基础设施串联起来。而 Istio 好像就为开源而生,设计之初就要考虑如何更好地集成并支持各类开源方案,比如专门抽象出 Mixer 组件来对接各种监控和日志系统。

总结

今天讲解了微博是如何一步步走向 Service Mesh 之路的,从这个过程可以看出微博的 Weibo Mesh 并不是一开始就是设计成这样的,它是随着业务的发展,对跨语言服务调用的需求日趋强烈,才开始探索如何使得原有仅支持 Java 语言的服务化框架 Motan 支持多语言,在这个过程中又不断尝试了各种解决方案之后,才笃定了走 Agent 代理这条路,并实际应用到线上。而随着 Service Mesh 概念的兴起,微博所采用的 Agent 代理的解决方案与 Service Mesh 理念不谋而合,于是在 Agent 代理的方案中吸纳 Service Mesh 的思想,进一步演变成如今的 Weibo Mesh。所以说一个可靠的架构从来都不是设计出来的,是逐步演进而来的。

  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值