写点什么

设计全球级的分布式、任务关键型应用——从实际项目中得来的教训(下)

  • 2015-11-18
  • 本文字数:3489 字

    阅读完需:约 11 分钟

此篇为设计下一代智能 DNS 和流量管理平台的 NSONE 公司的创建者和 CEO Kris Beevers 的客座文章的第二部分。点此阅读第一部分

集成和功能测试非常关键

每一个软件开发的课程都会反复强调单元测试的重要性。无论你是正在进行测试驱动的开发还是只想炫耀一下代码,没有进行单元测试的情况下,你仍然无法肯定代码的功能。而且,随着代码的修改,单元测试要不断进行,从而保证代码的功能正确性。

在一个分布式应用中,即使你拥有全世界最好的功能测试覆盖,系统仍然有可能出问题。单元测试永远不够!

你需要测试不同子系统之间的交互情况。例如,如果配置数据的一个特殊部分变化,会有什么影响呢?它会不会影响到子系统A 与子系统B 之间的通信呢?又如,如果你改变了一种消息格式,产生和处理这些消息的子系统还可以继续与其他子系统进行通信吗?代码修改后,需要依靠4 个不同后端子系统给出的结果的一类特殊请求还会得到正确反馈吗?

单元测试回答不了这些问题,但是集成测试可以。在集成测试环境中投入时间和精力,并且在研发和部署过程中要适时进行集成测试。理想情况下,最好一直在产品系统中运行集成测试。

没有中断维护这种东西

如果你正在设计一个真正的任务关键型应用(客户需要依赖该应用来打理生意),那么该应用可能不需要开关。它永远不需要停止工作。那么,你永远都不会有终端维护的权利和可能。即使是世界上最复杂的后端架构也会有需要改变的时候。

这就是你需要认真思考架构的其中一个原因。几个小时的认真思考可能可以避免后期几个月的漏洞弥补时间。

Kris 就遇到过一个真实的情况。NSONE 的团队从一开始在架构设计阶段就投入了大量精力,使得项目沿着正确的方向前进。但是,该团队仍然有没有考虑到的问题——平台接收高频率的数据反馈。这些反馈会影响到如何对复杂流量管理配置下 DNS 记录的请求进行回答。数据反馈可以应用到多个 DNS 记录中,也就是说一个服务器负载信息的反馈可以通知牵涉到服务器上多个网站的流量路由决策。当时,NSONE 团队假设只有一个单独的数据反馈连接到若干个 DNS 记录。那么,就可以通过把到达系统的数据反馈根据每个所连接的 DNS 记录发送到相应的边沿位置来节约大量时间和精力。然而,团队的假设是不成立的。一些客户把数据反馈连接到了数千个 DNS 记录。前期的偷懒导致内部发生 DoS,而且随着系统的扩展,问题会越来越严重。

其问题在于:团队不能通过发送比较少的控制消息来解决以上问题。Kris 等需要修改数据模型、消息模型和一些一直在运行的系统。前期只需要 2-3 个小时就可以避免的问题却引起了6 周的“马拉松”——头脑风暴式的会话、相当复杂的反应、大量正确性测试以及一系列的小心翼翼的部署和迁移等。所有这些都只是为了在不中断系统的情况修复以上的问题。

在极端情况下,新框架或者代码的每一次部署都会是无缝的——仔细的规划、滚动重启和集成测试等。一旦系统在服务用户,就永远不能关机。

非常小心的进行自动部署和配置管理

现在的开发生态系统拥有大量的自动部署和配置管理的工具,包括 Chef、Puppet、Ansible、SaltStack、Terraform 等数不胜数。选择使用哪个工具就像决定哪个模型更好一样根本无关紧要。真正有关系的是你要使用这些工具。即使是在公司的初创阶段,即使事情看起来非常容易搞定,你也千万不要手动管理配置或者部署——你会犯错、你会限制自身能力的提升以及使得以后的自动化变得十分艰难。

但是,要小心:权力越大,责任越大。自动部署工具使得你可以把平台迅速搞砸。

利用 Chef 管理所有主机的 IP 表?一个疲惫工程师的一个无意的按键动作就可以使你的平台全部瘫痪。把一个经过反复测试的特性部署到开发用的环境中?一个真实环境和模拟环境中略有差别的流量就可以使得端到端自动部署的产品崩溃。要善用自动化工具!

Kris 等就利用 Ansible 管理 NSONE 的配置和部署。这是一个非常好的工具。 NSONE 团队本可以把一切自动化,实现一键部署新的 DNS 传输代码到所有的边缘位置。但是,他们没有这么做。他们选择从最低流量到最高流量,一个设备一个设备的部署。在一个设备内部,他们甚至挨个核或者挨个服务器,运行复杂的单步功能测试。在移动到更加关键的设备前,该团队还会花费数十个小时或者几天时间来研究度量,确认没有潜在的问题。而且在部署之前,他们还会进行应用程序代码以及 Ansible 配置等的仔细审查。

对于你的团队和应用而言,要适时的使用自动化。但是也别忘记,自动化加速项目发展的同时,也可以加速项目的死亡!

做好“消防演习”

坏的事情总会发生。每一个科技公司都会遇到服务器崩溃的情况。NSONE 团队在项目之初就想到了各种服务器崩溃的情况——磁盘失效、网卡失效、RAM 失效、内核崩溃、虚拟环境中的邻域效应等等。各种情况都可能非常容易的引起服务器失效。

此外,电源供应也可能出问题。还记得飓风桑迪吗?NSONE 的员工不得不不断加注柴油,才能保证系统在发电机的帮助下保持工作。

而且,光缆也可能会断。BGP 有可能被黑。你也可能遭遇 64k 的 ICMP 报文、DNS 和 NTP 放射放大攻击以及等等。你该怎么办呢?

唯一能做的就是提前进行演练。在坏的事情发生之间进行演练。Netflix 的 Chaos Monkey 就是一个很著名的例子。你不可能直接模拟可能遇到的每一种状况,但是你可以尽力去模拟你的反应。唯一能够保证你在遇到状况时可以保持镇定的方法就是,使用你已经提前放置好的工具,然后快速反应。

最小化表面积

随着你的应用程序变得越来越分布,暴露给恶意攻击的表面积也会在不经意间迅速增加。看好你的系统,并最小化系统暴露给互联网的表面积。

架构中的每一个角色都应该只向那些允许访问的系统集暴露其服务接口。面向互联网的系统只提供面向用户的那些服务。在后端,系统之间应该尽可能的通过私有 IP 空间进行通信。否则,也应该通过加密的通道进行数据传输。无论是使用像 AWS 的安全组这样的提供商的工具,还是使用路由器 ACL 或已经防火墙进行 ip 表规则的自动管理,你应该尽可能的是防火墙。首先拒绝,然后在逐个按情况放行。

永远都不要允许通过 SSH 等对产品系统进行直接访问。人们应该通过采用多元素认证、端口试探、IP 白名单等重重保护的主机来进入系统。确保主机分布于各种网络、多个地域。进入产品架构的权限应该也限制为只有堡垒似的主机才可以。

有很多种策略可以帮助你看好系统。你只要去寻找,然后从一开始就考虑到系统的安全,使得安全成为系统的一部分即可。千万不要随着系统的扩展而淡化安全因素。

了解供应商环境

几乎每一个现代技术公司都选择把第一代产品放置在 AWS、DigitalOcean 或者其他低价低门槛的云服务提供商中。互联网一直在快速发展。由此,云服务提供商也在近些年迅速增多。

绝大部分公司都没有必要在扩张时着急放弃 AWS。但是,每一个公司都应该尽可能的保留可选性。

你或许会发现应用程序中的一些负载在裸机中运行效率最高,也可能发现你需要一个在澳大利亚的 CDN,或者在没有 AWS 存在的市场中获得很多关键性的用户。那么,花一些时间来让自己熟悉框架生态系统的各个方面——IaaS 供应商、场地出租、DNS、CDN 以及监控等等。在早期设计架构时,就考虑到以后可能需要迁移的地方。时刻准备着迅速迁移。

NSONE 公司就操作着一个全球任意播的 DNS 传输网络。当建立原型的时候,AWS 起了很大的帮助。但是在平台部署之前,他们就不得不迁移到别的地方来满足网络需求。设计一个非常具有竞争力的任意播 DNS 网络很大程度上依靠公司与框架供应商、网络供应商等进行协商,获得尽可能多的控制权。在很多情况下,Kris 等人不得不帮助供应商来找到合适的合作方式。

千万别忘了:基础设施运营商也都是怪胎,他们也经常欢迎各种新的想法和挑战。时刻了解生态系统,做好准备工作。

总结

Kris 已经分享了自己在设计和扩展分布式、任务关键系统时的经验和教训。或许,你不能在项目初创之时就把一些都规划好。但是,你可以努力把自己放在一个更好的位置,来迎接公司扩张所带来的挑战。

此外,正在设计互联网产品的公司也应该认真思考如何以分布式的方法来设计产品架构和扩展之路,从而为用户提供最大的性能、最好的可靠性和安全性。

编后语

《他山之石》是 InfoQ 中文站新推出的一个专栏,精选来自国内外技术社区和个人博客上的技术文章,让更多的读者朋友受益,本栏目转载的内容都经过原作者授权。文章推荐可以发送邮件到 editors@cn.infoq.com。

点此可回溯到文章的第一部分


感谢杜小芳对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-11-18 17:383734
用户头像

发布了 268 篇内容, 共 122.4 次阅读, 收获喜欢 24 次。

关注

评论

发布
暂无评论
发现更多内容

知乎开发了一个搜索引擎

红泥

搜索引擎 百度 知乎

回"疫"录(3):让人怀念的普通一天

小天同学

疫情 回忆录 现实纪录 纪实

程序员5分钟:你的程序占用了多少内存?

顾仲贤

程序员

决定我们认知深度的究竟是什么?

石君

深度思考 方法论 连接

漫谈哲学与编程

keelii

编程 哲学

「超级右键」

非著名程序员

macos 程序员 效率工具 软件 Mac

如何阅读源码?

武培轩

Java 源码 面试 进阶 后端

在谈判中,你有哪些属于自己的独特的方法和技巧?

Yolanda

随手记备忘录的好习惯

changyou

敏捷开发 | 张三与需求管理

易成研发中心

敏捷开发 需求管理

基于Kubernetes的多云和混合云

倪朋飞

云计算 架构 Kubernetes 微服务 Service Mesh

程序员5分钟:你了解32位带符号的整型吗?

顾仲贤

程序员

程序员都应该了解的运维知识经验

松花皮蛋me

DevOps 分布式 运维

最近的一些人生感悟

小智

人生 哲学

世界知识产权日碎碎念

Yin

成长 随笔 知识产权

程序员陪娃漫画系列——看医生

孙苏勇

程序员 生活 陪伴 漫画

我为什么选择infoq写作平台

三爻

克制文章长度

changyou

很不幸,自动化测试永远只能是必要非充分条件

刘华Kenneth

DevOps 敏捷 自动化 测试 金字塔

别总说CMS、G1,该聊聊ZGC了

猿人谷

CMS G1 ZGC JVM

Golang 真的好用吗?

极客时间

编程语言 Go 语言

除了负载均衡的算法,你还应该知道这些

松花皮蛋me

Java 负载均衡 分布式

小论互联网项目管理

南方

项目管理 互联网 个人成长 碧海潮生曲

Java并发编程系列——线程

孙苏勇

Java 并发编程 线程

聊聊苹果公司技术部门的宫斗和冷战

赵钰莹

程序员 外包 apple

爱他,就让他走?

Selina

团队管理 领导力 团队协作

前端如何搞监控总结篇

大前端洞见

大前端 监控 全链路监控

加班能解决交付的期望么?

拖地先生

项目管理 领导力 管理 时间管理

程序员陪娃漫画系列——修龙头

孙苏勇

程序员 生活 陪伴 漫画

微信朋友圈为什么没有阅读数?

彭宏豪95

微信 产品 产品设计

Java并发编程系列插曲——对象的内存结构

孙苏勇

Java 内存模型 面向对象 ClassLayout

设计全球级的分布式、任务关键型应用——从实际项目中得来的教训(下)_语言 & 开发_张天雷_InfoQ精选文章