开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
帮助 Medium 阅读时间达到 2600 年的技术栈 - 技术翻译 - 开源中国社区

帮助 Medium 阅读时间达到 2600 年的技术栈 【已翻译100%】

oschina 推荐于 2年前 (共 14 段, 翻译完成于 11-25) 评论 10
收藏  
109
推荐标签: 待读

medium

背景

Medium 是一个网络。这是一个分享有价值的故事和想法的地方,在这里人们可以保持想法不断的前行,大家已经在那里花费了 14 亿分钟(换句话说是 2600 年)的阅读时间。

每月的独立用户超过了 2500 万,每周会新增数以万计的新帖子。但是我们心目中的 Medium 应该是以观点量来衡量是否成功,而不是阅读量;不会关心作者的资历,而更关心想法是否有价值;应该能更方便的为大家推送有价值的内容。

我领导了整个工程团队。我之前是 Google 的一名软件工程师,从事 Google+ 和 Gmail 的开发,共同创建了 Closure 项目。在那段时间,我经历过滑雪板比赛,飞机跳伞,还有丛林冒险。

zicode
 翻译得不错哦!

工程团队

我为我的这个团队骄傲。团队里每个人都是天才,大家都充满求知的渴望,为了这个让人激动的事情聚在一起。在我们看来,经历过不同的磨练可以让你成为更有经验的工程师。有兴趣的话可以看看我们其他的价值观

在如何安排自己的工作上,团队有很高的自由度,不过作为公司,我们会设立季度目标,鼓励迭代冲刺。我们使用 GitHub 做代码 review 和 bug跟踪,用 Google Apps 管理邮件、文档和电子表格。我们是 Slack 的重度用户 (以及 slack bots),有不少团队使用 Trello

zicode
 翻译得不错哦!

初始的技术栈

刚开始的时候我们把服务部署到 EC2 上。主服务是用 Node.js 写的,每次发布的时候,会合并到DynamoDB

还有一个 node 服务器用于图片处理,调用 GraphicsMagick 来做具体的复杂的工作。另一个服务被用作 SQS 队列处理,负责后台任务。

我们的 email 使用 SES,静态资源放在 S3 上,CDN 使用 CloudFront,使用 nginx 作为反向代理。另外,使用 Datadog 做监控,PagerDuty 做报警。

网站使用 TinyMCE 作为编辑器。发布之前,我们已经在使用 Closure 编译器和部分 Closure 库,不过模板用的是 Handlebars

zicode
 翻译得不错哦!

当前的技术栈

Medium 这样的站点看上去似乎很简单,不过背后的复杂程度足以让人惊讶。这还仅仅只是一个博客网站么?要是这样的话,你用 Rails 几天就能搭建一个出来。:)

闲话少说,我们从最底层说起。

产品环境

目前我们运行在 Amazon 的虚拟私有云上。我们使用 Ansible 做系统管理,可以让我们的配置处于源码控制下,可以通过可控的方式很轻松的进行更新。

我们有着面向服务的架构,在其上运行了大约一打的产品服务(取决于你如何去统计,还有很多小一点的服务)。是否作为独立的服务来部署,主要取决于其功能,服务边界上是否可能产生有依赖的变动,以及对资源的利用。

zicode
 翻译得不错哦!

我们主要的应用服务器仍然写在Node里,它允许我们在供应商和客户之间交换代码,我们用编辑器就要用到它,公布变革也是用它。Node为我们工作得很好,但是在我们把事件循环编写成块的时候,性能问题就浮现了。为了缓和这一问题,我们在每台机器上运行多个实例,并把它们路由到昂贵的端点,以此来分隔它们。我们把它与V8运行环境相挂钩,以深入了解哪个部件运行花费的时间较长。通常它是因为在JSON还原序列化时目标的具体化。

我们用Go编程的时候可以享受到一些辅助服务。我们发现用GO建立、打包和部署很容易。我们喜欢不需用到繁冗并调试虚拟机Java的类型安全。就我个人而言,我更喜欢在团队环境中使用武断的语言。它能提高一致性、减少歧义,最终让你避免作茧自缚。

我们现在使用CloudFlare提供静态资源,尽管我们把5%的流量送到Fastly,同时还送5%的流量到CloudFront来保持它们的缓存热度,以防在紧急情况下万一我们需要割接。最近我们也把CloudFlare用于应用流,基本上是为了DDOS保护。但是对于性能提升我们还是乐见其成的。

我们使用Nginx和HAProxy的结合作为反向代理,达到负载均衡,以实现我们需要的Venn Diagram特性。

我们仍然使用Datadog监测,使用PagerDuty报警,但是我们现在大量使用ELK(Elasticsearch,Logstash,Kibana)调试出现的问题。

数据库

DynamoDB仍然是我们基本的数据存储库,但是它仍不完美。我们遇到的常见的问题之一是在重大事件发生时和有百万追随用户时的热键问题。在Dynamo前面我们可以用Redis缓存器,它能通过读取来减轻这些问题。

开发者便利性和产品稳定性二者之间的优化似乎总是存在矛盾,但是我们在努力缩小分歧。    

我们开始使用Amazon Aurora获取最新的数据,它的查询和过滤功能比Dynamo更灵活。

我们使用Neo4J来储存代表媒体网络的实体之间的关系,用两个副本来运行一个主本。

人、邮件、标签和合类是图表中的节点。

边界在实体创建的基础上建立。当人们发生以下行为,比如跟随、推荐和强调时,我们按图索骥,过滤并推荐相关的邮件。



女亭金玉
 翻译得不错哦!

数据平台

早起我们的数据很匮乏,所以在数据分析基础架构上做了很多投资,为商业和产品上的决策提供帮助。最近以来,我们可以在同样的数据处理流程上为整个产品体系提供更多的反馈,甚至可以运行类似 Explore 这样的数据驱动的功能。

我们使用 Amazon Redshift 作为数据仓库,它提供了可伸缩的存储和处理系统,我们其他的工具就运行在其上。我们持续的把核心数据(例如用户、文章)从 Dynamo 导入到 Redshift,以及把行为日志 (例如:文章阅读、翻页等等) 从 S3 导入到 Redshift。

我们使用 Conduit 来对任务做调度,这是一个内部工具,可以管理计划、数据依赖,还可以进行监控。我们的任务调度模型是基于断言的,只有一个的所有的依赖都满足了,这个任务才会被执行(例如,依赖全天行为日志的每日任务)。对于产品,这方面被证明是非常重要的:数据的生产者和消费者互相解耦,简化配置,系统状态可预知和易调试。

zicode
 翻译得不错哦!

尽管对我们来说在 Redshift 上运行 SQL 查询良好,我们还是需要将数据不断输入输出 Redshift。我们越来越转向 ETL 的 Apache Spark,这是因为它的灵活性与规模增长的能力。随着时间的推移,Spark 可能会成为我们数据管道的首选工具。

我们使用协议缓冲(Protocol Buffers)对我们的模式(模式演化规则)来保持所有层的分布式系统同步,包括移动应用,web 服务,和数据仓库。使用自定义选项,我们标注模式与表名和索引等配置细节,验证约束最大长度的字符串,或者控制接受数据控制的范围。

人们也需要保持移动和 web 应用程序同步,开发人员使得所有日志一样,产品研究员可以以同样的方式解释字段。我们帮助我们的成员在数据处理模式规范上的工作,并严格记录字段的消息,发布文档生成的原型(.proto)。


无若
 翻译得不错哦!

图像

我们的图片服务器现在是用 Go 写的,并使用了瀑布策略处理图像。服务器使用 groupcache,它提供了 memcache 的替代方案,来减少重复的工作。支持内存中的缓存是一个持久的 S3 缓存,然后来处理图像处理需求。这让我们的设计师可以在不同平台上,灵活地改变图像的表示和优化,而不必做大的批处理缩放图像作业。

现在主要用于调整和裁剪,早期版本的网站允许颜色清洗、模糊和其他图像效果。处理动态 gif 一直是一个巨大的头痛的问题,这应该又是另一篇文章了。

无若
 翻译得不错哦!

文本截图

完整的文本截图功能由一个小型的 Go 服务器驱动,使用 PhantomJS 作为渲染引擎。

我一直想把渲染引擎转换为 Pango,但在实践中,将图片嵌入 HTML 的方式更为灵活和方便。这项功能的使用频率意味着我们可以很简单地处理吞吐量。

自定义域名

我们允许用户对他们的 Medium 作品设置自定义域名。我们想让单点登录和 HTTPS 无处不在,所以让它开始工作不是件小事。我们有一组 HAProxy 服务器专门用于管理证书和导向主应用服务器的流量。在设置域名时还需要一些手动操作,但是我们通过自定义整合 Namecheap 已经自动化了很大一部分。证书的规定和公开链接是由一个专用服务处理的。

社会主义好
 翻译得不错哦!

Web 前端

在网页上,我们倾向于电子化。我们有自己的单页应用程序框架,使用闭包作为标准库。我们使用闭包模板在客户端和服务器渲染,我们使用闭包编译器压缩代码并把它分割成模块。编辑器是我们网页应用最复杂的部分,Nick 写出了 iOS 系统。

iOS 系统

我们的应用程序都是本地下载好的,很少使用网络视图。

在 iOS 中,我们使用国产构架和内置构件的混合。在网络层,我们使用 NSURLSession 提出请求,使用 Mantle 来把 JSON 解析成模型。 我们有一个建立在 NSKeyedArchiver 上的缓存层。我们有一个通用的方法把项目列入不同的列表,同一列表中的项目有共同特征。这就能让我们快速建立不同类型内容的列表。后视图是用 UICollectionView 自定义布局构建的。我们使用共享组件来渲染完整的文章和后预览。

Medium 的员工尽一切努力来尽快开发和推出新的应用。我们发布更新的节奏是受限于 Appstore 的审阅周期的,但我们正尽己所能地推进这一进程,即使只有很少的更新。

测试我们使用 XCTest 和 OCMock.

女亭金玉
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(10)
Ctrl/CMD+Enter

好文章,收藏了
good
高大上,好多看不懂
“文本截图用PhantomJS”,哪位大神能帮忙解释下这句话什么意思? 截图不是前台的吗,跟后台PhantomJS联系是什么?
谢谢!
这个应用不错,里面有些故事分享很有故事会的味道,很有软文的味道。

引用来自“Honghe”的评论

“文本截图用PhantomJS”,哪位大神能帮忙解释下这句话什么意思? 截图不是前台的吗,跟后台PhantomJS联系是什么?
谢谢!
PhantomJS就相当于一个浏览器,可以实现把网页保存成图片的功能。然后分享到twitter时就可以加上预览图了
9899910[10]:relieved::relieved::flushed::flushed::kissing_closed_eyes::kissing_closed_eyes::kissing_closed_eyes::kissing_closed_eyes::flushed:

引用来自“Honghe”的评论

“文本截图用PhantomJS”,哪位大神能帮忙解释下这句话什么意思? 截图不是前台的吗,跟后台PhantomJS联系是什么?
谢谢!

引用来自“zhangshine”的评论

PhantomJS就相当于一个浏览器,可以实现把网页保存成图片的功能。然后分享到twitter时就可以加上预览图了
哦,这样啊。还以为是APP上用户自己圈一块截图。

引用来自“Honghe”的评论

“文本截图用PhantomJS”,哪位大神能帮忙解释下这句话什么意思? 截图不是前台的吗,跟后台PhantomJS联系是什么?
谢谢!

引用来自“zhangshine”的评论

PhantomJS就相当于一个浏览器,可以实现把网页保存成图片的功能。然后分享到twitter时就可以加上预览图了

引用来自“Honghe”的评论

哦,这样啊。还以为是APP上用户自己圈一块截图。
phantomjs 屎一样渣渣,可是没有替换方案。

引用来自“Honghe”的评论

“文本截图用PhantomJS”,哪位大神能帮忙解释下这句话什么意思? 截图不是前台的吗,跟后台PhantomJS联系是什么?
谢谢!

引用来自“zhangshine”的评论

PhantomJS就相当于一个浏览器,可以实现把网页保存成图片的功能。然后分享到twitter时就可以加上预览图了

引用来自“Honghe”的评论

哦,这样啊。还以为是APP上用户自己圈一块截图。

引用来自“开源中国匿名会员”的评论

phantomjs 屎一样渣渣,可是没有替换方案。
嗯,其 API 与完整的浏览器、Node.JS 相比很怪异,闭包都不能很好地支持,各种奇怪的传参方式……
顶部