高性能网站构建实战

978-7-115-29478-4
作者: 刘鑫
译者:
编辑: 陈冀康

图书目录:

详情

本书从第一章对网站架构一个整体的介绍;然后会根据网站的层次,介绍了如何使用开源软件来构建Linux下的各种服务,以现下最为流行的LVS,HAProxy,Nginx,Hadoop等开源工具为讲解内容,帮助读者掌握从应用到底层架构的整体技术。

图书摘要

高性能网站构建实战
刘鑫◎编著
人民邮电出版社

北京

内容提要

目前,越来越多的网站采用Linux操作系统来提供各种服务,包括搭建Web服务器、文件存储、数据库等。人们对Linux服务器的可靠性、负载能力和计算能力也越来越关注。

本书从高性能站点的实际需求出发,详细介绍了如何使用当前流行的开源软件和工具构建Web站点所需的各种应用服务环境。全书共分为7篇16章和3个简短的附录。

第一篇是架构规划篇,也就是第 1 章,主要介绍了对企业网站架构的选型、系统的快速安装及初始化高性能系统的一些参数。第二篇为负载应用篇,包括第2章到第4章,分别介绍了LVS+KeepAlived、HAproxy、Nginx这3种负载开源软件的应用。第三篇为页面缓存篇,包括第5章、第6章和第7章;分别介绍了缓存软件Squid和Varnish,以及Nginx的缓存功能。第四篇为Web服务器篇,包括第8章和第9章,分别介绍了Apache、Lighttpd和Nginx这三款流行的Web服务器。第五篇为数据缓存篇(NoSQL),包括第10章、第11章和第12章,分别介绍了Memcached,以及两种当前非常流行的NoSQL数据库软件Redis和MongoDBC。第六篇为文件服务篇,包括第13章和第14章,介绍了MFS和Hadoop。第七篇监控应用篇,也是最后一篇,包括第15章和第16章,介绍了流量监控软件Cacti和系统监视软件Zabbix。附录部分,分别给出了使用ipvsadm命令、HAProxy和Squid的有用参考资料。

本书是作者多年Linux系统架构和运维经验的总结,兼具宏观性知识介绍和具体性实践技能,适合对系统架构、性能维护感兴趣的初级、中级读者学习,对于有经验的系统架构师和运维师也有一定的参考借鉴价值。

作者简介

刘鑫,运维工程师,曾担任过操作系统讲师,喜欢讨论各种网站架构上的技术,特别是对系统级的优化。对整体网站架构的把握以及各种架构中运用的技术有一定的实施心得。对Python情有独钟,喜欢编写运维自动化工具。他是ChinaUnix社区集群和高可用版块资深版主,经常在社区内发起技术讨论,深受广大 CU(ChinaUnix)社区会员喜爱。博客地址:liuxin1982.blog.chinaunix.net。

推荐序

随着互联网的发展壮大,有这样一群人被冠以“运维工程师”的职业称呼,他们的工作涉及了网络、负载、性能、安全、监控、数据库和脚本编程。

而本书的作者就是这样一位攀爬在技术领域的前进者。

不论你是懵懂的“菜鸟”,或者是有着多年工作经验的资深“老手”,抑或是以开发为主的从业人员,你都不应该错过这本书。

通过阅读本书,你将更深入地了解软件形式的负载均衡的魅力,领略LVS/Haproxy/Nginx的不同,今后在面对多种架构方案的同时,可以快速选型,提升系统性能,降低维护和支出成本,节省资源。

通过阅读本书,你将学习到如何使网站的访问请求更加迅捷,并可亲自实施部署,获得良好的用户体验。

通过阅读本书,你将更容易了解NoSQL数据库的安装、部署和运维,以及各种NoSQL的架构应用。

通过阅读本书,你将综合学习到当下流行的Web服务平台Apache/Nginx/Lighttpd的应用方法和不同应用场景的介绍。

通过阅读本书,你将体验到Hadoop分布式文件系统的应用也没有那么神秘和遥不可及。

通过阅读本书,你将再也不用被故障折腾得焦头烂额,你也可以未雨绸缪变成先知,将故障扼杀在萌芽状态,避免跟领导汇报故障的尬尴。Cacti和Zabbix将让你得心应手。

本书是作者多年的工作经验积累,不断学习、探索、智慧的结晶,书中的内容都是当前形势下较流行的架构和应用。相信通过本书的学习,你可以解决很多日常工作遇到的难题,也可以使自己更深入地理解运维工作的方方面面,并借鉴书中的架构场景,运用解决实际的应用需求。

在技术的道路上“达者为师”,作者不吝将多年的经验总结编写发布,分享精神值得敬佩。希望本书可以帮助更多的技术人员避免一些错误的领会和自行摸索的困难。

相信通过努力,不断前进,每个人都能达到自己心中的目标。

借用文学家韩愈的名言与作者和读者共勉:“业精于勤而荒于嬉,行成于思而毁于随”。

悠易互通(北京)科技有限公司 运维总监 王建

2012年8月

Gray1982:

ChinaUnix社区作者访谈

采访嘉宾:刘鑫(Gray1982)

2004年毕业,主要从事IT培训、技术支持、高性能网站架构等相关技术的研究工作。目前就职于某知名互联网公司主管运维工作,负责网站架构的相关技术,以及对Hadoop的研究。

本次访谈我们也邀请到抚琴煮酒版主参与主持,感谢!

欢迎大家跟帖提问,我们对于跟帖提问的网友给予30积分的奖励。更多访谈请关注ChinaUnix访谈录:http://star.chinaunix.net/。

抚琴煮酒:

刘总,您目前也算是 Linux 运维的元老了,你当时是怎么进入这一行的,在你的职业发展过程中,有没有走过弯路?有什么经验和教训跟大家分享一下。

2003年考取MCSE,之后我就一直喜欢对系统及应用软件进行研究,做视频、做音频、做动画、做网页、做图片的经验都有过。2004 年正式开始学习 Linux,然后就喜欢上了这个系统。因为有了学习MCSE的经验,所以对Linux也是从基础学起,很系统地学。之后做讲师、做技术,因为身体原因,不方便经常出差,所以选择了运维行业。

初入这行,不懂的比较多,所以没事的时候常去招聘网站看看这类职位所需的技能,也算是了解下“行情”,确定学习方向,这样比盲目学习效率更高一些。

行万里路不如名师指路,如果真没人指导,建议大家没事去来咱们 CU 论坛走走,加入一些技术群。有可能你会看到许多不会的问题。不懂没关系,知道别人怎么解决的,就是你的收获。

抚琴煮酒:

运维在日常工作中具体从事哪些工作,工作的重点、难点你认为在哪里?

Gray1982:

运维一般分为操作和应用运维,比如有的负责初始化系统脚本(增加通用的配置、监测网卡速度、连通率等),根据不同的业务对系统用户进行管理等。对服务器进行常规监控,报警处理。业务的更新部署,还需要配合开发诊断程序的错误。其实这些工作没有太多的技术性可言,只要细心一点就可以。

相对来说,应用运维需要了解的内容就比较多了,如各种负载(LVS、HAProxy),页面级缓存(Squid、Varnish),KV、分布式缓存(Redis、Memcache)、分布式文件系统(MFS, Hadoop),等等。除了要了解这些应用适用于什么样的业务情况,还需要对其进行适当的优化,这样还可以节省一批机器,减少公司的运营成本,也算为公司做出了一些贡献。因为现在很多公司片面追求快速发展,不讲究细节,功能只要能用就行,所以带来很多的弊端。不仅浪费资源,整个架构也不够完美。所以作为运维人员,为了公司的发展,整个架构的健壮性、可扩展性至关重要,但也往往是很多公司所忽略的。

如果想“偷懒”,最重要的就是自己写脚本。几台机器的情况你也许不在意,如果几十台甚至几百台呢?开源的软件也许能解决一些问题,但这些软件并不是专门为公司的业务开发的,所以总有些方面不合适。所以还是建议要么对这些开源软件进行二次开发,要么专门为这些业务写一些工具以满足公司的需求。这也是运维在工作中很重要的能力。

抚琴煮酒:

自动化运维和Linux集群方面有什么经验跟大家分享吗?

Gray1982:

就像我上面说的,一个出色的运维,不仅仅需要了解与掌握架构所需要的技术知识,还需要在实际生产环境中写出适合业务的工具来提高效率,减轻自己的压力。自动化运维除了要具备自行编写脚本的能力以外,还要能对服务器进行标准化部署,比如设置每台服务器软件放置的位置、脚本的运行等。如果没有标准化,服务就是一盘散沙,自动化运维很难实施。

Linux集群方面涉及的内容比较多,具体分为高可用性集群(运行于两个或多个节点上,目的是在系统出现某些故障的情况下,仍能继续对外提供相应的服务)、负载均衡集群(提供和节点个数成正比的负载能力,这种集群很适合提供大访问量的Web服务,往往具有一定的高可用性特点)、超级计算集群(海量数据的计算)三大类。其中包含的内容很多,有兴趣的朋友可以查看我写的网站架构技术方面的书。

常用的技术如负载均衡器LVS、HAProxy、Oracle集群数据库RAC、MySQL+DRBD集群等。了解并掌握软件之间的结合使用,就可以在架构设计时得心应手。

抚琴煮酒:

你现在最关注哪方面的技术?你自己是如何学习并掌握新技术的?

Gray1982:

在脚本方面主要研究 Python。各种编程语言是否顺手是个人的习惯,没有哪种语言是绝对不好的。看书的时候结合几本书一起看,可以综合学习该语言的知识,以免知识不全或错误。另外多写、多练,写得多了就明白得多了,就可以很简洁地写出整个程序。实现同一个功能,用60行代码实现和用200行代码实现,程序员的功力悬殊可见。

除了对Python的学习,我对云计算Hadoop也很感兴趣。除了基本配置,其原理、优化是我研究的方向。开始如果没有环境的话,可以自己用VMware搭建,只要能连网,安装根本不是问题。而且,由于VMware配置的虚拟Linux性能不如真实的服务器,所以在调整的时候会有更多的收获。

学自己感兴趣的内容,有计划地学,长久地学,效率会高一些。学习脚本就要多写写,多看看,多问问,就可以更好的掌握。

抚琴煮酒:

当前网站大概的架构,以及用到的技术有哪些?

Gray1982:

目前应用涉及的技术比较多,我只说一个项目吧。根据业务来做的网站页面级缓存架构可以是lvs-haproxy-nginx(varnish)-app的形式。LVS不多说了,大家都知道。中间之所以多了个HAProxy,一来因为整个架构更好管理(机器比较多,一个网段的IP已经不能满足其扩展需求),二来可以更好地按规则分发请求。至于是用专业级的缓存还是用轻量级的缓存要看公司的实际情况。有的可能需要对开源软件进行二次开发才可以得到公司需要的东西,有的可能考虑以后的扩展以及运营成本等。了解得更多才会掌控得更多。

抚琴煮酒:

对目前热门的CDN技术有什么心得和经验与大家分享?

Gray1982:

在CDN方面暂时没什么研究,相对来说对其架构方面了解的也不多,就不在这里献丑了。

技术方面只是对 Squid、Varnish 缓存有部分了解,但仅限于电商级的。企业中会遇到的问题多为CDN取源时的速度问题,CDN取源时有可能占有90%以上的企业带宽。这点需要CDN 厂商注意,最好添加限制速度方面的设置。如果企业文件无需经常更新,可以让 CDN厂商把取源时间调整为半年或者更久,如果有更新但为数不多的情况下建议手动刷新。

抚琴煮酒:

听说您Python玩得不错,您在平时的工作中具体使用Python来实现哪些工作,能有些具体的实用脚本跟大家分享吗?

Gray1982:

考虑到效率以及方便性,自己曾用Python写过一个多线程的批量部署程序。一般公司做批量部署管理都会用 Puppet,不过这些都需要安装服务器端和客户端,并且是单线程的。管理少量服务器也许看不出什么,管理到百台以上的机器,效率会明显下降。我自己写的这个多线程的程序(有兴趣的朋友可以到我的博客下载)暂时还没测试百台以上的运行情况,不需要安装客户端,完全以推送的形式,所以比较方便、快捷。可以是批量管理的必备工具。因为没有测试到多台服务器的情况,所以有问题也希望大家提出来,一起研究,共同起步。

另外一个是根据业务来监控网站的实用性工具,可以监控网络是否连通、访问的网页是否出现 400 以上的错误以及网页的内容是否正常,如果不正常,可以通过邮件报警。有兴趣的朋友也可以一起讨论。

前言

我的系统运维观

我做系统运维工作也好几年了,基本上应付过各种各样的运维环境和工具。从最开始简单的各种应用部署,比如常用的LVS、HAproxy这样的负载应用、Apache、Nginx这类的Web应用,到MySQL数据库的主从结构的部署,以及云计算Hadoop、各种监控(Cacti、Zabbix)、缓存(Squid、Varnish、Nginx、Memcached、Redis)等,无不有所涉足。

此后,更多的工作是根据实际的情况来设计架构。这不仅可以让系统稳定、高性能地运行,还需要在未来的扩展中不影响整个的业务的运行。整体架构的清晰对企业的发展是很重要的,如果上层企业领导不重视或者是外行人领导内行人的话,企业的人力成本、硬件成本等会有更多的消耗。

随着企业的发展、软硬件的增加,有一个健壮的自动化运维平台也是增加效率、减少人力成本,也是很好的方法。可惜很多企业不重视运维,认为只要有个人随便能应付就行,等企业发展起来想做调整也不行了,反而浪费了更多的人力物力。

想做好运维师这个职位,不仅要有相应的技术,还需要在一个具备发展眼光的技术团队和公司。否则只能是混日子,而这不论对公司还是个人都不是一个好的发展。

系统运维师这个职业,就是这样,不断面临新的问题和挑战,也需要不断学习新的知识和概念。不过一路走来,我感觉所有的付出都有所回报,还是值得的。

写作本书的目的

我工作有七八年时间了,期间也做过技术培训中心的讲师。在教学过程中,我发现很多学生在进入企业后有些是无法胜任工作的,这里不排除一些因为上课不好好听讲、课后不认真练习的学生;另一方面也有可能企业的线上环境比较复杂,再加上自己也没什么职业目标不明确干什么,不重视基础知识积累,实践经验少,根本不会计算流量、软件选型等。所以,我有了写这本书的想法,结合我个人在网站架构上的技术经验和培训时的教学思路,可以帮助初中级读者进行技术方面的一次系统的学习(包括负载、页面级缓存、NoSQL、分布式文件系统、监控)。由浅入深地介绍这些内容,也可以让初中级读者在网站架构上有一个清晰的认识,在多种应用软件中选择适合企业的来完善企业的网站架构。

本书中所提到的系统均为CentOS 5.6,所讲的应用,所提供的脚本均来自于线上生产环境,大家可以直接使用。

希望大家通过学习本书,能够掌握网站架构各种技术的应用,以及在一定程度上可以设置实用的网站架构,使自己的职业技能有一个质的提高。这是我期望看到的,也是我写这本书的目的。

读者对象

本书的读者对象如下:

网站运维工程师

系统管理员和系统工程师

网络管理员和企业网管

计算机相关专业的学生

如何阅读本书

本书的结构是按一般网站的架构需求顺序来编写的。全书共分为7篇16章。

第一篇是架构规划篇,也就是第1章,主要介绍了对企业网站架构的选型、系统的快速安装及初始化高性能系统的一些参数。

第二篇为负载应用篇,包括第2章到第4章。第2章介绍了LVS+KeepAlived,这是可以媲美硬件负载的开源软件。第3章则简单地介绍了Haproxy,它是提供高可用性、负载均衡以及基于TCP和HTTP应用的代理。第4章介绍的是Nginx的负载功能,它可以按照多种方式对后端的应用服务器做负载均衡。这些内容都是网站前端必然用到的知识,建议大家多花些精力和时间学习。

第三篇为页面缓存篇,包括第5章、第6章和第7章。第5章介绍了老牌的代理服务器和Web缓存服务器软件Squid。第6章介绍相对更为高性能的缓存软件Varnish。第7章介绍了应用在流量不大环境中Nginx的缓存功能。

第四篇为Web服务器篇,包括第8章和第9章两章。第8章介绍了几乎可以在任何平台上运行、世界使用排名第一的Web服务器软件Apache。第9章介绍了一款轻量级软件Nginx,其并发能力在同类型的Web服务器中表现较好,此外,还简单介绍了Lighttpd的安装和配置。

第五篇是数据缓存篇(NoSQL),包括第10章、第11章和第12章。第10章首先对NoSQL的概念进行简单介绍,然后,介绍了Memcache的机理、安装和使用。第11章则介绍了拥有更多的Value类型、持久化和主从功能的Redis。第12章介绍了基于分布式文件存储的数据库MongoDB。

第六篇为文件服务篇,包括第13章和第14章。第13章介绍了一个具备容错功能的网络分布式文件系统MFS,它可以将数据分布在网络中不同服务器上。第14章介绍了Hadoop,它不仅仅是一个用于存储的分布式文件系统,而且可以用来在通用计算设备组成的大型集群上执行分布式应用框架。

第七篇监控应用篇,也是最后一篇,包括第15章和第16章。第15章介绍了各大IDC都在使用监控流量的Cacti。第16章介绍了Zabbix,这是一款基于Web界面的提供分布式系统监视以及网络监视功能的软件。

附录部分分别给出了ipvsadm命令参考、HAProxy关键字列表、Squid客户端命令行参考等常用的信息。

大家可以根据自己的需求选择阅读侧重点,不过我还是希望你能够按照顺序来阅读,这样不仅仅可以对架构上有一个清晰的认识,还可以对架构中的技术有一个简单的对比。

本书体例说明

本书编写体例有以下几点提醒读者注意。

命令行

需要输入的命令行,用加粗的等宽字体表示。如下所示:

/usr/local/sbin/keepalived -D -f /usr/local/etc/keepalived/keepalived.conf

配置文件

一般的配置文件,使用常规等宽字体表示。如下所示:

! Configuration File for keepalived

global_defs {

notification_email {

admin@example.com

}

配置文件说明或注释

文件的说明或注释,用#符号开头,并用仿宋字体表示。如下所示:

#让进程在后台运行,即作为守护进程运行,正式运行的时候开启,此处先禁止,等同于在命令行添加参数“-D”

注意和提示

注意和提示,是需要提醒读者特别注意的内容。其标题用黑体,内容用楷体表示。如下所示:

提示

系统默认状态没有HAProxy用户和组,需要自行添加。

致谢

感谢我的妹妹,在我最初刚来北京时给我的诸多照顾,让我能很快地熟悉北京的环境。

感谢在我上学时对学生非常负责的英语老师孙老师,她的教诲使我以后学习和使用英语很是便利。

感谢一起工作过的唐华、王锴、祝传雷、左辉、魏学丰、王涛,不论是在工作方面还是技术方面都给了我很大的帮助,让我少走了不少弯路。

感谢Chinaunix的编辑们,特别是天晴、send_linux、小尾巴鱼,正是有了你们对我的帮助,本书才有机会为广大的读者知晓。

感谢QQ群中Linux/UNIX系统运维群、Linux饭醉团伙、系统运维专业群的很多朋友,和群里的朋友一起研究学习,一起聊天解闷,非常开心,也谢谢你们对我的支持以及对这本书的期待。特别感谢好友pcghost,他在Nginx环境中很有研究,对本书Nginx章节中的内容给予很好的建议和很大的帮助。

感谢本书编辑对我的各种指导,使我的写作水平有了很大的提高。

感谢在工作和生活中帮助过我的所有人,感谢你们,正是因为有了你们,才有了本书的面世。

关于勘误

虽然花了很多时间和精力去核对书中的文字、代码和图片,但因为时间仓促和水平有限,书中仍难免会有一些错误和纰漏,如果大家发现什么问题,恳请反馈给我,相关信息可发到我的邮箱danshenguizu1982@163.com。我肯定会努力回答疑问或者指出一个正确的方向。

如果大家对本书有任何疑问或想与我探讨Linux相关的技术,可以访问我的个人博客,地址为:liuxin1982.blog.chinaunix.net。另外,我在ChinaUnix社区的ID为Gray1982,大家也可以直接通过此ID在社区中与我在线交流。

第一篇 架构规划篇

第1章 网站架构简介

第1章 网站架构简介

在目前这样一个高速的信息时代,我们更希望在最短的时间内以最简单的方式获取自己需要的内容。因此,我们需要一个高性能、高可用性的网站架构来支撑网站大量的访问。所以,网站的架构在网站运营当中所占的分量是相当之重的,那么如何构建稳定而又可平滑扩展的网站结构呢?我们先来了解什么是网站架构。

网站架构通过对用户需求进行分析、了解并定位网站的目标用户,从而对网站整体架构进行规划、设计,以最大限度地进行高效资源分配与管理的设计。网站架构粗略分为硬架构和软架构。

1.1 网站的硬架构

1.1.1 机房的选择

在选择机房的时候,根据用户的地域分布,可以选择双线或多线机房,但更多时候,可能多线机房才是最合适的。越大的城市,机房价格越贵,从成本的角度看可以在一些中小城市托管服务器,比如说北京的公司可以考虑把服务器托管在天津、廊坊等地,不是特别远,但是价格会便宜很多。

1.1.2 带宽的大小

通常我们在架构网站的时候,会设定一些目标,比如网站每天要能承受千万 PV 的访问量,这时我们要估算一下大概需要多大的带宽。计算带宽大小主要有两个指标(峰值流量和页面大小),我们先做出必要的假设:

1.峰值流量是平均流量的3倍;

2.每次访问平均的页面大小是100kB左右。

如果1000万PV的访问量在一天内平均分布,每秒大约120次访问,如果按平均每次访问页面的大小是100kB字节计算,120次访问总计大约就是12000kB。字节的单位是Byte,而带宽的单位是bit,它们之间的关系是1Byte = 8bit,所以12000k Byte大致就相当于96000k bit,也就是90Mbps的样子。实际上,我们的网站必须能在峰值流量时保持正常运行状态,所以按照假设的峰值流量计算,真实带宽的需求应该在270Mbps左右。

当然,这个结论是根据前面提到的两点假设得出的,具体值则需要根据公司实际情况来计算。

1.1.3 服务器的划分

一般情况下网站需要的服务器包括图片服务器、页面服务器、数据库服务器、应用服务器、日志服务器等。

对于访问量大的网站,图片服务器和页面服务器的分离是相当必要的。我们可以在图片服务器上运行Lighttpd,在页面服务器上运行Ngnix,当然也可以选择别的。我们也可以扩展成多台图片服务器和多台页面服务器同时运行,并设置相关域名,如imgs.domain.com和www.domain.com,页面里的图片路径都使用绝对路径,如<img src="http://imgs.domain.com/xxx.gif"/>,然后配置 DNS 轮循,达到最初级的负载均衡。服务器多了就不可避免地涉及同步的问题,这时可以使用Rsync软件来完成。

数据库服务器是重中之重,因为网站的瓶颈问题大多出在数据库身上。现在一般的中小网站多使用MySQL数据库。一般而言,使用MySQL数据库的时候,我们应该配置为一个主从(一主多从)结构,主数据库服务器使用InnoDB 表结构,从数据服务器使用MyiSAM表结构。这样充分发挥它们各自的优势,而且这样的主从结构分离了读写操作,降低了读操作的压力。我们还可以设定一个专门的从服务器作为备份服务器,有时候还需要借助Memcached之类的第三方软件,以便适应更大访问量的要求。MySQL在后面的章节有具体介绍。

如果有条件,可以应用独立的日志服务器。一般网站的做法是把页面服务器和日志服务器合二为一,在凌晨访问量不大的时候计划任务运行前一天的日志计算。不过对于百万级访问量而言,即使按天归档,也会消耗很多时间和服务器资源来计算。所以分离单独的日志服务器还是有好处的,这样不会影响正式服务器的工作状态。

1.2 网站的软架构

1.2.1 框架的选择

现在的框架有很多选择,比如PHP 的Symfony、Zend Framework等,至于应该使用哪种并没有唯一的答案,这要根据业务以及团队成员对各个框架的了解程度而定。很多时候,即使没有使用框架,仍然可以写出好的程序来,据说Flickr就是用Pear和Smarty这样的类库写出来的。所以,是否使用框架,使用什么样的框架,这都不是最重要的,重要的是我们的编程思想里要有框架的意识。

1.2.2 逻辑的分层

网站达到一定的规模之后,前期代码逻辑设计里的不足便会给维护和扩展带来巨大的障碍,但我们的解决方式其实很简单,那就是重构,将逻辑进行分层。通常,自上而下可以分为表现层、应用层、领域层和持久层。

表现层

表现层的表现形式不应该仅仅是模板,它的范围还可以更广一些,所有和表现有关的逻辑都应该纳入表现层的范畴。比如说某处的字体要显示为蓝色、某处的开头要有空格,这些都属于表现层应解决的问题。通常,我们容易犯的错误就是把本属于表现层的逻辑放到了其他层去完成。举一个比较常见的例子:通常在列表页显示文章标题的时候,都会设定标题允许的最多字数,一旦标题长度超过了这个限制,就会被截断,并在后面显示“...”,这就是最典型的表现层逻辑。但实际上,有很多程序员都是在非表现层代码中完成数据的获取和截断,然后赋值给表现层模板。这样的代码最明显的缺点就是,同一段数据,在一个页面可能要显示前5个字,在另一个页面可能要显示前10个字,而一旦在程序中固化了这个数值,这就丧失了灵活性。正确的做法是用视图程序来专门处理此类逻辑。

应用层

应用层的主要作用是定义用户可以做什么,并把操作结果返回给表现层。至于如何做,这就不属于其职责范围(而是领域层的职责范围),应用层会通过委派把工作实现的具体方法交给领域层处理。

领域层

最直接的解释就是包含领域逻辑的层,是一个软件的灵魂所在。首先,我们来看看什么叫领域逻辑。简单来说,具有明确的领域概念的逻辑就是领域逻辑,比如在 ATM 机上取钱,过程大致是这样的:插入银行卡——输入密码——输入取款金额——确定——拿钱——打印凭证——ATM吐出一张交易凭条。银行卡在ATM机中完成钱从账户划拨的过程就是一个领域逻辑,因为取钱在银行中是一个明确的领域概念,而ATM机吐出一张交易凭条的过程则不是领域逻辑,而仅是一个应用逻辑,因为吐出交易凭条并不是银行中一个明确的领域概念,只是一种技术手段。对应的,我们取钱后不要求打印交易凭条,而只要求发送一条提醒短信也是可能的。如果要求取款后必须吐出交易凭条,则吐出交易凭条的过程已经和取款过程紧密结合,那么就可以把吐出交易凭条的过程看作是领域逻辑的一部分,一切都以问题的具体情况而定。

持久层

持久层用于把领域模型保存到数据库中。因为程序代码是面向对象风格的,而数据库一般是关系型的数据库,所以需要把领域模型碾平,才能保存到数据库中。可以使用的方法有行数据入口(Row Data Gateway)或者表数据入口(Table Data Gateway),或者把领域层和持久层合二为一变成活动记录(Active Record)的方式。

1.3 网站架构需要考虑的几个问题

1.3.1 HTML静态化

众所周知,效率最高、消耗最小的就是纯静态化的HTML页面,所以我们尽可能使网站架构上的页面采用静态页面来实现,最简单的方法往往也是最有效的。但是对于内容大量并且频繁更新的网站,我们无法全部手动去逐一实现,于是出现了常见的信息发布系统(CMS),像各个门户站点的新闻频道等,都是通过信息发布系统来管理和实现的。信息发布系统可以实现最简单的信息录入并自动生成静态页面,还具备频道管理、权限管理、自动抓取等功能。对于一个大型网站来说,一套高效、可管理的CMS是必不可少的。

除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能地静态化也是提高性能的必要手段。将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化都是大量使用的策略,像MOP的大杂烩、网易社区等就是如此。

同时,HTML 静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但内容更新很小的应用,可以考虑使用HTML静态化来实现,比如论坛的公用设置信息。目前,主流论坛都可以对这些信息进行后台管理并将其存储在数据库中,这些信息其实大量被前台程序调用,但是更新频率很小。可以考虑将这部分内容在后台更新时进行静态化,这样就避免了大量的数据库访问请求。

1.3.2 图片服务器分离

对于Web服务器来说,不管是Apache、IIS还是其他Web服务器,图片是最消耗资源的,所以有必要将图片与页面进行分离,这是大型网站都会采用的策略,他们都有独立的一台或图片服务器。这样的架构可以降低提供页面访问请求的服务器系统的压力,并且可以保证系统不会因为图片问题而崩溃。在应用服务器和图片服务器上,可以进行不同的优化配置,比如Apache在配置ContentType的时候可以只支持必要的类型,配置LoadModule的时候只加载必要的模块,保证更高的系统消耗和执行效率。

1.3.3 数据库集群和库表散列

大型网站都有很多复杂的应用程序,这些应用程序必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就显现出来,这时一台数据库无法满足应用要求,所以需要使用数据库集群或者库表散列。在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL数据库提供的Master/Slave也是类似的方案,业务上使用了什么样的DB,就参考使用相应的解决方案。

由于数据库集群在架构、成本、扩张性方面都受到所采用DB类型的限制,于是需要从应用程序的角度来考虑改善系统架构。库表散列是常用并且最有效的解决方案。在应用程序中,安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如按照用户ID进行对用户表散列,这样不仅能够低成本地提升系统的性能而且使系统具有很好的扩展性。一些大型论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行数据库和表散列,最终只需在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。

1.3.4 缓存

相信程序开发人员都了解,很多地方要用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存,高级和分布式的缓存将在后面进行讲述。

架构方面的缓存:对 Apache 比较熟悉的人都知道,Apache 拥有自己的缓存模块,也可以使用外加的Squid进行缓存,这两种方式均可以有效提高Apache对访问的响应能力。

网站程序开发方面的缓存:Linux上提供的MemoryCache是常用的缓存接口,可以在Web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通信共享,一些大型社区便使用了这样的架构。另外,在进行WEB开发的时候,各种语言基本都有自己的缓存模块和方法,如PHP有Pear的Cache模块。

1.3.5 镜像

镜像是大型网站常采用的提高性能和数据安全性的方式。镜像技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异促使很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的、现成的解决架构和产品可供选择,也有廉价的通过软件实现的方案,比如Rsync等工具。

1.3.6 负载均衡

负载均衡是大型网站解决高负载和大量并发请求而采用的终极解决办法。

四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。

四层交换功能就像是虚拟 IP,指向物理服务器。其传输业务服从多种协议,有 HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。

使用负载均衡的一个典型策略是,在软件或者硬件四层交换的基础上搭建缓存集群。这种思路被很多大型网站(包括搜索引擎)所采用。这样的架构成本低、性能高还有很强的扩展性,可随时向架构中增减节点,操作非常容易。这样的架构技术我们后面再行讲解。

1.4 操作系统的选择及参数优化

1.4.1 用U盘自动安装操作系统

目前市面上有很多种类的Linux,下面来介绍几种常见的Linux操作系统。

Ubuntu:最流行的Debian 的衍生版软件,非常简单而全面;

Fedora:Redhat 的免费桌面版;

Red Hat Enterprise Linux ASX:Redhat 服务器版;

Mandriva:其前身为Mandrake,号称最易用的Linux;

OpenSUSE:由Novell 发起的Linux,很不错;

Gentoo:大牛们玩的编译安装Linux;

CentOS(Community Enterprise Operating System):来自于Red Hat Enterprise的Linux,依照开放源代码规定释出的源代码所编译而成。它也是企业中最常用的一种。由于出自同样的源代码,因此有些要求高度稳定性的服务器使用 CentOS 替代商业版的 Red Hat Enterprise Linux。两者的不同,在于CentOS并不包含封闭源代码软件。

系统的光盘安装这里不再多说,可以去我的博客里下载相关的视频,这些视频是我以前教学用的课件。下面讲解U盘无人值守安装Linux操作系统的方法。公司新购置十几台机器放到办公区,总不能一台一台地用光盘安装系统,虽然说可以配置批量安装服务器来远程安装(放到IDC机房),但需要购买管理控制卡,为了节省成本,个人感觉还是U盘安装比较方便。一台标配的DELL R710一般12 分钟就可以装好Linux 系统(视安装包多少决定),然后配置IP和主机等基本配置,其他配置可回公司操作。注意,U盘的数量决定总体安装的时间。

U盘无人值守安装需要一个4GB的U盘(根据操作系统ISO的大小来定),另外需要两台服务器:一台做服务器端用来创建分区、复制文件;一台做测试机用来测试U盘安装。还有一台Windows操作系统用来引导写入MBR。

U盘无人值守安装Linux操作系统操作步骤如下。

1.创建ISO挂载点

[root@utest srv]# mkdir -p /mnt/iso/

2.挂载操作系统的ISO

[root@utest srv]# mount -o loop RHEL4.8-x86_64-AS-DVD.iso /mnt/iso/

3.给U盘分区(本环境被识别为/dev/sdb)

[root@utest srv]# fdisk /dev/sdb

如果U盘被系统认做sdb,如图1-1所示。按【n】键来创建新的分区,如图1-2所示。

图1-1
图1-2

首先创建一个分区(格式化成DOS分区)用来存放启动文件,这里为其分配大于100MB的空间即可,如图1-3所示。

图1-3

然后剩下的空间全部分配给/dev/sdb2,用于存放ISO文件,如图1-4所示。

图1-4

按【p】键查看分区结果,如图1-5所示。

按【w】键保存并退出,如图1-6所示。

图1-5
图1-6

4.创建两个挂载U盘的挂载点

[root@utest srv]# mkdir -p mnt/usb1

[root@utest srv]# mkdir -p mnt/usb2

5.格式化第一个分区成DOS分区

[root@utest srv]# mkfs.msdos /dev/sdb1

6.格式化第二个分区为ext2分区(syslinux暂不支持ext3文件系统)

[root@utest srv]# mkfs.ext2 /dev/sdb2

7.分别挂载

[root@utest srv]# mount /dev/sdb1 /mnt/usb1

[root@utest srv]# mount /dev/sdb2 /mnt/usb2

8.查看本地分区情况,如图1-7所示

图1-7

[root@utest srv]# df –lh

9.移动isolinux目录到DOS分区并且重命名

[root@utest srv]# cp -a /mnt/iso/isolinux/ /mnt/usb1/syslinux

10.复制自动安装读取的文件到DOS分区

[root@utest srv]# cp -a /root/anaconda-ks.cfg /mnt/usb1

11.复制系统ISO文件

[root@utest srv]# cp -a RHEL4.8-x86_64-AS-DVD.iso /mnt/usb2

12.进入DOS分区重命名文件并且编辑

[root@utest srv]# cd /mnt/usb1/syslinux/

[root@utest syslinux]# mv isolinux.cfg syslinux.cfg

[root@utest syslinux]# chmod +w syslinux.cfg(原本为只读文件)

[root@utest syslinux]# vi syslinux.cfg

修改文件的配置,原配置如图1-8所示。修改为如图1-9所示。

图1-8
图1-9

13.修改自动启动的配置文件

[root@utest syslinux]# cd /mnt/usb1

[root@utest usb1]# vi anaconda-ks.cfg

# Kickstart file automatically generated by anaconda.

install

harddrive --partition=sdb2 --dir=

lang en_US.UTF-8

keyboard us

text

network --device eth0 --bootproto static --ip 192.168.14.11 --netmask255.255.255.0 --gateway 50.11.11.19 --nameserver 22.16.0.20

rootpw aaaaaa

firewall --enabled --port=22:tcp

authconfig --enableshadow --enablemd5

selinux --disabled

timezone Asia/Shanghai

bootloader --location=mbr --driveorder=sda --append="rhgb quiet"

# The following is the partition information you requested

# Note that any partitions you deleted are not expressed

# here so unless you clear all partitions first, this is

# not guaranteed to work

clearpart --all --drives=sda

part / --fstype ext3 --size=50000 --ondisk=sda

part swap --size=4096 --ondisk=sda

%packages

@admin-tools

@base

@core

@development-libs

@development-tools

@editors

@graphical-internet

@legacy-network-server

@legacy-software-development

@legacy-software-support

@network-server

@server-cfg

@system-tools

@base-x

keyutils

kexec-tools

iscsi-initiator-utils

trousers

fipscheck

device-mapper-multipath

perl-Convert-ASN1

imake

以上软件包的数量如果认为比较少,还可以自行添加其他软件包。

syslinux.cfg完整内容

default ks

prompt 1

timeout 10

display boot.msg

F1 boot.msg

F2 options.msg

F3 general.msg

F4 param.msg

F5 rescue.msg

label linux

kernel vmlinuz

append initrd=initrd.img

label text

kernel vmlinuz

append initrd=initrd.img text

label ks

kernel vmlinuz

append ks=hd:sdb1:/hdd.cfg initrd=initrd.img text

label local

localboot 1

label memtest86

kernel memtest

append -

在Windows系统的操作如下。

1.从Linux服务器上把U盘拔出并插在Windows上,这里识别为I盘,如图1-10所示。

2.复制syslinux.exe到系统目录,最后路径如图1-11所示。

图1-10
图1-11

3.在DOS环境下执行命令,把系统引导写入U盘的MBR,如图1-12所示

图1-12

将测试机设置为从U盘启动,启动后如果没错误则系统自动安装,如果弹出红帽子的安装界面然后在boot后输入ks,然后按【Enter】键即可完成系统安装。

1.4.2 系统初始化

系统安装完成后,需要根据不同的应用配置不同的参数。下面首先对 sysctl.conf 文件进行配置。该文件可以实现对千万级PV负载的支持,当然根据环境的不同,参数也不同。

# Kernel sysctl configuration file for Red Hat Linux

#

# For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and

# sysctl.conf(5) for more details.

# Controls IP packet forwarding

net.ipv4.ip_forward = 1

# Controls source route verification

net.ipv4.conf.default.rp_filter = 1

# Do not accept source routing

net.ipv4.conf.default.accept_source_route = 0

# Controls the System Request debugging functionality of the kernel

kernel.sysrq = 0

# Controls whether core dumps will append the PID to the core filename

# Useful for debugging multi-threaded applications

kernel.core_uses_pid = 1

# Controls the use of TCP syncookies

net.ipv4.tcp_syncookies = 1

# Controls the maximum size of a message, in bytes

kernel.msgmnb = 65536

# Controls the default maxmimum size of a mesage queue

kernel.msgmax = 65536

# Controls the maximum shared segment size, in bytes

kernel.shmmax = 68719476736

# Controls the maximum number of shared memory segments, in pages

kernel.shmall = 4294967296

# Reboot a minute after an Oops

kernel.panic = 60

# Syncookies make SYN flood attacks ineffective

net.ipv4.tcp_syncookies = 1

# Ignore bad ICMP

net.ipv4.icmp_echo_ignore_broadcasts = 1

net.ipv4.icmp_ignore_bogus_error_responses = 1

# Disable ICMP Redirect Acceptance

net.ipv4.conf.all.accept_redirects = 0

# Enable IP spoofing protection, turn on source route verification

net.ipv4.conf.all.rp_filter = 1

# Log Spoofed Packets, Source Routed Packets, Redirect Packets

net.ipv4.conf.all.log_martians = 1

# Reply to ARPs only from correct interface (required for DSR load-balancers)

net.ipv4.conf.all.arp_announce = 2

net.ipv4.conf.all.arp_ignore = 1

fs.file-max = 1024000

net.ipv4.tcp_max_syn_backlog = 65536

net.core.netdev_max_backlog = 32768

net.core.somaxconn = 32768

net.core.wmem_default = 8388608

net.core.rmem_default = 8388608

net.core.rmem_max = 16777216

net.core.wmem_max = 16777216

net.ipv4.tcp_timestamps = 0

net.ipv4.tcp_synack_retries = 2

net.ipv4.tcp_syn_retries = 2

net.ipv4.tcp_tw_recycle = 1

#net.ipv4.tcp_tw_len = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_mem = 94500000 915000000 927000000

net.ipv4.tcp_max_orphans = 3276800

#net.ipv4.tcp_fin_timeout = 30

#net.ipv4.tcp_keepalive_time = 120

net.ipv4.ip_local_port_range = 1024 65535

# Increase max conntrack table

net.ipv4.ip_conntrack_max = 1310720000

# Reduce time_wait period to 10s (60s default)

net.ipv4.tcp_fin_timeout = 1

net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 0

# Re-use Time_Wait socket when safe -- help reduce the amount of TW socket

vm.swappiness = 2

net.ipv4.tcp_tw_reuse = 1

# Controls source route verification

net.ipv4.conf.default.rp_filter = 0

# Enable IP spoofing protection, turn on source route verification

net.ipv4.conf.all.rp_filter = 0

net.ipv4.ip_nonlocal_bind = 1

# 优化硬盘

cp /etc/fstab /etc/fstab.'date +"%Y-%m-%d_%H-%M-%S"'

# 关闭系统,写入文件最后读取时间

sed -i 's/ext3 defaults/ext3 defaults,noatime/' /etc/fstab

# 关闭系统,按时间间隔决定下次重启时运行fsck

grep ext3 /etc/fstab | grep -v boot | awk '{print $1}' | xargs -i tune2fs -i0 {}

# 关闭系统,按mount次数决定下次重启时运行fsck

# grep ext3 /etc/fstab | grep -v boot | awk '{print $1}'|xargs -i tune2fs -c-1 {}

# 安装工具软件sysstat, ntp, net-snmpd, sudo

yum install sysstat ntp net-snmp sudo screen –y

# Linux大多远程维护pts连接,可以关闭多余的tty,保留一个用于物理登录

cp /etc/inittab /etc/inittab.'date +"%Y-%m-%d_%H-%M-%S"'

sed -i '/tty[2-6]/s/^/#/' /etc/inittab

# 关闭不必要的服务

SERVICE='which service'

CHKCONFIG='which chkconfig'

SERVICES="acpid atd auditd avahi-daemon bluetooth cpuspeed cups firstboot hidd

ip6tables isdn mcstrans messagebus pcscd rawdevices sendmail yum-updatesd"

for service in $SERVICES

do

${CHKCONFIG} $service off

${SERVICE} $service stop

Done

#Iptables的默认配置,需要根据实际情况添加

*filter

:LOGDROP_ILLEGAL_PACKET - [0:0]

-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j

LOGDROP_ILLEGAL_PACKET

-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,

PSH,ACK,URG -j LOGDROP_ILLEGAL_PACKET

-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j LOGDROP

ILLEGAL_PACKET

-A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j LOGDROP_ILLEGAL_PACKET

-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j LOGDROP_ILLEGAL_PACKET

-A INPUT -p tcp -m tcp --tcp-flags FIN,ACK FIN -j LOGDROP_ILLEGAL_PACKET

-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK,

URG -j LOGDROP_ILLEGAL_PACKET

-A LOGDROP_ILLEGAL_PACKET -m limit --limit 2/sec -j LOG --log-prefix

"IPTFW-bad-flag " --log-level 7

#-A INPUT -s 192.168.0.0/255.255.0.0 -i eth0 -j LOGDROP_ILLEGAL_PACKET

-A INPUT -s 172.16.0.0/255.240.0.0 -i eth0 -j LOGDROP_ILLEGAL_PACKET

-A INPUT -s 172.16.0.0/255.240.0.0 -i eth1 -j LOGDROP_ILLEGAL_PACKET

-A INPUT -s 10.0.0.0/255.0.0.0 -i eth1 -j LOGDROP_ILLEGAL_PACKET

-A INPUT -s 169.254.0.0/255.255.0.0 -j LOGDROP_ILLEGAL_PACKET

-A LOGDROP_ILLEGAL_PACKET -j DROP

:FORWARD ACCEPT [0:0]

:INPUT DROP [0:0]

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p vrrp -j ACCEPT

-A INPUT -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT

-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT

-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT

-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 5/sec -j ACCEPT

-A INPUT -p icmp -m icmp --icmp-type 0 -m limit --limit 5/sec -j ACCEPT

-A INPUT -p icmp -m icmp --icmp-type 11 -m limit --limit 5/sec -j ACCEPT

-A INPUT -p icmp -m icmp --icmp-type 3 -m limit --limit 5/sec -j ACCEPT

-A INPUT -p icmp -j DROP

-A INPUT -i eth0 -j REJECT --reject-with icmp-host-prohibited

:OUTPUT DROP [0:0]

-A OUTPUT -p vrrp -j ACCEPT

-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A OUTPUT -o lo -j ACCEPT

-A OUTPUT -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT

-A OUTPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

-A OUTPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT

-A OUTPUT -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT

-A OUTPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT

-A OUTPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 5/sec -j ACCEPT

-A OUTPUT -p icmp -m icmp --icmp-type 0 -m limit --limit 5/sec -j ACCEPT

-A OUTPUT -p icmp -m icmp --icmp-type 11 -m limit --limit 5/sec -j ACCEPT

-A OUTPUT -p icmp -m icmp --icmp-type 3 -m limit --limit 5/sec -j ACCEPT

-A OUTPUT -p icmp -j DROP

COMMIT

以上是笔者在工作中的一些经验和心得,与大家分享,希望能给大家一定的帮助。一套成熟的方案、一个安全稳定的网站或者系统,是长时间的积累和实践得出来的,因此,读者还需要不断地实践和总结。

1.5 小结

本章简单介绍了网站的架构和选择依据,并且对系统包的定制、U盘安装、系统初始化做了全方位的介绍,这是对系统底层的强有力的建设,希望大家掌握本章内容。尤其是系统部署部分的内容,这些对于以后的工作有很大的帮助。理解了本章的内容,我们的工作会更得心应手。

第二篇 负载应用篇

第2章 LVS+KeepAlived实现高可用集群

第3章 高性能负载均衡器HAProxy

第4章 轻量级的负载Nginx

第2章 LVS+KeepAlived实现高可用集群

在设计网站架构的时候,其稳定性、可靠性以及可扩展性是首要考虑的问题。从网站架构的前端负载入手是设计高可用网站的开始。目前,有多种不同的软硬件为我们提供负载功能,下面就对其主流的软件一一介绍,以便选择一种最为适合企业运营的配置。

2.1 软硬负载应用介绍

随着电脑网络的高速发展,网络间通信不断增多,服务器的工作负载日益增加,所以需要利用负载均衡技术保证服务器的正常工作。根据负载均衡的原理,利用其功能构建的负载均衡系统,即可提供可靠和稳定的服务,这是其方便、灵活,有实际使用价值的体现。

负载均衡设备可以根据实际的响应时间制定优先级交付决策,从而实现高性能、智能化管理,达到最佳的服务器集群标准。

2.1.1 Linux集群简介

目前,越来越多的网站采用Linux操作系统提供邮件、Web、文件缓存、数据库等服务。也有很多的公司在企业内部网中利用 Linux 服务器提供这些服务。随着对 Linux 服务器依赖的加深,人们对其可靠性、负载能力和计算能力也倍加关注。所以,Linux集群技术应运而生,它可以以低廉的成本,很好地满足人们的这些需要。

Linux拥有强大竞争力的原因之一是,它可以运行在极为普及的计算机上,不需要购买昂贵的专用硬件设备。几台装有 Linux 系统的计算机,只要加入相应的集群软件,就可以组成具有极强可靠性、负载能力和计算能力的Linux集群。集群中的每台服务器称为一个节点。

按照侧重点的不同,可以把Linux集群分为三类。

第一类是高可用性集群,运行于两个或多个节点上,目的是在某节点系统出现故障的情况下,仍能继续对外提供相应的服务。高可用性集群的设计目的就是最大限度地减少服务中断时间。这类集群中比较著名的有Turbolinux、TurboHA、Heartbeat、Kimberlite等。

第二类是负载均衡集群,目的是提供和节点个数成正比的负载能力,这种集群很适合提供大访问量的Web服务。负载均衡集群往往也同时具有一定的高可用性特点。TurboLinux Cluster Server、Linux Virtual Server都属于负载均衡集群。

第三类是超级计算集群,按照计算关联程度的不同,又可以分为两种。

一种是任务片方式,把计算任务分成任务片,再把任务片分配给各节点,在各节点上分别计算后再把结果汇总,生成最终计算结果。

另一种是并行计算方式,在计算过程中节点之间大量地交换数据,可以进行具有强耦合关系的计算。

这两种超级计算集群分别适用于不同类型的数据分析处理工作。有了超级计算集群软件,利用若干台服务器就可以完成通常只有超级计算机才能完成的计算任务。这类软件有Turbo Linux EnFusion、SCore 等。

高可用性集群对一种服务而言不具有负载均衡功能,它可以提高整个系统的可靠性,但不能提升负载的能力。当然,高可用性集群可以运行多种服务,并根据规则分配在不同节点上,比如节点A提供MySQL服务,同时节点B可以提供Oracle服务,这也可以看成是某种意义上的负载均衡,不过是对多种服务的分配而言。

负载均衡集群适用于提供相对静态的数据服务,比如 HTTP 服务。因为负载均衡集群的各节点间通常没有共用的存储介质,所以用户需将数据复制成多份,存放于每一个提供该项服务的节点上。

以上介绍了Linux集群技术的基本原理,也介绍了几款著名的软件。总之,Linux集群技术最大程度地发挥了服务器和网络的优势,可以使系统实现高性能运作。

2.1.2 硬件负载介绍

目前,许多硬件厂商都已经推出了专用于负载均衡服务器的设备,这类厂商主要有:Arrow Point、F5 Networks、Coyote Point、Hydra Web、Foundry Networks 以及RADWare 等。

作为启动器,负载均衡设备的形式多种多样。一些厂商,如Alteon、ArrowPoint,将负载均衡功能集成到交换设备中,置于服务器与Internet链接之间;而另外一些厂商,如CoyotePoint、F5 Networks以及Hydra Web,则运用两块网络适配器将这一功能集成到计算机中,其中一块连接到前端止于Web服务器的交换机上,另一块通过路由器或其他设备连接到Internet上。一旦负载均衡设备检测到所管理的每台服务器的负载量,就会按照一定的算法和规则来分配转发请求。

Alteon的Coyote Point均衡器、F5 Networks的Big、IP以及RADWare的Web服务定向器支持以最小的TCP链接将请求发送到服务器。

由于采用了负载均衡技术,自动故障恢复得以实现,服务的时间可以延长,7 × 24 可靠和持续运行成为可能。另外,负载均衡设备普遍都支持路径外返回模式,即绕过流量分配器,为那些焦急等待大量数据文件请求响应的客户提供更快的响应时间。

如果负载均衡需求简单,也就是说,接近于通过所有服务器的“共享”级水平,则不需要太高级的均衡产品。同样的,若以静态内容传输,则只需具备循环分配功能的负载均衡设备也就可以了。

在最新的负载均衡产品中,智能化越来越明显。一些智能化的负载均衡设备能够侦测到诸如数据库错误、服务器不可用等信息,从而采取措施恢复会话和重定向服务器,使网站得以顺利进行服务。多址负载均衡设备可以对客户发来的访问请求进行解析,计算出最佳地址,然后将该地址返回给客户端,使客户端自动连接到最佳的数据中心。

负载均衡服务具体分为本地和远程两种。本地负载均衡服务能够平衡服务器集群中所有的服务器和应用之间的通信负载,根据实时响应时间进行判断,将请求交由负载最轻的服务器进行处理,以实现真正的智能通信管理和优秀的服务器群性能。服务器故障切换和多重冗余特性可以让通信绕过故障点,从而使服务器保持运行和可访问状态。并且,每次提供负载均衡服务后,网络应用负载均衡设备都通过记录来了解流量的分布情况。

远程负载均衡服务,针对拥有多个网站地址的企业进行专门设计,能够根据单个URL地址将通信路由到方便可用的站点,从而实现广域网范围的负载平衡。其“快速响应模式”,使所有站点都能对同一用户的访问请求作出响应,响应最快的站点将接受并完成这一访问任务,而不是在发生用户请求时计算“最快”的路由因而产生额外的延迟时间。采用这种模式,可以确保服务器响应时间短,也可以选择对用户满意度产生更大影响的其他算法。系统在后台收集多站点状态信息,如服务器响应时间、通信量、本地系统状态,从而使设备能够立即确定每个数据中心的状态,并将访问导向最佳站点。

2.1.3 软件负载介绍

最早的负载均衡技术是通过DNS轮询来实现的,在DNS中配置多个A记录,查询这个域名的客户机将得到其中一个A记录所对应的地址,从而使得不同的客户访问不同的服务器,达到负载均衡的目的。

DNS轮询是一种简单而有效的负载均衡方法,但不能区分服务器的差异,也不能反映服务器的当前运行状态。当使用DNS轮询的时候,必须尽量保证不同的客户计算机能均匀获得不同的地址。由于 DNS 数据具备刷新时间标志的能力,一旦超过这个时间限制,其他 DNS服务器就需要和此服务器同步数据,就有可能获得不同的IP地址。因此为了使地址能随机分配,应使刷新时间尽量短,不同地方的DNS服务器能更新对应的地址。然而将过期时间设置得过短,会使 DNS 流量大增,而造成额外的网络问题。DNS 轮询的另一个问题是,一旦某个服务器出现故障,即使及时修改了DNS设置,还是要等待足够的时间(刷新时间)修改才能发挥作用,在此期间,使用原故障服务器地址的客户计算机将不能正常访问服务器。

尽管存在各种各样问题,但DNS轮询仍是一种非常有效的方式,包括Yahoo在内的很多大型网站都使用该方法。

另一种方式是使用代理服务器,将请求转发给内部的服务器。这种加速模式可以提升静态网页的访问速度,也可以将请求均匀转发给多台服务器,从而达到负载均衡的目的。

这种代理方式与普通的代理方式有所不同,这种代理方式是代理多个客户访问内部服务器,因此也被称为反向代理,而标准代理方式是客户端使用代理访问多个外部服务器。虽然利用代理服务器实现负载均衡的任务并不是特别复杂,然而由于效率要求特别高,所以实现起来也不简单。

代理服务器本身虽然可以高效运行,但针对每一次请求,代理服务器都必须维护两个连接,一个对外的连接,一个对内的连接,因此对于特别高的连接请求,代理服务器的负载也就非常大。反向代理方式能应用优化的负载均衡策略,使每次访问请求由最空闲的内部服务器来提供服务。但是随着并发连接数量的增加,代理服务器本身的负载也变得非常大,最后反向代理服务器本身就会成为服务的瓶颈。

支持负载均衡的地址转换网关,可以将一个外部IP地址映射为多个内部IP地址,对每次TCP连接请求动态分配其中一个内部地址,达到负载均衡的目的。很多硬件厂商将这种技术集成在交换机中,作为第四层交换的一种功能来实现,一般采用随机选择、根据服务器的连接数量或者响应时间进行选择的负载均衡策略来分配负载。由于地址转换相对来讲比较接近网络的底层,因此就有可能将其集成在硬件设备(通常是局域网交换机)中。

除以上负载均衡方式之外,有的协议内部支持与负载均衡相关的功能,例如HTTP协议中的重定向能力等,HTTP运行于TCP连接的最高层。客户端通过80号端口直接连接到服务器,然后通过TCP连接向服务器端发送HTTP请求。在服务器分清客户端所需的网页和资源之前,至少要进行四次TCP的数据包交换请求。由于负载平衡设备需要把进入的请求分配给多个服务器,因此,它只能在TCP连接时建立,且HTTP请求通过后才能确定如何进行负载平衡。

当一个网站的点击率达到每秒上千次时,TCP 连接、HTTP 报头信息以及进程的时延就显得尤为重要。在 HTTP 请求和报头中有很多对负载平衡有用的信息。最重要的一点是,可以从这些信息中获知客户端所请求的URL和网页,利用得到的信息,负载平衡设备就可以将所有的图片请求分配到一个图片服务器,或者把所有数据库查询请求分配到一个专用的高性能数据库服务器。如果熟悉Web内容交换技术,负载平衡设备可以仅仅根据HTTP报头的cookie字段,利用Web内容交换技术来改善对特定客户的服务,如果能从HTTP请求中找到一些规律,还可以充分利用这些规律作出各种决策。除了TCP连接表的问题外,如何查找合适的HTTP报头信息以及作出负载平衡决策,是影响Web内容交换技术性能的重要问题。

但负载均衡技术依赖于特定协议,因此使用范围有限。根据现有的负载均衡技术,并应用优化的均衡策略,来实现后端服务器负载分担的最优状态。

2.2 搭建LVS+KeepAlived环境

随着网站业务量的不断增长,网站服务器的压力越来越大,所以需要一个合适的负载均衡方案!商业硬件太贵,对于创业型公司而言,如何有效节约成本,节省不必要的浪费,同时实现商业硬件一样高性能、高可用的架构成为值得深思的问题,那么有没有一套行之有效的可伸张、可扩展的负载均衡方案呢?答案是肯定的!可以利用LVS+KeepAlived这套基于完整开源软件的架构,搭建负载均衡及高可用的服务器。

2.2.1 LVS的模式原理以及算法

LVS(Linux Virtual Server),是基于Linux 系统的服务器集群解决方案。其目标是创建一个具有良好的扩展性、高可靠性、高性能和高可用性的体系。许多商业的集群产品,比如RedHat的Piranha、Turbo Linux公司的Turbo Cluster等,都是基于LVS的核心代码完成的。

LVS 的核心就是通过一组服务器来进行负载均衡,通过前端的负载调度器( Load Balancer),将网络请求无缝地调度到真实服务器上,从而使得服务器集群的结构对客户透明,客户端访问集群系统所提供的网络服务就像访问一台高性能、高可用的服务器一样。客户端不受服务器集群的影响,无需作任何修改。系统的伸缩性通过在服务集群中透明地加入或删除节点来实现,通过检测节点或服务进程故障、正确重置来达到系统的高可用性。由于负载调度技术是在Linux 内核中实现的,所以称之为Linux 虚拟服务器(Linux Virtual Server)。

使用LVS架设的服务器集群系统从体系结构上看是透明的,最终用户只感觉到一个虚拟服务器。物理服务器之间可以通过高速的LAN或分布在各地的WAN相连,最前端是负载均衡设备,负责将各种服务请求分发给后面的物理服务器,让整个集群表现得像一台服务于同一IP地址的虚拟服务器。

我们把前端负载均衡机器叫做 Director Server(DR),把后端的实际服务机器叫做 RealServer(RS),把IP虚拟服务器软件叫做IPVS(IP Virtual Server)在调度器的实现技术中,IP负载均衡技术是效率最高的。在已有的 IP 负载均衡技术中,通过网络地址转换(Network Address Translation)将一组服务器构建成一台高性能的、高可用的虚拟服务器的技术,我们称之为VS/NAT 技术(Virtual Server via Network Address Translation)。大多数商业化的IP 负载均衡调度器都使用此方法,如Cisco的LocalDirector、F5的Big/IP和Alteon的ACEDirector。在分析VS/NAT的缺点和网络服务的非对称性的基础上,得出通过IP隧道实现虚拟服务器的方法VS/TUN(Virtual Server via IP Tunneling)和通过直接路由实现虚拟服务器的方法VS/DR (Virtual Server via Direct Routing)。这两种方法可以极大地提高系统的伸缩性。所以,IPVS软件实现了3种IP负载均衡技术,大致原理如下。

NAT(VS/NAT)

通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器在响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。

用地址翻译实现虚拟服务器时,地址转换器有能被外界访问到合法的IP地址,并修改来自专有网络的流出包的地址。在外界看来,包来自地址转换器本身,当外界包送到转换器时,转换器能判断出应该将包送到内部网的哪个节点。该方法的优点是节省IP地址,能对内部进行伪装;缺点是效率低,因为返回给请求方的流量需经过转换器。

IP Tunneling(VS/TUN)

采用NAT技术时,由于请求和响应报文都必须经过调度器地址进行重写,当客户请求越来越多时,调度器的处理能力可能成为瓶颈。为了解决这个问题,调度器可以把请求报文通过IP隧道转发至真实服务器,再由真实服务器将响应直接返回给客户,这样调度器只需处理请求报文即可。一般网络服务应答比请求报文大许多,而采用 VS/TUN 技术后,集群系统的最大吞吐量可以提高10倍。

用IP隧道技术实现虚拟服务器的方式通常在集群节点、Mail服务、News服务、DNS服务、Proxy服务器等。

Direct Routing(VS/DR)

当参与集群的计算机和作为控制管理的计算机在同一个网段时可以使用直接路由技术实现虚拟服务器。控制管理的计算机接收到请求包时将直接送到参与集群的节点。

VS/DR通过改写请求报文的MAC地址,将请求发送到真实服务器,再由真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地提高集群系统的伸缩性。这种方法没有 IP 隧道的开销,对集群中的真实服务器也没有必须支持 IP 隧道协议的要求,但是要求调度器与真实服务器通过网卡连接到同一物理网段。

3种负载均衡技术模式的优缺点简单对比参见表2-1。

表2-1 负载均衡技术模式比较

下面介绍LVS的几种不同算法。

轮询(Round Robin)

调度器通过“轮询”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,在这一过程中,调度器均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。

加权轮询(Weighted Round Robin)

调度器通过“加权轮询”调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

最少连接(Least Connections)

调度器通过“最少连接”调度算法动态地将网络请求调度到已建立的连接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用“最小连接”调度算法可以较好地均衡负载。

加权最少连接(Weighted Least Connections)

在集群系统中的服务器性能差异较大的情况下,调度器采用“加权最少连接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

基于局部性的最少连接(Locality-Based Least Connections)

这种算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标 IP 地址找出该目标 IP 地址最近使用的服务器,若该服务器是可用的,则将请求发送到该服务器;若服务器不存在,或者该服务器不存大或不可用,则用“最少连接”的原则选出一个可用的服务器,并将请求发送到该服务器。

带复制的基于局部性的最少连接(Locality-Based Least Connections with Replication)

这种算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。与LBLC算法的不同之处在于,该算法要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标 IP 地址到一台服务器的映射。该算法根据请求的目标 IP 地址找出与之对应的服务器组,按“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,则将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,该算法将最忙的服务器从服务器组中删除,以降低复制的频率。

目标地址散列(Destination Hashing)

这种调度算法将请求的目标 IP 地址作为散列键(Hash Key),从静态分配的散列表中找出对应的服务器,若该服务器是可用的且未超载,则将请求发送到该服务器,否则返回空值。

源地址散列(Source Hashing)

这种调度算法将请求的源 IP 地址作为散列键(Hash Key),从静态分配的散列表中找出对应的服务器,若该服务器是可用的且未超载,则将请求发送到该服务器,否则返回空值。

最短的期望延迟(Shortest Expected Delay Scheduling SED)

这种调度算法是基于WLC的算法。下面举例说明。

A、B、C三台机器权重分别为1、2、3,连接数也分别是1、2、3。那么如果使用WLC算法,一个新请求进入时可能会分配给A、B、C中的任意一个。使用SED算法运算过程如下:

A:(1+1)/1

B:(1+2)/2

C:(1+3)/3

根据运算结果,把连接交给C。

最少队列调度(Never Queue Scheduling NQ)

这种调度算法无需队列等待,如果Real Server的连接数为0 则直接分配连接任务,不需要再进行SED运算。

2.2.2 KeepAlived简介

KeepAlived是一个类似于Layer3、4、5交换机制的软件,也就是我们平时说的第3层、第4层和第5层交换。KeepAlived用于检测服务器的状态,如果有服务器死机或工作出现故障,KeepAlived会检测到并将其从系统中剔除。当服务器工作正常后,KeepAlived再将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉。

KeepAlived在这里主要用于Real Server的健康状态检查以及LoadBalance主机和BackUP主机之间Failover的实现。

Layer3:KeepAlived使用Layer3的方式工作时,会定期向服务器群中的服务器发送一个ICMP的数据包(即平时用的Ping程序),如果发现某台服务的IP地址没有激活,KeepAlived便报告这台服务器失效,并将其从服务器群中剔除,这种情况的典型例子是服务器被非法关机。Layer3以服务器的IP地址是否有效作为判断服务器工作正常与否的标准。

Layer4:主要以TCP端口的状态来决定服务器的工作正常与否。如Web Server的服务端口一般是80,如果KeepAlived检测到80端口没有启动,便会将把这台服务器从服务器群中剔除。

Layer5:在具体的应用层工作,比 Layer3 和 Layer4 要复杂,在网络上占用的带宽更大一些。KeepAlived 将根据用户的设定检查服务器程序是否正常运行,如果与用户的设定不相符,则KeepAlived将服务器从集群中剔除。

2.2.3 LVS+KeepAlived环境的实践

这里首先介绍LVS/DR模式的网络拓扑情况。如果4台机器均置于IDC机房,前端无防火墙时,整个网络拓扑清晰明了,实施起来也非常方便,只需要向IDC申请5个公网IP即可,多余的一个公网IP分配给VIP。

但如果是置于防火墙后,情况就有点小复杂了,这时虽仍可使用内网IP,但需要将内网的VIP通过防火墙转换成公网IP才可以(注:此时不要进行80端口的映射)。

如果上述网络拓扑结构,后面4台机器均用内网,需要前面的防火墙将内网VIP映射成公网IP(注:不能映射80和443端口)。

LVS比较依赖于网络环境,甚至可以用苛求来形容。要做好LVS的管理,确实得学习很多有关网络通信方面的知识,就像HTTP那么简单了。相对而言,Nginx对网络的依赖较小,理论上只要Ping得通,网页访问正常,Nginx就能连接正常。本书后面将会介绍Nginx。

当LVS的Master出现故障时(如服务器宕机、Web服务终止、网线松动等),无法再接受用户请求,也将请求转发给真实的Web服务器(即便真实Web服务器工作正常),从而导致整个Web服务的瘫痪,即LVS控制器存在单点故障问题。

当LVS的Master正常运行时,如果真实的Web服务器(如RealServer1)出现故障,此时LVS的Master并不知道真实服务器是否能正常提供Web服务,所以仍然向故障的服务器转发用户请求。结果用户请求无法被出现故障的Web服务器响应,造成有些用户可以访问网站而有些则无法访问。

基于以上的问题,需要想办法实现对LVS控制器和Web服务器的健康监测,保证一旦出现问题能在不中断服务的情况下排除故障。即增加LVS控制器,实现主备模式,避免单点故障以及自动删除故障Web服务节点的情况发生并当服务器恢复后再自动将其添加到群集中,这就是LVS+KeepAlived能实现的功能。整个系统的环境拓扑如下。

LVS_Master_dr:192.168.100.10

LVS_Backup_dr:192.168.100.11

VIP:192.168.100.100

RealServer:192.168.100.14

RealServer:192.168.100.15

下面介绍LVS+KeepAlived的安装过程。

为两台LVS主机安装LVS+KeepAlived软件。LVS软件是必需的,因为KeepAlived运行在LVS之上,因此LVS及KeepAlived必须安装在一个系统中,安装过程如下。

tar zxvf ipvsadm-XXX.tar.gz

cd /usr/src/kernels/

ln -s /usr/src/kernels/2.6.XXXXXX/ /usr/src/linux

cd ipvsadm-XXXX

make&&make install

安装KeepAlived并编辑,然后直接用KeepAlived实现负载均衡及高可用性。

tar zxvf keepalived-XXXX.tar.gz

cd KeepAlived-XXXXX

./configure --prefix=/ --with-kernel-dir=/usr/src/kernels/2.6.XXXXXX/

make&&make install

cp /usr/local/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/

cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/

mkdir /etc/keepalived

cp /usr/local/etc/keepalived/keepalived.conf /etc/keepalived/

cp /usr/local/sbin/keepalived /usr/sbin/

service keepalived start|stop

当然也可以直接用命令行启动。

/usr/local/sbin/keepalived -D -f /usr/local/etc/keepalived/keepalived.conf

分别在主、从负载均衡服务器上配置keepalived.conf,内容如下。

! Configuration File for keepalived

global_defs {

notification_email {

admin@example.com

}

notification_email_from admin@example.com

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id linux00

}

vrrp_instance VI_1 {

state MASTER

interface eth0

virtual_router_id 51

priority 100

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.100.100

#  192.168.0.150 dev eth0 label eth0:0

}

}

virtual_server 192.168.100.100 80 {

delay_loop 6

lb_algo wrr

lb_kind DR

persistence_timeout 60

protocol TCP

Real_Server 192.168.100.14 80 {

weight 3

TCP_CHECK {

connect_timeout 10

nb_get_retry 3

delay_before_retry 3

}

}

Real_Server 192.168.100.15 80 {

weight 3

TCP_CHECK {

connect_timeout 10

nb_get_retry 3

delay_before_retry 3

}

}

}

! Configuration File for keepalived

global_defs {

notification_email {

admin@example.com

}

notification_email_from admin@example.com

smtp_server 127.0.0.1

smtp_connect_timeout 30

router_id linux00

}

vrrp_instance VI_1 {

state BACKUP

interface eth0

virtual_router_id 51

priority 99

advert_int 1

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.100.100

#  192.168.0.150 dev eth0 label eth0:0

}

}

virtual_server 192.168.100.100 80 {

delay_loop 6

lb_algo wrr

lb_kind DR

persistence_timeout 60

protocol TCP

Real_Server 192.168.100.14 80 {

weight 3

TCP_CHECK {

connect_timeout 10

nb_get_retry 3

delay_before_retry 3

}

}

Real_Server 192.168.100.15 80 {

weight 3

TCP_CHECK {

connect_timeout 10

nb_get_retry 3

delay_before_retry 3

}

}

}

分别在两台LVS机上启动servcie keepklived start,就可以实现负载均衡及高可用集群的构建。

keepalived.conf配置文件主要分为以下几个模块。

全局定义块

1.Email通知。在有故障时,发邮件报警。

2.LVS负载均衡设备标识(LVS_id)。在一个网络内,该标识是唯一的。

3.花括号“{}”。用来分隔定义块,因此必须成对出现。如果漏写其中一个,KeepAlived运行时,不会得到预期的结果。由于定义块内存在嵌套关系,因此很容易遗漏结尾处的花括号,这点要特别注意。

VRRP定义块

1.同步vrrp组(vrrp_sync_group)。作用:确定失败切换(FailOver)所包含的路由实例个数。即在有两个负载均衡设备时,一旦其中一个负载均衡设备失效,需要自动切换到另一负载均衡设备的实例有哪些。

2.实例组(group)。至少包含一个vrrp实例。

3.vrrp实例(vrrp_instance)。实例名出自实例组(group)所包含的名字。

(1)实例状态(state)。只有MASTER和BACKUP两种状态,并且需要这些单词大写。其中MASTER为工作状态,BACKUP为备用状态。当MASTER所在的服务器失效时,BACKUP所在的系统会自动将其状态由BACKUP变换成MASTER;当原失效的MASTER所在的系统恢复时,原BACKUP所在系统再从MASTER状态恢复到BACKUP状态。

(2)通信接口(interface)。对外提供服务的网络接口,如eth0、eth1。当前主流的服务器都有两个或两个以上的接口,在选择时一定要核实清楚。

(3)LVS_sync_daemon_inteface。负载均衡设备之间的监控接口,类似于HA HeartBeat 的心跳线,但其机制优于Heartbeat,因其没有“裂脑”问题,而是以优先级机制来规避这个麻烦。在DR模式中,LVS_sync_daemon_inteface与服务接口interface使用同一个网络接口。

(4)虚拟路由标识(virtual_router_id)。这个标识是一个数字,并且同一个vrrp实例使用唯一的标识。即同一vrrp实例,MASTER和BACKUP的virtual_router_id是一致的,同时在整个vrrp内是唯一的。

(5)优先级(priority)。以数字表示,数值愈大,优先级越高。在同一vrrp实例里,MASTER的优先级高于BACKUP。若MASTER的priority值为150,那么BACKUP的priority只能是140或更小的数值。

(6)同步通知间隔(advert_int)。MASTER与BACKUP负载均衡设备之间同步检查的时间间隔,单位为秒。

(7)验证(authentication)。包含验证类型和验证密码。验证类型主要有PASS、AH两种,通常使用的类型为 PASS,据说 AH 使用时容易问题。验证密码为明文,同一 vrrp 实例中,MASTER与BACKUP只有使用相同的密码才能正常通信。

4.虚拟IP地址(virtual_ipaddress)。可以有多个地址,每个地址占一行,不需要指定子网掩码。注意:该IP必须与在LVS客户端设定的VIP相一致!

192.168.0.150 dev eth0 label eth0:0 功能为使用label 标签启用eth0:0。

虚拟服务器virtual_server定义块

虚拟服务器定义是KeepAlived框架中最重要的项目,也是KeepAlived.conf文件必不可少的部分。

1.虚拟服务器(virtual_server)。IP来自于vrrp定义块的第4步,后面一个空格,然后加上端口号。定义一个VIP,可以实现多个tcp端口的负载均衡功能。

(1)delay_loop。健康检查时间间隔,单位是秒。

(2)lb_algo。负载均衡调度算法,互联网应用常使用WLC或RR。

(3)lb_kind。负载均衡转发规则,一般包括DR、NAT、TUN3种,在本书的方案中,都使用DR方式。

(4)persistence_timeout。会话保持时间,单位为秒。这个选项对动态网站很有用处:当用户从远程用账号登录网站时,有了该会话保持功能,就能把用户的请求转发给同一个应用服务器。假定现在有一个LVS环境,使用DR转发模式,真实服务器有3台,负载均衡设备不启用会话保持功能。当用户第一次访问的时候,其访问请求被负载均衡设备转给某个真实服务器,这样用户看到一个登录页面,第一次访问完毕;接着用户在登录文本框中填写用户名和密码,然后提交;这时候,问题就可能出现了——不能成功登录。因为没有会话保持,负载均衡设备可能把第2次的请求转发到其他服务器。

(5)转发协议(protocol)。一般有TCP和UDP两种。

2.真实服务器(Real_Server),也即服务器池。其值包括IP地址(多个连续的真实IP)和端口号。

权重(weight),权重值是一个数字,数值越大,权重越高。使用不同的权重值以便为不同性能的机器分配不同的负载,性能较好的机器,分担较多的负载;反之,性能差的机器,则分担较少的负载,这样就可以合理地利用不同性能的机器资源。

客户端配置

在RealServer主机上运行脚本RealServer,为lo:0绑定VIP地址192.168.100.100,操作分别在两台Web主机192.168.100.14、192.168.100.15上实施。操作需提前进行,因为以后的过程中这一步的设置无法更改。

#!/bin/bash

VIP=192.168.100.100

. /etc/rc.d/init.d/functions

case "$1" in

start)

ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $VIP

/sbin/route add -host $VIP dev lo:0

echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore

echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce

echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore

echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce

sysctl -p >/dev/null 2>&1

echo "RealServer Start OK"

;;

stop)

ifconfig lo:0 down

route del $VIP >/dev/null 2>&1

echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore

echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce

echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore

echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce

echo "RealServer Stoped"

;;

*)

echo "Usage: $0 {start|stop}"

exit 1

esac

exit 0

针对上述脚本,下面进行简单说明。

(1)VIP(virtual ip)。直接路由模式的VIP 必须与服务器对外提供服务的IP 地址在同一个网段,并且LVS负载均衡设备和其他所有提供相同功能的服务器都使用这个VIP。

(2)VIP 被绑定在环回接口lo0:0 上,其广播地址是其本身,子网掩码是255.255.255.255。这与标准的网络地址设置有很大的不同。采用可变长掩码方式将网段划分到一个主机地址是为了避免IP地址冲突。

(3)echo段代码的作用是抑制arp广播。否则,将会有众多的机器向其他机器宣称:“嗨!我在这里,我在这里呢!”,这样就乱套了。

值得注意的是:

1.必须向服务器所在机房IDC多申请一个IP供VIP使用;多关注/var/log/messages和ipvsadm-ln,利用其有效信息进行排错。

2.服务器的iptables、selinux均需关闭;在工作环境中,可能出现由iptables的NAT转发问题而导致的LVS失败。当然也可以让iptables允许vrrp协议即可。

3.KeepAlived在启动过程中并不会对配置文件进行语法检查,就算没有配置文件, KeepAlived的守护进程照样能够被运行起来。在默认状态下,即在不指定配置文件的位置的情况下,KeepAlived先查找文件/etc/keepalived/keepalived.conf。

4.Session 的过程默认以文件的形式存在,在浏览器关闭或重启时删除;会话保持时间建议设置为120秒,如果该值设置得不合理,将会对用户的访问效果产生非常恶劣的影响。

5.KeepAlived是LVS的扩展项目,因此两者之间具备良好的兼容性,因此KeepAlived部署比其他类似工具更简单。LVS+KeepAlived 目前是一个应用于生产环境的成熟架构,实现了真正意义上高可用的负载均衡,尤其适用于访问频繁、用户量大的对象,建议熟练掌握。

2.3 FAQ

Q:LVS/DR如何处理请求报文?会修改IP包中的内容吗?

A:VS/DR本身不会关心IP层以上的信息,即使端口号也由TCP/IP协议栈去判断是否正确,VS/DR本身主要完成:

(1)接收Client的请求,根据设定的负载均衡算法选取一台RealServer的IP;

(2)以选取的IP对应的MAC地址作为目标MAC,然后重新将IP包封装成帧转发给这台RS;

(3)在HashTable中记录连接信息。

LVS/DR做的事情很少,也很简单,所以效率很高,与硬件负载均衡设备差距不大。

数据包、数据帧的大致流向为:Client→VS→RS→Client。

Q:RealServer为什么要在lo接口上配置VIP,在出口网卡上配置VIP可以吗?

A:既然要让RS能够处理目标地址为VIP的IP包,首先必须要让RS能接收到这个包。

在lo上配置VIP能够完成包的接收并将结果返回Client,所以不可以将VIP设置在出口网卡上,否则会响应客户端的arp 响应,造成client/gateway arp table紊乱,以至于整个load balance都不能正常工作。

Q:LVS/DR load balancer(director)与RS 为什么要在同一网段中?

A:从上面的问题中相信大家应该看得出LVS/DR是如何将请求转发给RS的,该过程通过数据链路层来实现,所以Director必须和RS在同一网段中。

Q:如何实现高可用性呢?

A:一般在调度器上监控Real Server的健康情况;用ICMP ping 不可达时,资源监测进程通知操作系统内核将该服务器从调度列表中删除或者使之失效。

Q:当主、从服务器切换时会不会丢失原有的session?

A:通常当主调度器失效时,其上所有已建立连接的状态信息将丢失,已有的连接会中断。客户需要重新发送连接请求,从调度器才会将新连接调度到各个服务器上,对客户造成一定的不便。所以,IPVS调度器在Linux内核中建立了一种高效状态同步机制,将主调度器的状态信息及时地同步到从调度器。当从调度器接管时,绝大部分已建立的连接会持续下去。

Q:IPVS是怎么解决https连接问题的呢?

A:IPVS调度器提供了持久服务功能,可以使在设定时间内来自同一IP地址的不同连接被发送到集群中的同一个服务器结点,可以很好地解决客户连接的相关性问题。

Q:针对大规模拒绝服务(Deny of Service)攻击,如何实施防卫策略?

A:在连接上引入一个状态机,不同的报文会使连接处于不同的状态,不同的状态有不同的超时值。在TCP连接中,根据标准的TCP有限状态机进行状态迁移;在UDP中,只设置一个UDP状态。不同状态的超时值可以自行设置。在缺省情况下,SYN状态的超时值为1分钟,ESTABLISHED状态的超时值为15分钟,FIN状态的超时值为1分钟;UDP状态的超时值为5分钟。当连接终止或超时,调度器会将该连接Hash表中删除。

2.4 小结

本章对软硬件负载进行介绍,旨在引导大家以后在生产环境中进行更合适的选择。LVS和KeepAlived的组合为企业提供了一套高性能、高可用的负载方案,本章通过对其各种模式、算法以及参数的介绍,使读者熟悉适合企业的应用特点。

下一章介绍具有定制规则的7层负载——HAProxy软件。

图书在版编目(CIP)数据

高性能网站构建实战/刘鑫著.--北京:人民邮电出版社,2013.1

ISBN 978-7-115-29478-4

Ⅰ.①高… Ⅱ.①刘… Ⅲ.①网站—设计 Ⅳ.①TP393.092

中国版本图书馆CIP数据核字(2012)第223871号

高性能网站构建实战

◆著 刘鑫

责任编辑 陈冀康

◆人民邮电出版社出版发行  北京市崇文区夕照寺街14号

邮编 100061  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

三河市海波印务有限公司印刷

◆开本:787×1092 1/16

印张:23.25

字数:436千字  2013年1月第1版

印数:1-4000册  2013年1月河北第1次印刷

ISBN 978-7-115-29478-4

定价:59.00元

读者服务热线:(010)67132692 印装质量热线:(010)67129223

反盗版热线:(010)67171154

广告经营许可证:京崇工商广字第0021号

相关图书

jQuery EasyUI网站开发实战
jQuery EasyUI网站开发实战
Joomla!模板设计与网站开发
Joomla!模板设计与网站开发
大型网站服务器容量规划
大型网站服务器容量规划
网站设计 开发 维护 推广 从入门到精通
网站设计 开发 维护 推广 从入门到精通
高扩展性网站的50条原则
高扩展性网站的50条原则
网页制作与网站建设从入门到精通
网页制作与网站建设从入门到精通

相关文章

相关课程