内容简介:2016年,BuzzFeed启动了一个重构项目,把使用Perl编写的一个单体应用程序转换成一组微服务。他们之所以这样做,主要是因为Perl应用程序被证明很难扩展,使除了扩展问题外,BuzzFeed发现,寻找懂Perl并且希望使用它开发的工程师越来越难。最后,他们希望自己能够在有了新产品想法时可以更快速地迭代。从一个很高的层面上来说,新架构包含一个CDN,指向一个路由服务,该服务位于AWS上,使用了ECS容器化服务:
本文要点
2016年,BuzzFeed启动了一个重构项目,把使用Perl编写的一个单体应用程序转换成一组微服务。他们之所以这样做,主要是因为Perl应用程序被证明很难扩展,使 buzzfeed.com 独自服务于每月大约70亿次页面访问,而且,组织还要向大约30个不同的社交平台发布内容,包括不同的语言版本。
除了扩展问题外,BuzzFeed发现,寻找懂Perl并且希望使用它开发的工程师越来越难。最后,他们希望自己能够在有了新产品想法时可以更快速地迭代。
从一个很高的层面上来说,新架构包含一个CDN,指向一个路由服务,该服务位于AWS上,使用了ECS容器化服务:
新的微服务是以Python作为主要语言开发的,对于性能比较敏感的组件则使用了Go。BuzzFeed的工程团队发现,这两种语言可以很好地互补,对于开发人员而言,根据需要从一种切换到另一种也相对简单。
在本文写作时,他们在AWS上的过渡环境和生产环境中已经有大约500个微服务。他们在分解服务时使用了听上去和 SCS 类似的东西;buzzfeed.com的首页是一个服务,新页面是单独的服务,作者页面也是,诸如此类。
团队面临的一项挑战是把请求路由到正确的后台应用程序。他们的CDN提供商 Fastly 具有在边缘通过编程定义行为逻辑的能力,使用的是一种基于C的编程语言VCL,工程团队最初就是直接使用 VCL 编写他们所有的路由逻辑。
不过,他们发现,随着配置越来越复杂,修改变得越来越困难,充分测试这些配置的能力愈发重要。BuzzFeed资深软件工程师 Mark McDonnell 告诉InfoQ:
我们在CDN中有大量的逻辑,只有少数几名工程师真正了解它是如何工作的。另外,CDN还被有意锁定,因为缓存层对我们而言特别重要,我们需要防止工程师意外修改,那可能会对我们的缓存策略产生不利影响,或者会导致进入的请求被路由到错误的源服务器。
此外,Fastly还有自己的 Varnish HTTP加速器 实现。BuzzFeed发现,这让工程师很难启用一个本地开发环境,并通过它运行他们的VCL逻辑,因此,VCL代码测试就成了问题。为此,工程团队决定实现一个新的路由服务来代替VCL路由,把大部分路由逻辑从CDN提取到一个单独的路由器微服务中。
网站路由服务被设计成在BuzzFeed自己的 Rig平台 上运行,这便于他们部署到他们运行的每一个Amazon弹性容器服务环境(ECS)(测试、过渡、生产)中的每个服务上。
对于反向代理,他们考虑了包括 HAProxy 在内的多个选项,但最终决定使用NGINX。McDonnell 说,“我们选择 NGINX ,因为我们平台基础设施团队中的大部分人都有使用经验,所以,我们得到了SRE的支持,我们其中的一个卖点是,它很容易提升速度”。如你所想,向系统添加NGINX确实会给单个请求带来额外的延迟,但按照McDonnell的说法,这可以“忽略不计”。
虽然把简单易用和熟悉度作为选择NGINX的其中两个原因,但BuzzFeed还是构建了一个配置该服务的抽象层。该服务是用Python编写的,它会从 YAML 动态生成所需的nginx.conf文件。它广泛使用了YAML特有的特性,如“锚和别名(Anchors and Aliases)”和“合并键(Merge Key)”,据 BuzzFeed技术博客 介绍,“这让我们可以跨环境块重用配置,而且很容覆盖特定的键,不需要重复大量的配置工作。我们主要把这种方法用于‘上游’和‘超时’区域,因为我们通常会希望覆盖那些特定于环境的值。”
起初,路由服务是使用NGINX的开源版本构建的,但后来转到了商业版本 NGINX Plus 。按照McDonnell的说法,可以获得付费支持是一个原因,但团队也需要只有付费版本中才有的某些特性,尤其是DNS监控;BuzzFeed的服务器区域相当复杂,那样,当AWS负载均衡改变IP地址时,NGINX Plus能够保证DNS条目也更新。 BuzzFeed技术博客 上有一篇博文是这样解释的:
在NGINX启动的时候,它会为我们在配置文件中定义的下游解析DNS。也就是说,它会把主机名转换成IP(或者一组IP,和使用AWS Elastic负载均衡器一样)。然后,NGINX会缓存这些IP,我们的问题在这里开始出现了。
你可能不熟悉负载均衡器,它们会检查多个服务器,看看它们是否健康,如果不健康,服务器会被关闭,并有一个新实例启动。我们发现的问题是,每个服务器实例的IP都在不断变化。如前所述,NGINX在启动时会缓存IP,而因为ELB[Elastic负载均衡器]的原因,新进来的请求会被代理到不再有效的缓存IP。
一种解决方案是热重载NGINX配置。那是个手动过程,我们不知道什么时候该那样做,因为我们无法知道服务器实例何时会停止服务。
NGINX文档中有几个设法变通解决这个问题的选项;不过,除了一个选项外,其他所有选项都意味着我们需要重新设计我们的整个架构,因为它们不支持NGINX的upstream指令(作为配置抽象的一部分,我们对它的依赖度很高)。
允许我们利用接口设计的那个解决方案只有NGINX Plus提供。采用商业版本的成本是合理的:我们不需要从头重写我们的整个服务,后续我们也可以利用额外的特性(其中有一部分我们已经考虑过)。一旦切换,该解决方案只需要增加一行resolver指令,为缓存的DNS解析结果定义一个TTL。
VCL逻辑用于帮助BuzzFeed在他们推出新服务时根据用户的地理位置分类用户,那样,他们就可以从一个类似新西兰这样的小国家开始。McDonnell解释说:
对于任何geoip.country_code是NZ的用户,他们会设置一个X-BF-SiteRouter头。然后,在VCL代码中,如果X-BF-SiteRouter头已经设置(取决于请求哪个路由),我们会把后端切换到Site Router。
一旦我们满意,我们就会把服务区域扩展到AU、GB、OC、EU、SA(南美),最终,我们会把所有东西都指向Site Router(实际上,北美是最后一个区域)。
我们还使用了Vary头保证来自不同区域、还没准备好访问Site Router的用户不会意外从中获得缓存的响应。
迁移到新架构已经在团队生产率方面为我们带来了益处,McDonnell告诉我们:
工程师可以根据自己的意愿自由启动服务,我们每天部署很多次。周遭有各种流行的术语,如持续集成、持续交付和持续部署,它们只有稍微的不同。最终,我们有了一个非常棒的交付管道,但是,我们特有的平台实现无法自动把变更推送到生产环境,目前我们还得手动选择,那对于我们的应用场景而言是合理的(例如,并不是我们构建的所有东西都必须自动存在于生产环境中)。
BuzzFeed有一个富A/B系统,用于测试单个的“特性”,规模较大的基于A/B测试的上线在他们的方法中反而变得比较简单(综合运用VCL逻辑和Site Router特有的“override”配置来处理请求路由)。
新基础设施监控(以及日志聚合和分析)是使 用DataDog 实现的。他们还在评估 Honeycomb.io 。
关于作者
Charles Humble 于2014年3月成为InfoQ.com编辑团队负责人,指导我们的内容创作,包括新闻、文章、著作、视频演讲和采访。在承担InfoQ的这个全职角色之前,Charles负责我们的 Java 报道,并且是薪酬研究公司PRPi Consulting的CTO,该公司2012年7月被PwC收购。他已经从事企业级软件工作将近20年,做过开发,当过架构师和开发经理。在业余时间,他从事音乐创作,是伦敦氛围科技舞曲团 Twofish
的三名成员之一。
查看英文原文: How BuzzFeed Migrated from a Perl Monolith to Go and Python Microservices
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 走出微服务误区:避免从单体到分布式单体
- 对单体系统优缺点评判到位:拆分Shopify单体工程的经验分享
- 单体应用微服务改造实践
- 单体应用微服务改造实践
- Istiod——回到单体的理由
- 在单体架构中应用Hystrix
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Pro Django
Marty Alchin / Apress / 2008-11-24 / USD 49.99
Django is the leading Python web application development framework. Learn how to leverage the Django web framework to its full potential in this advanced tutorial and reference. Endorsed by Django, Pr......一起来看看 《Pro Django》 这本书的介绍吧!
HTML 编码/解码
HTML 编码/解码
URL 编码/解码
URL 编码/解码