文 / 陈波
前不久,Facebook宣布投资10亿美元收购仅成立15个月的移动照片分享应用Instagram,消息传出时,人们不仅惊叹于这笔巨额的交易,更为这支13个人的小团队感到不可思议。Instagram的Android版客户端发布时,24小时内下载量超过100万,高峰期达到每分钟2000次,是下载量最大的Android应用之一。究竟是什么原因让这支团队在很短的时间内一鸣惊人?又是什么技术让他们在巨大的下载量下顶住了压力?让我们回顾一下Instagram开发团队奉行的3大原则:
总而言之,专注于自己的业务和擅长领域,其他事情让更专业的人去做。Instagram选择了美国的亚马逊云计算平台作为基础设施提供商,它部署了数以百计的云服务器和存储服务,却只有区区3名工程师负责维护,不需要任何现场人员支持。如果依赖于传统的IDC服务,光是把这几百台服务器托管到IDC机房,就需要数天时间和大量的人力成本。每当发布一个新版本时,Instagram所要做的只是在云计算平台上开启更多的服务器,便可稳坐钓鱼台,看着自己应用的下载量节节攀升了。
阿里云弹性计算平台(Elastic Compute Service,简称ECS)面向中国互联网开发者和站长,致力于为中国的Instagram提供靠谱的互联网基础服务。它基于底层的飞天分布式计算系统,结合高性能虚拟化技术,实现了计算、存储和网络资源的统一调度和弹性分配。在具体的产品形式上,客户接触的是最简单的云服务器,与物理机无二,没有任何的使用门槛。由于采用了云计算技术,相比传统的IDC托管服务,弹性计算在自助管理、资源组合灵活性、基础环境定制化、数据安全性及硬件资源利用率上都有不小的优势。
在本文中,我们将和大家分享在云计算平台上构建高可用、可扩展应用的一些进阶技巧。考虑到有些读者尚未接触过ECS,所以在进入正题之前,让我们简单浏览一下ECS的各项特性。
自助管理
ECS在aliyun.com的控制台中提供了多种用户自助的操作,例如最为常见的创建、启动、关闭云服务器,将来还会陆续推出比较高级的快照、回滚、自定义镜像(Image)等功能。回想我们以前遇到服务器不可访问时,提交工单、电话催促,在经历漫长等待之后,也未必能够得到一个满意的答复。现在,我们可以在控制台中全程监控和管理每一台服务器的运行情况,从而做出快速的决定——重启或者部署新的服务器。
ECS支持目前主流的Windows和Linux系列操作系统。用户不仅可以使用这些标准的镜像,还可以在此基础上修改配置、安装软件,创建出自己的镜像,当要快速恢复基础环境或者批量部署集群时,自定义镜像将成为提高运维效率的利器。
图1简单地描述了一个自定义镜像的生产过程。
数据可靠性
对于写入VM磁盘的数据,ECS会实时地在不同的交换机下同步3份拷贝,当集群中的磁盘损坏时,后台进程也会自动地重建故障磁盘的数据。相比常见的RAID硬件方案,这种分布式存储系统能够提供更高的数据安全保障,因为它不受单台服务器可用性的限制,并且,由于多台服务器可以并发处理,数据恢复的时间更短。
ECS提供的在线快照功能可以完美地替代传统的复制备份,它采用先进的增量数据算法,确保做到备份空间和时间的最优化。当用户数据被误删或者系统被病毒破坏时,只需要一个简单操作就可以瞬间恢复环境。
自动故障恢复
有了分布式存储的支持,ECS可以提供比传统主机或VPS服务更高的可用性指标。当一台物理机损坏时,ECS会自动监测到硬件故障,在第一时间内把云服务器迁移到新的宿主机上,同时硬盘数据保持最后一刻的状态。如图2所示。
从以上介绍可以看出,托管在弹性计算平台上的应用可以获得更多的保障,但我们是否可以认为,将应用搬到云计算平台之后,它就能跑得欢快、永不宕机,还能自动扩展了?答案是NO!
每时每刻,硬盘、主板、电源或者网络设备都可能突然损坏,甚至整个数据中心发生停电。云计算技术没有办法解决所有硬件问题,只是降低了某些故障的发生几率,例如:
如果我们的应用只能跑在单台服务器上,只能依赖单台设备的硬件升级才能应付日益增长的访问量,那么这种应用的宕机是迟早的事情。事实上,我们需要从部署架构和应用架构两个方面来破解这个难题。
部署架构
既然没有什么硬件是永不损坏的,我们是否可以用多份冗余的硬件来降低故障的概率?如果挨在一起的服务器被一把火烧掉的可能性太大,我们是否可以把它们分散在不同的集群?如果数据可能被破坏,是否要经常做些备份?……
把各种故障因素都考虑一遍,我们就可以得出下面这个大致的部署框架。
以集群方式提供服务
Web服务器、缓存服务器都是非常适合部署为集群的,单台服务器损坏不会影响整个网站的访问。数据库服务器稍难一些,但它们也提供了主从复制、读写分离的解决方案。
将云服务器分布在不同的可用区(Zone)下
不同的可用区代表数据中心里的不同物理位置,同一可用区内的服务器可能同时遭遇网络设备、电力等故障,因此,把一个集群内的云服务器分散到不同的可用区甚至不同的数据中心(Region)是个明智的选择。
为Web服务集群配置负载均衡与DNS轮询
多台Web服务器可以通过配置负载均衡或者DNS轮询提供对外服务。DNS轮询,负载均衡方式会更加灵活,因为它对外屏蔽了服务器的真实IP,当负载均衡资源池内增加或减少服务器时,对客户是透明的。而DNS存在时延的问题,集群发生调整后,很有可能造成部分用户在很长一段时间内无法正常访问网站。
另外,负载均衡能够跟踪后端应用服务器的健康状态,自动排除有故障的节点,避免出现服务时断时续的问题。
对于特别大的应用,我们推荐使用负载均衡+DNS轮询的方式,只是这里的DNS轮询域名指向的是负载均衡的VIP。
实现动态部署
为了应对经常性的业务推广和可能的DDoS网络攻击,实现系统与应用程序的一键部署很重要。系统管理员可以根据应用的当前状态(CPU、内存使用率、HTTP的响应时间等)作出判断,即时增加服务器,并且快速部署应用程序,顶住突增的业务流量。如果实现得更智能一些,可以在应用服务器内部部署一些监控程序,由主控程序判断当前整个集群的负载情况,调用ECS API自动增减服务节点。
用一台主控机去批量操作其他云服务器时,应该尽量使用一些便捷工具,例如SSH密钥对,它实现了授权服务器间的免登录,使得集群管理更加简单。
定时备份很重要
前面说到,没有什么技术可以保证100%的数据安全,你的数据始终面临误删文件、病毒破坏、程序写错、硬件损坏等种种可能的风险。如果你的数据非常重要,请定期备份!在弹性计算平台上,这件事情相对简单,快照功能自动完成增量数据备份。然而,单个物理位置的存储始终会面临地震、火灾等灾难的威胁,如果你觉得还不够安全,或者有异地使用的需要,且能够承受异地备份带来的存储、带宽等成本,可以自行拷贝数据文件。弹性计算平台也正在考虑跨机房的容灾方案。
将应用程序配置为自恢复的
单台服务器的硬件故障是常见现象,以现有的云计算技术能力,尚无法做到不影响云服务器的运行,但ECS可以快速检测到故障特征,并且将云服务器自动迁移到新的宿主机上。这里存在一个问题,虽然云服务器重新启动了,而且硬盘数据恢复到最后一刻的状态,但原先正在运行的应用程序中止了。为了让你的服务中断时间尽量地缩短,避免人工的介入,强烈建议将应用程序及相关服务设置为开机自启动,这样,你就可以高枕无忧地睡大觉,不用半夜起来恢复应用,尽管只是几个点击或者命令操作。
加固系统
安全也是高可用的重要前提之一。放在IDC机房中的服务器时时面临各种恶意攻击,图3是我们偶然截取的一个攻击片段。
这台服务器在循环探测机房中每一台机器的1433端口,有经验的读者很快猜出来了,它是在试探SQLServer服务,一旦SQLServer被攻破,再利用SQLServer管理员的系统权限漏洞,马上就有一些机器沦为肉鸡。
阿里云弹性计算服务在平台层面就屏蔽了一些影响范围很大的恶意攻击,例如篡改MAC、伪造IP、发送ARP欺骗包等,但用户的系统还是要遵循一些安全最佳实践,才能让自己的系统更加稳固。
越多的服务意味着越多的漏洞,特别是Windows共享文件夹、远程修改注册表项等服务都存在巨大的风险,如果你的工作不需要这些服务,请马上关闭。
前段时间爆出的微软高危RDP漏洞让很多用户深受其害,通过一个简单的Python脚本,黑客就可以直接获取系统管理员权限或者直接把服务器打至蓝屏。不要忽略操作系统厂商的安全警告,一旦遭遇攻击,将造成不可挽回的损失。
采用白名单控制策略,只开放最小集合的端口。对于数据库服务器,更要设置IP白名单,仅允许前端的Web服务器访问;对于Web服务器,只对外开放80端口。
从刚才的攻击示例看出,黑客虽然漫无目的地扫描同一网段的IP,但攻击的目标端口只有一个1433,这是SQLServer的默认配置。为了减少这类攻击,最有效的方式就是修改数据库、FTP这类常见服务的默认端口,增加黑客扫描的难度。
我曾经遇到过一个很奇怪的现象,在一台Windows 2003服务器上,应用的负载很低,但CPU利用率达到了99%,从任务管理器中看到,有无数个winlogon.exe进程疯狂消耗CPU,当时百思不得其解。一天之后,这台服务器就沦陷了,我才恍然大悟,一定是攻击者在尝试破解密码。对于这类攻击,即使调整密码长度增加破解难度也收效不大,因为攻击过程会消耗大量的系统资源,正常的业务根本无法进行。何况,现在的服务器计算能力越来越强,一个密码的安全性实在太低了。
一些加密传输方式能够有效地抵御这类攻击,也能减少传输过程中的敏感信息泄露问题。Windows可以配置远程桌面服务使用SSL传输,要求客户端必须持有证书登录。Linux则可以使用SSH登录密钥对。结合修改默认端口的方式,将使你的系统安全性提高一个层次。
友情提醒:如果你开启了防火墙,又修改了默认的远程桌面或者SSH端口,请务必在防火墙中设置这些服务的白名单,否则就悲剧了。
应用架构
要支持上述高可用、可扩展的部署架构,应用程序也要做相应的调整。
Web应用的无状态设计
Web应用的诸多因素可能造成系统无法扩展:本地存放的上传文件、进程内的Session等。以上传文件为例,假设使用了本地存储,用户第一个请求上传了一个头像文件,存放在Web-A服务器上,接着刷新页面,但这个请求被发送到Web-B服务器上,他惊奇地发现:上传的头像文件不见了!要解决这个问题,必须把上传文件存放到共享的文件夹,Web服务器不能保留任何自己的数据(即无状态)。而对于Session数据,一般的建议是用Cookie代替,或者存放到共享的Session服务器或者数据库中。
用分布式服务代替单点的服务
单点就意味着故障,不仅有可用性的风险也有性能瓶颈的问题。常见的单点一般出现在共享文件服务器、Session服务器、缓存服务器、数据库服务器。阿里云计算平台提供了一系列分布式服务,是这些单点服务的可行替代方案。
对于平台暂时不提供的分布式缓存服务,业界也提供了一些解决方案,例如Memcached集群技术,但这也对应用程序的设计提出了更高的要求,开发者必须清楚各种服务的HA原理,还需要了解一致性哈希算法等细节的实现。
应用的安全不容忽视
安全不仅是操作系统配置的问题,堡垒更容易从内部被攻破,而这个内鬼很有可能就是我们的应用。从概率上说,一个复杂程序会比一个简单程序多很多漏洞,而Web应用涉及数据库、应用服务器、缓存等诸多组件,稍有不慎,攻击的后门就会向黑客敞开。常见的Web服务漏洞有以下几种。
这类Web攻击最为普遍,一般发生在允许用户输入内容的页面,尤其是提供富文本编辑的模块。几乎所有的网站都会被XSS攻击光顾,但防御这类攻击也是最为简单的:限制用户输入,并且在页面输出内容时对敏感字符进行编码,相对来说,后者更为重要一些。PHP语言的htmlspecialchars函数、Java Jakarta commons的StringEscapeUtils类都是实现编码功能的快捷工具。
只要应用代码中存在这样的SQL:
那么这个应用距离沦陷也就不远了,攻击者只要输入一个值为的
name就可以轻易进入你的应用系统。杜绝这类问题的方法有2种:对输入的特殊字符进行转义,例如PHP的mysql_real_escape_string函数;或者采用参数化的SQL,例如:
后者实现更加优雅,绝对避免了SQL注入的风险,而且在提升数据库的查询性能上也会有所帮助。
这是最为危险的应用级漏洞,特别容易出现在允许用户上传内容的网站中。假设一个tomcat搭建的Web网站允许用户上传附件,却忘了限制上传目录的可执行权限,攻击者就可以上传一个带webshell的jsp文件,通过访问这个上传文件的URL就可以完全控制网站服务器。一定要取消上传文件的可执行权限,另外,绝不允许这类文件被当作服务端脚本解析。赶紧为你的网站实施安全策略吧!
只要会用HttpWatch、Firebug等开发工具,大家都可以看到各大网站的Cookie数据,而这些Cookie正是网站用于鉴别用户身份的凭证。通过分析Cookie构成,黑客有可能猜测出网站的鉴权策略。要想让你的应用更安全,可以对Cookie等敏感数据进行加密。如果你的网站还包含在线支付功能,部署带授权证书的HTTPS是必不可少的,这也是很多第三方支付平台的强制要求。
综上所述,虽然云计算平台提供了更灵活、更稳定的基础服务保障,但它不足以解决应用的高可用性和可扩展性问题,应用自身必须在架构设计和部署上充分考虑各种意外情况,才能实现真正意义上的高可用、可扩展。