当前位置: 首页 > 科技观察

架构师必读京东东东架构演进

时间:2023-03-20 12:31:10 科技观察

什么是东东?东东之于京东,就像旺旺之于淘宝。它们都服务于买卖双方之间的沟通。自从京东开始为第三方卖家提供平台服务,东东就诞生了。我们先来看看它诞生时的样子。1.0的诞生(2010-2011)为了快速上线业务,1.0版本的技术架构实现非常直接简单。多么简单粗暴?请看架构图,如下。1.0的功能非常简单,实现了IM的基本功能,如访问、消息交换、状态。此外,还有客服功能,是客户接入咨询时的客服分配,以轮询的方式分配客户在线客服接待。采用开源Mina框架实现TCP的长连接访问,通过TomcatComet机制实现HTTP的长轮询服务。消息投递的实现是一种生产消费模型,一端发送的消息暂存在Redis中,另一端拉取。此模型的方法导致需要以高频方式轮询Redis以获取属于其自身连接的关联会话消息。这个模型非常简单,简单包括多个层次的含义:简单易懂;开发简单;易于部署。只需要一个Tomcat应用,依赖一个共享的Redis,简单实现核心业务功能,支持业务快速上线。但是这个简单的模型有一些严重的缺陷,主要是效率和扩展问题。轮询频率间隔基本上决定了消息的延迟。轮询越快,延迟越低,但轮询越快,消耗越高。这个模型实际上是一个高功耗低性能模型,因为不活跃的连接在那里做高频无意义的轮询。高频多高,基本在100ms以内,不能让轮询太慢,比如超过2秒,聊天的时候人会感觉到明显的session延迟。随着在线用户数的增加,轮询时间也线性增加。因此,这种模式导致扩展性和承载能力较差,随着在线用户数量的增加,必然会遇到性能瓶颈。1.0时代背景是京东技术平台从.NET向Java过渡的时代。正是在这段时间,我加入了京东,参与了京东主站的技术改造和架构升级的过程。之后开始接手京东东东,并不断完善这款产品,进行了3??次技术架构演进。2.0成长(2012年)我们刚接手的时候,1.0已经上线了,支持京东的POP(开放平台)业务。之后,京东计划组建自己的在线客服团队,落地成都。无论是自营还是POP客服咨询业务刚刚起步,1.0架构中的性能和效率缺陷还没有达到引爆的业务水平。自营客服当时还处于起步阶段,客服人员数量不足,服务能力不够,客户咨询量远远超过客服的服务能力。对于超出我们服务能力范围的客户咨询,我们系统统一返回提示客服忙,请稍后咨询。这种情况导致大量客户在高峰期,无论怎么刷新请求,都可能无法接入客服,体验很差。因此,2.0着重于业务功能体验的提升,如下图所示。对于不能及时提供服务的客户,您可以排队或留言。对于纯文本的交流,提供了文件、图片等更丰富的表达方式。此外,还支持客服转接和快速回复,提高客服接待效率。总之,整个2.0都是围绕提升客服效率和用户体验展开的。我们担心的效率问题在2.0业务高速发展时期还没有出现,但业务量在逐渐积累,我们知道它即将爆发。2012年底,双十一之后,开始了3.0的重大结构升级。3.0的爆发(2013-2014)经历了2.0时代业务高速发展的一整年,代码规模实际上也在快速膨胀。伴随着代码,团队也扩大了,从最初的4人扩大到近30人。团队成长后,一个系统会由开发人员不同层次的多人开发,规范难以统一,系统模块耦合度高,变更、沟通、依赖多,上线风险大难以控制。单个tomcat应用的多实例部署模式终于告一段落了。本次版本架构升级的主题是面向服务。服务化的第一个问题是如何将一个大的应用系统拆分成子服务系统。当时的背景是京东的部署还处于半自动化时代,自动化部署系统才刚刚起步。如果子服务系统被拆分成太多的子服务系统,部署工作量大,难以管理。所以当时我们并没有按照业务功能划分服务,而是按照业务重要程度划分了0、1、2三个不同级别的子业务服务体系。另外,一套接入服务是独立的,针对不同信道和通信方式的接入终端,见下图。下图可以看到更详细的应用服务和架构分层方法。此次重大架构升级主要考虑了三个方面:稳定性、效率和容量。做了以下事情:业务分类、核心与非核心业务隔离、多机房部署、流量分流、容灾冗余、峰值响应冗余读库多源、写库主备故障自动转移、短期损伤服务容忍对外接口快速切换,Redis主备故障切换或快速断开,故障切换和大表迁移,MongoDB替代MySQL存储消息记录,改进消息传递模型。前6项基本上是考虑系统稳定性和易用性的改进和升级。这部分是迭代完成的,承载很多failover的配置和控制功能由上图中的管控中心提供。第七条主要是随着业务量的增加,单日消息量越来越大,使用MongoDB分别存储最大量的聊天记录。第8条是针对1.0版本消息轮询效率低下的改进。改进后的下发方式如下图所示:不再是轮询,而是让终端在每次连接建立后注册接入点的位置。定位连接所在接入点的位置,推过去。这样,交付效率是恒定的,并且易于扩展。在线的人越多,联系就越多。您只需要扩展接入点。其实这个模型还是有一些小问题的,主要是在离线消息的处理上。你可以先想一想,我们最后再说。3.0经历了两年的迭代升级,单从业务量上来说已经可以长期支撑增长。但实际上,到2014年底,我们面临的已经不是业务量的问题,而是商业模式的转变。这直接导致了一个全新时代的到来。4.0Nirvana(2015年至今)2014年,京东的组织架构发生了很大的变化,从一个公司变成了拥有多个子公司的集团。原商城成为子公司之一,新成立的子公司有京东金融、京东智能、京东到家、拍拍、海外事业部等,各自的业务范围不同,业务模式也不同,但无论他们总是需要客户服务什么样的业务。如何复用原本为商城量身打造的东东客服系统,支持其他子公司业务的快速接入,成为我们新的课题。最早请求接入的是拍拍网,它是从腾讯手中收购的,因此拥有完全不同的账户和订单交易系统。由于时间关系,我们剥离掉了为商城定制的部分,基于3.0架构为拍拍单独定制了一套,独立部署,如下图。虽然在业务要求的时间之前就完成了上线,但也带来了明显的问题:项目重复、定制化业务开发、多套源码维护成本高且独立部署,至少双机房主备加灰度集群以前我们都是为了业务做系统。现在,在业务变革的新形势下,我们开始考虑面向平台的架构,将多套业务跑在一个统一的平台上,统一源码,统一部署,统一维护。继续拆分业务服务,剥离出最基础的IM服务、IM通用服务、客服通用服务,针对不同业务的特殊需求开发最小化定制服务。部署方式以平台的形式进行部署。不同业务方的服务运行在同一个平台上,但数据相互隔离。服务继续拆分成更细的粒子,形成一组服务矩阵(见下图)。至于部署方式,只需要在双机房建立两套对等集群,搭建一个更小的灰度发布集群即可。所有不同的服务都运行在统一的平台集群上,如下图所示。更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。但是,更细粒度的服务也意味着更繁琐的运维监控和管理。直到今年,公司内部的弹性私有云、缓存云、消息队列、部署、监控、日志系统日趋完善,使得这种细粒度划分的微服务架构的实施成为可能,运维和维护成本可控。从1.0的1个应用进程,到3.0的6、7个应用进程,再到4.0的50+更细粒度的不同应用进程。每个进程根据业务承载的流量分配不同数量的实例,实际实例进程数会上千。为了更好的监控和管理这些流程,为此专门定制了一个面向服务的运维管理系统,如下图所示。统一服务运营提供有用的内部工具和库来帮助开发更强大的微服务。包括中心配置管理、流量埋点监控、数据库和缓存访问、运行时隔离,如下图是操作隔离的示意图:细粒度的微服务实现进程间隔离,严格的开发规范和工具库助力异步消息传递和异步HTTP的实现是为了避免跨进程的多个同步长调用链。流程中引入服务增强容器Armor,通过切面隔离线程,支持流程内单个业务降级和同步转异步执行。而所有这些工具和库服务都是为了两个目标:让服务进程的运行时状态可见,让服务进程的运行时状态可以被管理和改变最后,我们回到上一篇文章留下的悬念,就是关于消息传递模型的缺陷。一开始我们在接入层检测到终端连接断开后消息无法下发,然后缓存消息,等终端重连后拉取下线消息。这种模式在移动时代表现不佳,因为移动网络的不稳定往往会导致断线重连。网络连接断开的准确检测依赖于网络超时,这可能导致检测不准确和错误的消息传递成功。新模型如下图所示。它不再依赖准确的网络连接检测。缓存投递前待确认消息的id,消息体持久化。终端收到确认返回后才认为消息已提交,未确认的消息id将在重新登录或重连后作为离线消息推送。该模型不会造成消息误投递造成的损失,但可能会导致消息重复,只需要客户端根据消息id进行去重即可。京东东东诞生之初,正值京东技术向Java过渡之时。经过这些年的发展,取得了长足的进步。从草根到专业,从小到大,从分散到统一,从杂乱到规范。本文主要关注东东架构这几年的演进过程。我觉得单看技术架构没有绝对的好坏。技术架构必须始终放在当时的背景下看待,业务的时效性必须考虑团队的价值、规模和能力、环境基础设施等。只有架构演进的生命周期及时匹配业务的生命周期,才能达到最好的效果。