BT

Office 365架构演变及微服务实践

| 作者 虞雷 发布于 2017年3月21日. 估计阅读时间: 1 分钟 |

天下大势,分久必合,合久必分。三国演义开头的这句话是对Office 365整体架构的演变最生动的概括。

互联网业界的同行,对微软存在偏见甚至鄙视者大概不算少数,也许会觉得标题里的微服务(micro-services)貌似是个多少有点潮的概念,好像和微软的技术形象有点不符,更何况是Office 365这样历史悠久的庞然大物。但事实上,微软很多团队都是与时俱进的,而Office 365架构的分分合合某种程度上也能侧面反应这一点。

Office 365是一个多义词,本文讨论的Office 365是以Exchange Online为核心的一系列Office online services产品,从技术范畴上并不包括普通用户所熟悉的Office客户端产品,例如Word和Excel,当然也不是微软以每年授权的方式销售给个人用户的套装。

DVD盒装软件时代

Office 365的前身是Exchange Server(以下简称Exchange),是一个非常典型的on-premise的企业电子邮件服务器,早些年和IBM Lotus Notes以及Novell GroupWise竞争。第一个正式的版本是在1996年,可以想象那个时候的软件基本是跑在单台服务器上的,邮件数据也是存在本地硬盘或者SAN。后来Active Directory分离出去成为Windows Server 2000的一部分以后,就有了分布式系统的架构,而且AD Domain Controller也可以是和Exchange独立的role。Exchange 2000可以支持8个节点的集群。这个时期的架构,已经可以称为scale out的一个例子,但每台服务器的角色都是等同的,所以是“合”的时期。

Exchange 2003开始支持通过internet的客户端,包括基于web的访问方式,于是有了Front End和Back End两种server role。Web界面的Outlook Web Access,Outlook客户端用的RpcHTTP,IMAP,POP等协议头被放在了Front End上,前面还有Network Load Balancer。这个时期已经开始了“分”的时期。到Exchange 2007和Exchange 2010时候,一共有了Mailbox, Client Access, Hub Transport,Edge Transport, Unified Messaging多个服务器角色。其中数据主要存放在Mailbox Server上,并且用软件实现了High Availability,包括replication和跨地域failover。之前的Front End变成了Client Access,通过MAPI RPC访问Mailbox Server上的数据,而邮件中转的处理交给了Transport服务器。这个版本的Exchange把“分”的模式又增近了一步,而这种架构作为on-premise软件来讲已经属于相当现代和成熟的模式。

(点击放大图像)

图片引用自technet.microsoft.com

软件即服务

Exchange 2010的代码同时是被用来搭建Office 365 Exchange Online云服务的第一个版本。由于Exchange 2010本身的企业版本已经能够支持大型跨国公司所需要的大规模跨地域集群,所以放进数据中心里运行的时候核心代码几乎就可以直接工作。最大的修改主要在于客户的组织目录结构的分区上,另外还有身份验证方式的改变。个人认为这个可以作为业内成功的SaaS的案例之一,真实地将一个software改成了online service,而且用的同一套代码。值得提及的一点是,这个时候微软的三大云服务部门,Azure,Bing,Office几乎是互相独立的,从数据中心基础架构到自动化部署,监控等都是各自运行自己的系统。

Exchange这样的架构在企业客户的环境下是比较容易控制的,但作为在线服务时候,由于自动化工具的不够完善,用户增长和访问峰值的变化,对各个服务器角色所需的数量和硬件配备的预估和计算就有些复杂,尤其在发生紧急情况需要failover时候需要兼顾到所有类型服务器的运行和访问模式。另外涉及到用户交互的Client Access需要遵循数据最近原则,所以用户最重得到的URL都是具体到各个数据中心的,在某些情况下甚至会改变,需要通过302重定向,proxy或者AutoDiscover等手段来作补充。

从Exchange 2013开始,虽然online和on-premise的代码还是同一份,大量的开发工作开始集中于云服务下的场景,而这个时期的架构又发生了重大的调整。首先把Client Access, Hub Transport和UM都搬到了Mailbox Server上,成为一个统一的shard,进一步强调数据就近原则,并提出了每个服务器都是孤岛的原则,要求跨节点的访问必须通过HTTP而并非RPC。这个版本里引入了一个专门用来做HTTP反向代理的部件,用来分发所有HTTP的协议,代替了之前L7硬件Load Balancer的大部分工作,也实现了URL的全球统一域名。

(点击放大图像)

图片引用自technet.microsoft.com

这种设计相比之前多个server role极大地简化了部署和扩容模型,被称为“砖块”架构,用来形容每台服务器的同质化和标准化。就像盖房子只需要一种砖块一样,新的集装箱式服务器运到数据中心后可以很简单完成部署,加入集群。负载均衡也被统一和简化成基于用户数据所在的shard为核心,也就是说,当服务器上的某些进程开始有CPU或者内存压力的时候,只需要简单地将原先分配到这个shard上的一些用户无断点迁移到另一些服务器组上。当然,所谓用户所在的shard也是一个动态的概念,由于新版本部署等原因用户数据所在的物理机器其实每天都可能改变数次。在“分”了大概十年以后,数据单元的计算和存储又被“合”到了一起作为一个整体架构,回到了有点类似刚开始的状态。

联邦化的服务

与此同时,Office 365整条云计算产品线在紧密地相互整合,包括原有的SharePoint, Lync,One Drive等,加上收购的Skype,Yammer,还有新开发的Teams等。这些产品从宏观来看都是和Exchange类似的,基于用户或者群组,都可以通过Azure Active Directory来统一描述客户的用户组织结构。一个用户或者群组的邮件,日历,文档,联系人,聊天信息和记录,博客和通告牌等信息其实在数据的本质上是一样。Exchange也慢慢成为了整个系统的数据及计算的核心,演变为超越电子邮件服务器的Office 365 Substrate战略平台。

在这种情况下,添加新的功能时候,尤其对于非Exchange团队出身的项目组,所面临的第一个问题是,代码应该在哪里运行?是应该放到现有的框架下,运行在Mailbox Server上作为整体架构的一部分,还是别的选择?理论上来讲,在一台服务器上能够运行的进程数量和内存大小是有极限的,即便能scale out,无限制地添加新功能也是不现实的。另一方面,从开发的角度上,整体架构各个层之间是互相耦合的,使用的是同一个代码分支,而部署的时候也必须将整个build统一部署,影响了开发运维的敏捷性。这样的整体架构对于这样一个有很多工程师协同工作的产品来讲已经开始暴露出一些弊端。同时,随着Azure的成熟和完善,Azure平台也成为微软内部开发和运行平台的一个主要选项,迫切需要一套新的架构方案。

这个问题的解决方案就是“分”,将整体架构拆分成一种更趋向于SOA的结构。这一次拆分的维度,并不是简单重复历史,单纯地垂直切割,或者回到之前的多角色服务器。拆分的原则是将各个部件按照核心服务和微服务来分类,类似于操作系统的核心模式和用户模式之间的关系,形成一种行星形的结构。核心服务主要包括数据库和核心API等,而微服务是那些可以围绕这些API搭建起来的用户功能。这里的API是指分布式的API,大多数情况下是HTTP的和REST的,甚至是完全和暴露给第三方的公有API一致的。一个新的功能也许需要一些核心API的改动,但大部分的业务逻辑可以通过微服务来实现。微服务的开发和部署环境也变得非常灵活,可以根据自身使用Azure,也可以使用内部一种基于Bing所使用的Auto Pilot的混合平台。基础设施组会提供相应的工具来解决Azure和Auto Pilot方案的容量计算,容器化部署,监控和compliance相关的问题。

API为桥梁

这种架构的最关键部分在于API的完整和成熟度。目前的手机应用Outlook Mobile的前身是一个加州的公司,叫做Accompli,完全通过Exchange Online公有的第三方API开发出来的。这个app非常出色以至于后来被Office 365收购,代替了自己内部的产品。而目前的Mac Outlook也是基于同一套API开发出来的,也就是说任何开发者都可以自己开发出一个和Mac Outlook和Outlook Mobile一样功能的产品来。我个人一直秉持的观点认为,微服务架构的一大益处就是在某种程度上迫使内部和第一方团队以第三方的方式来思考,甚至感受到第三方开发者的痛处,这样对产品整体生态圈的建设有很好的促进作用。

去年发布并且引起业内很大关注的Teams,也是采用了一种和传统Office Server服务不一样的架构。Teams并没有很清晰独立的后端服务,而完全是基于Skype,Exchange和SharePoint的现有功能而搭建的微服务集合。

微之敏捷

微服务架构的思想之一是用最适合需求的编程语言和stack来完成工作。我本人所负责的项目中需要一个RSS feed parser,但因为现实中各大内容网站的RSS实现并不严格遵守协议,.net framework所带的库只能处理大概80%左右的feed,需要一个更robust的替代品。在进行调研后,我们选择了GitHub上评分较高的NodeJS和Java的开源RSS库。考虑到运行环境的因素,以及20%的非交互式应用场景,我们选择了不在本地运行,而是采用了Azure Functions (类似AWS Lambda)作为微服务来调用,也即所谓的serverless computing的模式,效果很理想。类似这样的方案在一些应用场景下可以让开发团队有很多选择,提升开发和运维过程的灵活和敏捷性。

挑战与思考

如果我在这里说Office 365是一个庞大而复杂的系统,不知道大部分读者是不是会同意,或者有部分读者会觉得不以为然,甚至认为我有王婆卖瓜之嫌。如果单纯从体量,用户数量和访问峰值来看,行业内很多的佼佼者都能给出非常让人敬佩和称赞的数据。这里我想强调的,是系统开发和运维的时候由于规模所带来的一些独特的问题。Office 365在几乎全球都有部署和运营,其中包括很多有特殊要求的国家和地区,也包括一些国家的政府和国防等敏感部门。每隔一两年,都会有新开发或者收购的产品加入Office 365家族中,甚至运行在AWS上的外部产品,能够被很快地整合成为一个整体。

之前面向个人免费用户的Hotmail,即Outlook.com, 后台也被无缝地替换成了Exchange。很多客户其实是在使用一种on-premise和云计算混合的方式,包括私有云,而Office 365的一个卖点就是保证这种混合配置的无缝运行,因此带给开发运维的包袱也不小。参与整套产品线设计,开发和运维的工程师数量,也是行业内少有的规模,可以想象协同工作过程中面临的挑战。总而言之,同众多云服务相比,Office 365有其自身独特的任务和挑战。

在新CEO纳德拉的带领下,秉持“云为先”和“一个微软”的方针,微软比任何时候都更加开放和谦虚,内部协作也更紧密。Office 365发展到现在,在经过各种用户看得见和看不见的变迁和进化后,已经成为一套比较成熟的云服务,而各种进步和创新还在继续。各位读者在关注互联网和云计算的群雄逐鹿之时,可以给微软一些目光,也许能给大家带去一些思考和启发。

作者简介

虞雷 (Jason Yu), 微软Office 365 Core部门首席软件工程师,在生态系统项目组主要负责Connectors,Actionable Message和Bots等项目的架构设计。


感谢郭蕾对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

深度内容

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT