基于开源软件在Azure平台建立大规模系统的最佳实践
前言
Microsoft Azure 是微软公有云的唯一解决方案。借助这一平台,用户可以以多种方式部署和发布自己的应用。 这是一个开放的平台,除了对于 Windows 服务器和 SQL Server 的支持,Microsoft Azure 也支持了大量主流开源软件和框架,包括 Linux, Tomcat®, Java®等。如何将一个基于开源软件的系统迁移到 Microsoft Azure 平台,并充分发挥云在弹性、敏捷性等方面的优势? 本文和读者分享一些最佳实践经验,并在文末以中国网络电视台的系统迁移作为参考案例。
阅读本文之前,希望读者对 Microsoft Azure 有所了解。读者可以登录 http://www.windowsazure.cn 得到关于这一平台的各项信息。本文提到了如下概念:
- 基础设施即服务(IaaS: Infrastructure as a Service): 消费者通过互联网获得计算机基础设施类的资源,包括计算资源(虚机),存储资源和网络资源等。
- 平台即服务(PaaS: Platform as a Service): 云平台的服务提供商对资源在 IaaS 的基础上做进一步封装,将 IaaS 层对用户透明。消费者借助开发工具和一系列开发语言,在云平台上构建自己的应用,而无需管理和维护虚机、存储、网络等基础设施。
在 Azure 中使用 Linux 虚拟服务器:
Azure 平台目前支持三种类型的 Linux 操作系统: UBUNTU, CENTOS 和 SUSE。他们的版本分别是:
- Ubuntu Server 12.04 LTS
- Ubuntu Server 12.10
- Ubuntu Server 13.10
- Ubuntu Server 14.04 LTS
- OpenLogic
- SUSE Linux Enterprise Server 11 SP3
在 Azure 平台使用 Linux 虚机,有如下最佳实践帮助用户得到更好的体验。
为 Linux 配置交换分区(SWAP)
在 Linux 中保留 swap 分区有两个重要的原因:
- 当物理内存不足以支撑系统和应用程序(进程)的运作时,这个 swap 空间可以用作临时存放使用率不高的内存分页,把腾出的内存交给急需的应用程序(进程)使用。
- 即使你的机器拥有足够多的物理内存,也有一些程序会在它们初始化时残留的极少再用到的内存分页内容转移到 swap 空间,以此让出物理内存空间。对于有发生内存泄漏几率的应用程序(进程),swap 空间更是重要,因为谁也不想看到由于物理内存不足导致系统崩溃。
在 Azure 平台上,当用户通过镜像库,创建出一台 Linux 服务器时,默认并没有分配任何交换分区。运行 free 命令,我们可以看到 swap 所对应的数字为0。
读者也许会问,既然 swap 分区如此重要,为什么 Azure 平台的镜像不自动配置好 swap 分区?一个重要的原因是, swap 分区的大小和位置是由用户各自的使用场景决定的,Azure 保留客户自己定制的灵活性,把这一工作留给用户,在虚机创建之后进行。
如何创建 swap 分区?下面的例子在/mnt/resource 目录下创建 5GB 的 swap 分区。
- 切换至 root 用户
- 运行命令: fallocate –l 5g /mnt/resource/swap5g
- 运行命令: chmod 600 /mnt/resource/swap5g
- 运行命令: mkswap /mnt/resource/swap5g
- 运行命令: swapon /mnt/resource/swap5g
Linux 虚机的非持久化磁盘
每一台 Linux 虚拟服务器都自带一块非持久化磁盘。这块磁盘的读写速度很高,但它并不存在于 Azure 的持久化存储设备上,而且在宿主机上。用户一定要注意不能把需要持久化的数据放在这个目录下/mnt/resource,否则当服务器重启以后,这些数据 将会丢失。
在 Azure 中使用 Tomcat
如果用户原有的应用部署于 Tomcat 服务器上,有两种迁移模式:IaaS 和 PaaS。使用 IaaS 模式,用户通过 Azure 创建虚机,并把 Tomcat 安装到虚拟服务器上,然后部署应用。使用 PaaS 模式,用户借助 Azure 提供的工具,将原有应用部署为“云服务”。如果客户的应用并不一定要求是 Linux 操作系统(即应用中没有使用到 Linux 操作系统的特殊功能),我们推荐的方式是 PaaS。下面我们仔细讲解把 Tomcat 应用部署为 Azure Cloud Service 的优势和便利之处。(如何通过 Eclipse 将 Tomcat 应用部署到 Azure,请参考官方文档: http://msdn.microsoft.com/library/azure/hh694271.aspx )
当我们在 Eclipse 中创建了 Windows Azure 工程以后,单击右键,选择“部署”。在弹出的部署对话框中,我们可以看到对于 JDK 和 Tomcat 的部署有三种方式:
- 使用客户本地开发环境的 JDK 和 Tomcat。
这种方式最为直观,客户只需指定自己机器上 JDK 和 Tomcat 所在的位置即可。缺点是上传的时间较长。不过这样的工作只需在第一次部署时进行,以后更新应用程序时将不再需要。
- 使用第三方提供的在 Windows Azure 上的 JDK。
- 使用 Azure 存储中的 JDK 和 Tomcat。
这种方式需要客户提前将 JDK 和 Tomcat 压缩包上传到 Azure 存储中。客户可以借助一系列工具,例如 Windows Azure Storage Explorer, AzCopy 等。这种方法最为快捷,也是笔者推荐的。
在 Azure 中使用 MySQL
通过 Microsoft Azure 的镜像库部署 CentOS 虚拟服务器,在 YUM Repository 里自带了 MySQL 的安装程序包。用户可以很方便的通过”yum install mysql”安装 MySQL 服务器。对于部署了 MySQL 的虚机,请执行命令“chkconfig --list mysql”将 MySQL 进程加入到虚机启动程序里。这样,当虚机被重启时,可以保证 MySQL 服务自动恢复正常。
如何实现 MySQL 的高可用性架构。客户有多种选择,例如通过 MySQL, Heartbeat, DRBD 来做虚机状态监控和数据同步。也可以选择 Oracle 版本的 MySQL Cluster。在全球的 Azure 实例上,客户还可以直接采用 ClearDB 提供的 MySQL as a Service。
对于大规模应用的最佳实践
使用 Azure PowerShell 批量部署虚机
当我们需要部署上百台甚至更多的虚机时,使用基于浏览器的 Azure 管理门户是非常耗时的。特别是如果我们需要在短时间内将服务器就绪,使用图形界面人工操作更是不现实的。Azure 管理门户提供的所有管理功能都可以通过 PowerShell 来实现。对于非 Windows 环境,Azure 也提供了命令行接口。
例如,我们需要部署 100 台基于 CentOS 的 Apache 服务器。推荐的方法是首先通过 Azure 镜像库部署一台 CentOS 服务器(目前的版本是 CentOS 6.5)。安装 Apache,并对其进行自己需要的配置。之后,将这台虚机制作为镜像(image)。制作方法参考: http://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-capture-image/ 。制作完成后,我们就可以通过这个镜像文件,批量部署虚机。参考下面的 PowerShell 脚本。
注意: Azure 的云服务(Cloud Service)目前最多可以容纳 50 台虚机。如果您的应用程序需要 50 台以上的虚机,则需要创建多个云服务。
使用 Azure 的自动伸缩功能
很多时候,我们对系统规模的需要是动态的。例如一个投票系统,平时的用户访问量不大。当有大型活动(例如春晚)的时候,系统访问量激增。这是我 们需要系统的规模随需而变。还有些爆发性增长是不可预测的。针对这种场景,Azure 提供了自动伸缩功能。您可以根据 CPU 使用率的平均百分比或基于队列中的消息数指定缩放。
在 Windows Azure 管理门户的“缩放”页上,您可以手动缩放应用程序,也可以设置参数使其自动缩放。您可以缩放运行 Web 角色、辅助角色或虚拟机的应用程序。若要缩放运行 Web 角色或辅助角色实例的应用程序,您需要添加或删除角色实例以适应工作负载。
在配置应用程序的缩放之前,应考虑以下信息:
- 您必须将虚拟机添加到可用性集,才能缩放使用它们的应用程序。您添加的虚拟机最初可能处于打开或关闭状态,但它们在扩展操作中将打开,在缩减操作中将关闭。有关虚拟机和可用性集的更多信息,请参见管理虚拟机的可用性。
- 缩放受内核使用情况影响。较大的角色实例或虚拟机使用更多内核。您只能在您的订阅的内核限制内缩放应用程序。例如,如果您的订阅的上限是二十个内 核,并且您通过两个中等规模的虚拟机(一共四个内核)运行某个应用程序,则对于订阅中的其他云服务部署,您只能扩展十六个内核。可用性集中用于缩放应用程 序的所有虚拟机必须具有相同大小。
- 您必须先创建队列并使其与角色或可用性集关联,然后才能基于消息阈值缩放应用程序。
- 您可以缩放链接到云服务的资源。
使用 Azure 虚拟网络提高整体性能
当我们使用 Azure 的 IaaS 服务创建虚机时,往往需要几台虚机之间达到高速的互连互通。例如,我们创建了一个 Windows Server 2008 R2 作为应用服务器,还创建了一台 SQL Server 2008 R2 Standard 作为数据库服务器。当应用服务器访问数据库服务器时,我们希望它们通过 Azure 内部网络(即后台数据中心中的网络)彼此对话,而不是要绕过 Internet。要达到这个目标,有两种方法:
- 将这些虚机放在同一个云服务里。
- 将这些虚机放在同一个虚拟网络里。
在一个经典的三层架构的系统中,我们通常都要借助虚拟网络来部署虚机。由于目前一个云服务最多容纳 50 台虚机,仅使用云服务往往是不够的。因为系统规模扩大后,很可能超过 50 台的限制,这样我们就需要部署多个云服务。在多个云服务中,Azure 并不保证虚机的互联互通走的是内网 IP。如何使用虚拟网络部署虚机,读者可以参考这篇文章: http://blog.csdn.net/azureincubationchina/article/details/10212871 。
在某种情况下,系统被部署成 PaaS 和 IaaS 混合的模式。例如 Web 服务器部署为云服务,数据库服务器部署在虚机上。这时,我们仍然希望 Web 服务器和数据库服务器处于同一虚拟网络中。要达到这一点,用户首先将 IaaS 虚机部署到某个虚拟网络中,之后编辑云服务的*.csfg 文件,加入下面的段落即可。
中国网络电视台 (CNTV) 案例参考
有关 CNTV 在 Microsoft Azure 的应用场景和商业价值,读者可参考下面的文章。本文集中介绍技术架构部分。
- Windows Azure 助力马年春晚网络直播,为 CNTV 带来三大惊喜: http://blog.sina.com.cn/s/blog_6b8988220102edgt.html
- CNTV 转型“一云多屏”新媒体微软 Windows Azure 保驾护航: http://www.cnetnews.com.cn/2014/0216/3011306.shtml
技术架构
CNTV 原有数据中心存在丰富的 IT 资源和关键数据,如何将原有 IT 系统与 Windows Azure 融合,以获得系统资源最佳的利用率和的效率是需要重点考虑的问题。CNTV 的 VDN 视频分发网络需要达到每秒处理 8 万次用户请求,经过多次测试与论证,CNTV 原有 IT 系统承担 40% 的用户请求,另外 60% 的用户请求将有 Windows Azure 完成,也就是 CNTV 内部设有一条基线,基线以下的业务放在原有 IT 系统中,而基线以上的业务则放在 Windows Azure,比如每天有 4000 万的 UV 访问,基线是 1600 万的 UV,超过 1600 万 UV 请求就会放在 Windows Azure 之上,而整个的切换过程属于无缝切换,用户完全感受不到。
在 Windows Azure 中,CNTV 的 VDN 前端 Tomcat 服务器采用 Azure Cloud Service 中的 Worker Role,接收来自客户端的请求,并返回结果。用户使用 Eclipse,安装 Azure SDK 插件作为开发和发布环境。在前端,用户部署了两个 Cloud Service,一个部署在 Azure 北京数据中心,另一个在上海数据中心。在两个 VIP 的前端,用户的 F5 设备对 HTTP 请求进行分流。
当 Tomcat 服务器接收到请求后,需要首先访问 MEMCACHE 服务器,查找数据,如果缓存中不存在要查询的数据,则访问后台 MySQL 数据库,并更新 MEMCACHE。在 Windows Azure 中,MEMCACHE 服务器和 MySQL 服务器,分别由多个实例组成负载均衡集。
用户自有数据中心中运行着 MySQL 的主库。主库通过 V*N 连接,定期将数据同步到 Windows Azure 上的从库中。
在 Azure Cloud Service 中,每种角色对应多个实例,属于同一个负载均衡集。当其中一台虚机发生问题,Windows Azure 会自动生成一台新的虚机替换。当系统发生后台维护时,Windows Azure 也会确保这组虚机不会同时重启,从而保证服务的延续性和系统的高可用性。
对于数据库管理系统,MySQL Master DB 在客户自有数据中心,Slave MySQL 在 Windows Azure 中。两边通过 MySQL Bin-log 进行数据同步。同时,两台从库属于一个高可用集。通过开源框架 Guzz 实现了 MySQL 的读写分离。
参考文档
- Windows Azure Plugin for Eclipse with Java
- http://msdn.microsoft.com/library/azure/hh694271.aspx
- 下载 Eclipse IDE: http://www.eclipse.org/downloads/
- 下载 Azure Storage Explorer: http://azurestorageexplorer.codeplex.com/
- 下载针对 Azure 存储的高速上传和下载工具 AzCopy: http://blogs.msdn.com/b/windowsazurestorage/archive/2012/12/03/azcopy-uploading-downloading-files-for-windows-azure-blobs.aspx
- 下载 Azure PowerShell: http://az412849.vo.msecnd.net/downloads01/windowsazure-powershell.0.6.15.msi
- 下载跨平台命令行接口: http://az412849.vo.msecnd.net/downloads02/windowsazure-cli.0.6.17.msi
- 在 Azure 中为 Linux 虚机制作镜像文件: http://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-capture-image/
- 如何缩放应用程序: http://www.windowsazure.cn/zh-cn/manage/services/cloud-services/how-to-scale-a-cloud-service/
感谢马国耀对本文的审校,刘大玮和 Shirley Wang 对本文的策划。