Medium开发团队谈架构设计_转

转自:Medium开发团队谈架构设计

 背景

  说到底,Medium是个社交网络,人们可以在这里分享有意思的故事和想法。据统计,目前累积的用户阅读时间已经超过14亿分钟,合两千六百年。

  我们支持着每个月两千五百万的读者以及每周数以万计的文章发布。我们不想Medium的文章以阅读量为成功的依据,而是观点取胜。在Medium,文章的观点比作者的名头更重要。在这里,对话促进想法,并且很看重文字的力量。

  我是Medium开发团队的负责人,此前在Google工作,负责开发Google+和Gmail,还创立了Closure项目。业余时间我喜欢滑雪跳伞和丛林冒险。

  团队介绍

  说起团队我非常自豪,这是一群富有好奇心而且想法丰富的天才,大家凑到一块是想做大事的。

  团队以跨功能的任务驱动,这样每个人既可以专攻,又可以毫无压力的对整个架构有所贡献。我们的理念就是接触的方面越多,对团队的锻炼越大。更多关于团队的理念见此

  在工作组织方面,我们有着很大的自由度,当然作为一个公司组成,我们还是有季度目标的,并且鼓励敏捷开发模式。我们使用GitHub进行code review和问题跟踪,用Google Apps作为邮件、文档和表单系统。跟很多团队习惯使用Trello不同,我们是Slack和slack机器人的重度用户。

  原始架构

  最开始的时候,Medium部署在EC2上,用Node.js实现,后来公测的时候迁移到了DynamoDB

  其中有个节点用来处理图片,负责将复杂的处理工作转向GraphicsMagick。还有一个节点用作后台的SQS队列处理。

  我们用SES处理邮件,S3做静态元素服务器,CloudFront做CDN,nginx作为反向代理,Datadog用来监控,Pagerduty用来告警。

  在线编辑器用了TinyMCE。上线之前我们已经开始使用Closure编译器以及部分的Closure库,但是模板还是用的Handlebars

  当前架构

  虽然Medium表面看起来很简单,但是了解其后台的复杂性后,你会大吃一惊。有人会说,这就是个博客啊,用Rails之类的一周就能搞定了。

  总之,闲话不多说,我们自底向上介绍以后再做判断。

  运行环境

  Medium目前运行在Amazon虚拟私有云,使用Ansible做系统管理,它支持配置文件模式,我们将文件纳入代码版本管理,这样就可以随时回滚随时掌控。

  Medium的后台是个面向服务的架构,运行了大概二十几个产品服务。划分服务的依据取决于这部分功能的独立性,以及对资源的使用特性。

  Medium的主体仍然是Node.js完成,方便前端和后端的代码共享,主要是文章编辑和发布这个过程。Node大部分时候不错,但阻塞event循环的时候会有性能问题。为了缓解,我们在每台机器上启动多个Node实例,将对性能要求比较高的任务分配给专门的实例。同时我们还深入V8运行时环境查看更加细节的耗时,基本上是JSON去串行化的时候的对象具体化耗时较多。

  我们还用Go语言做了一些辅助服务。因为Go非常容易编译打包和发布。相比Java语言的冗长罗嗦和虚拟机,Go语言在类型安全方面做的很到位。就个人习惯来讲,我比较喜欢在团队内部推广强类型语言,因为这类语言能够提高项目的清晰度,不纠结。

  目前静态元素大部分是通过CloudFlare提供的,还有5%通过Fastly,5%通过CloudFront,这么做是为了让两者的缓存得到更新,用于一些紧急的情况。最近我们在应用流量上也使用了CloudFlare,当时主要是为了防止DDOS攻击,但随之而来的性能提升也是我们愿意看到的。

  我们使用Nginx和HAProxy做反向代理和负载均衡,来满足我们所需功能的维恩图。

  我们仍然使用Datadog来监控,Pagerduty来告警。现在又增加了ELK(ElasticsearchLogstashKibana)来进行产品问题调试。

  数据库

  DynamoDB仍然是我们的主力数据库,但是用起来也不是毫无问题。目前遇到的比较棘手的是大V用户展开和虚拟event过程中的热键问题。我们专门在数据库前面做了一个Redis缓存集群,来缓解这些问题。到底为开发者优化还是为产品稳定性优化的问题通常会引发争执,我们也一直在尝试中和两者的矛盾。

  目前我们开始在存储新数据上使用Amazon Aurora,它可以提供更灵活的查询和过滤功能。

  我们使用Neo4J存储Medium网络中实体之间的关系,运行在有两个副本的主节点上。用户、文章、标签和收藏都属于图中的节点。边则是在实体创建和用户进行推荐高亮等动作时生成。我们通过在图中游走来过滤和推荐文章。

  数据平台

  早期我们对数据非常渴望,不断尝试数据分析框架来辅助商业和产品决策。最近我们则是利用同样的框架来反馈产品系统,支持Explore等数据驱动功能。

  我们采用Amazon Redshift作为数据仓库,为生产工具提供可变存储和处理系统。我们持续将诸如用户和文章等核心数据从Dynamo导入Redshift,还将诸如文章被浏览被滚动等event日志从S3导入Redshift。

  任务通过一个内部调度和监控工具Conduit调度。我们用了一个基于断言的调度模型,只有条件满足的时候,任务才会执行。从产品角度来讲,这是不可或缺的:数据制造方应该与数据消费方隔离,还要简化配置,保持系统的可预见和可调试性。

  Redshift的SQL检索目前运行不错,但我们时不时需要读取和存储数据,所以后期增加了Apache Spark作为ETL,Spark具有很好的灵活性和扩展能力。随着产品的推进,估计后面Spark会成为我们数据流水线的主要工具。

  我们使用Protocol Buffers作为schema来确保分布式系统的各层次间保持同步,包括移动应用、web服务和数据仓库等。通过定制化的选项,我们将schema标记上更加细化的配置,如带有表名和索引,以及长度等校验约束。

  用户也需要保持同步,这样移动端和网页端就可以保持日志的一致性了,同时方便产品科学家们用同样的方式解析字段。我们帮助项目成员从.proto文件中生成消息、字段和文档等内容,进而利用所得数据开展研究。

  图片服务器

  我们的图片服务器现在用Go语言实现,采用瀑布型策略来提供处理过的图片。服务器使用groupcache,是memcahce的替代品,可以帮助减轻服务器之间的重复工作。而内存级缓存则是用了一个S3的持续缓存。图片的处理是请求来触发的。这给了我们的架构设计师灵活改变图片展示的自由度,为不同平台优化,而且避免了大量的生成不同尺寸图片的操作。

  目前Medium对图片主要支持放缩和裁剪,但原始版本中还支持颜色清洗和锐化等操作。处理动图很痛苦,具体后续可以写一篇文章来解释。

  文本标注

  文本标注是个有意思的功能,用了一个小型Go服务器,跟PhantomJS接口形成渲染进程。

  我一直想要把渲染进程换到Pango,但是在实践过程中,能在HTML中摆放图片的能力的确更灵活。而从功能的使用频率来看,这意味着更容易开发和管控。

  自定义域名

  我们允许用户为其Medium文章设置个性化域名。我们想做成单点登录且HTTPS全覆盖,因此实现起来颇有难度。我们专门准备了一批HAProxy服务器用来管理证书,并向主要应用服务器引导流量。初始化一个域的时候需要一些手动的工作,但是通过与Namecheap的定制化整合,我们将其大部分转换为自动化。证书验证和发布链接由专门服务负责。

  网站前端

  网页端这块,我们有自主研发的单网页应用框架,使用Closure标准库。我们使用Closure模板渲染客户端和服务端,然后使用Closure编译器来缩减代码并划分模块。编辑器是我们网页端应用最复杂的部分,具体参见Nick此前的文章。

  iOS

  我们的两个应用都是原生的,尽量避免使用网页视图。

  在iOS上,我们使用了一系列的自建框架,以及系统原生组件。在网络层,我们用NSURLSession发起请求,用Mantle解析JSON并映射到模型。我们还有一层基于NSKeyedArchiver的缓冲层。对于将条目渲染为共同主题的列表,我们有一个通用方法,这让我们能够快速为不同类型的内容构建新列表。文章界面是一个定制布局的UICollectionView。我们使用共享组件来渲染全文界面和预览界面。

  应用代码的每一次提交都会编译后推送给Medium员工,这样我们能够很快尝试新版本。应用商店的版本是滞后于新版本的,但我们也一直在尝试更快的发布,虽然可能仅仅是几处小更新。

  对于测试,我们使用XCTest和OCMock。

  Android

  在Android方面,我们与当前的SDK和支持库版本保持一致。我们并没有使用任何复杂的框架,而是倾向于为重复出现的问题构建持续性的模式。我们利用guava弥补Java中所有的缺失。另一方面来讲,我们也倾向于使用第三方库来解决特别的问题。我们还利用protocol buffers定义了API,用以生成应用中的对象。

  我们利用mockitorobolectric。我们会开发一些高层测试来运转activity和poke:刚添加screen或要重构的时候,先创建一些基本的版本,随着我们复现bug它们也会进化。我们还会开发一些底层测试,来检测一个特定的类:随着新功能的增加我们会创建测试,这能够帮助我们思考和设计底层是如何交互的。

  每个提交都会作为alpha版本自动推送到play商店,然后到Medium员工(包括我们的Hatch,Medium内部版)。推送大部分发生在周五,我们会把alpha版本发送给测试小组,请他们用整个周末进行测试。然后,周一我们会从beta版推进至正式产品版。因为最近一批代码总是随时可以推送,因此一旦发现很严重的bug,我们就可以立即修复正式产品版。当我们怀疑某些新功能的时候,可以给测试小组更长的时间。开发比较亢奋的时候,也可能发布地更加频繁。

  AB测试及其他

  我们所有的客户端都用了服务器端提供的功能标记,称为variants,用于AB测试以及指导未完成功能的开发。

  剩下还有一些框架相关的内容我没有提及:Algolia让我们在搜索相关功能上快速迭代,SendGrid处理邮件,Urban Airship用来发送提醒,SQS用来处理队列,Bloomd用作布隆过滤器,PubSubHubbubSuperfeedr用作提供RSS等等。

  编译、测试和部署

  我们积极拥抱持续集成技术,随时随地准备发布,使用Jenkins来负责相关事宜。

  我们曾经使用Make作为编译系统,但是后来迁移到Pants

  测试方面我们采用单元测试和HTTP层面功能测试两者结合的方式。所有提交的代码都需要通过测试才能够合并。我们跟Box团队合作,利用Cluster Runner来分布式运行测试,保证效率,而且能够和GitHub很好的整合在一起。

  我们大概不到15分钟就可以把某阶段的系统部署,顺利编译通过,留作正式产品的备选。主应用服务器通常一天要部署五次,多的时候十次。

  我们采用蓝绿部署。正式产品版本的流量发送给一个canary实例,发布进程会监控部署过程的错误率,必要时候通过调整内部DNS回滚。

  面向未来

  到此,讲了足够多的干货!为了重构产品,获得更好的阅读体验,还有很长的路要走。我们仍然在努力为作者和发布者设计更多的功能。打比方来讲,线上阅读还是一片绿地,面对它有着无限可能,我们始终抱着开放的心态设计和实现功能。未来我们会努力用各种功能为用户提供高质量内容和价值。

原文地址:https://www.cnblogs.com/embedded-linux/p/9534123.html

时间: 2024-10-08 14:20:28

Medium开发团队谈架构设计_转的相关文章

Android开发-浅谈架构(二)

写在前面的话 我记得有一期罗胖的<罗辑思维>中他提到 我们在这个碎片化 充满焦虑的时代该怎么学习--用30%的时间 了解70%该领域的知识然后迅速转移芳草鲜美的地方 像游牧民族那样.原话应该不是这样,但是我想说的是 自从我想写一些笔记记录知识的时候 为了不误导其他人 我不得不参考github 一些比较知名大牛的代码.在这个过程中 我下载过很多demo.一点一点的啃 汲取精华的部分 当然也充满疑惑.后来觉得标题取得有点大了 我应该取"学习"类的标题才对.但是另一方面我也只能就

谈架构设计中DDD思想的运用

首先,描述一下我的业务场景及项目分层结构,非标准DDD(其实我不觉得有标准),只是思考的时候有带入DDD思想. 业务场景:这是一个ERP系统对中台提供的接口项目,仓储操作大多都是存储过程去完成的. 项目结构,如图: WebAPI层:这个不用多说了,入口. DTO层:增加数据传入传出对象,和领域model.实体model区分.(要不要围绕领域model或从现有系统中提取领域model看实际业务情况,拿我目前这个项目来说,得不偿失.) Services层:业务服务层(可以命名成BizServices

iOS开发&gt;学无止境 - 浅谈MVVM的架构设计与团队协作

李刚按:本文是青玉伏案写的一篇文章.相信大家对MVC耳熟能详,MVVM可能听说的相对少一些,这一篇文章将会想你阐述MVVM设计,还有团队协作的经验分享.如果你也觉得不错,就分享一下吧! demo:https://github.com/lizelu/MVVM 今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由 于本人项目经验有限,关于架构设

iOS开发之浅谈MVVM的架构设计与团队协作

今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与传统的MVC可谓是极为相似,也可以说是兄弟关系,也就是一家人了. 说道架构设计和团队

浅谈iOS中MVVM的架构设计与团队协作【转载】

今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与传统的MVC可谓是极为相似,也可以说是兄弟关系,也就是一家人了. 说到架构设计和团队

IOS中 浅谈iOS中MVVM的架构设计与团队协作

今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦~). 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 由于本人项目经验有限,关于架构设计方面的东西理解有限,我个人对MVVM的理解主要是借鉴于之前的用过的MVC的Web框架~在学校的时候用过ThinkPHP框架,和SSH框架,都是MVC的架构模式,今天MVVM与

web架构设计经验分享(转)

本人作为一位web工程师,着眼最多之处莫过于 性能与架构,本次幸得参与sd2.0大会,得以与同行广泛交流,于此二方面,有些心得,不敢独享,与众博友分享,本文是这次参会与众同撩交流的心得,有兴趣者可以查看视频 架构设计的几个心得: 一,不要过设计:never over design 这是一个常常被提及的话题,但是只要想想你的架构里有多少功能是根本没有用到,或者最后废弃的,就能明白其重要性了,初涉架构设计,往往倾向于设计大而化一的架构,希望设计出具有无比扩展性,能适应一切需求的增加架构,web开发领

架构设计的方法学

约公元前25年,古罗马建筑师维特鲁威说:"理想的建筑师应该既是文学家又是数字家,他还应通晓历史,热衷于哲学研究,精通音乐,懂得医药知识,具有法学造诣,深谙天文学及天文计算."(好难哪,软件构架设计师的要求呢?大家好好想想吧.)   本文目录   一.与构架有关的几个基本概念:   二.构架设计应考虑的因素概揽:   三.程序的运行时结构方面的考虑:   四.源代码的组织结构方面的考虑:   五.写系统构架设计文档应考虑的问题   六.结语   一.与构架有关的几个基本概念:   1.模

架构设计概念

什么是架构设计? 架构定义大的系统结构.是对需求的转化,上接业务,下接技术决策.架构设计包括静态架构设计和动态架构设计. 静态架构设计:完成系统功能性需求,系统的整体结构 动态架构设计:通用问题的解决方案,完成系统非功能性需求,主要有稳定性,安全性,可扩展性,可伸缩性,吞吐量 架构设计与项目管理 帮助进行任务分工,任务协作,通过接口定义模块间接口,开发过程中依赖接口,不依赖具体实现,并行开发 详细设计与架构设计 粒度不同,架构设计定义模块/组件以及他们之间的关系,详细设计定义模块/组件内类和类间