看透SpringMVC:源代码分析与实践.html.pdf

上传人:紫竹语嫣 文档编号:5514581 上传时间:2020-05-27 格式:PDF 页数:138 大小:8.98MB
返回 下载 相关 举报
看透SpringMVC:源代码分析与实践.html.pdf_第1页
第1页 / 共138页
看透SpringMVC:源代码分析与实践.html.pdf_第2页
第2页 / 共138页
看透SpringMVC:源代码分析与实践.html.pdf_第3页
第3页 / 共138页
看透SpringMVC:源代码分析与实践.html.pdf_第4页
第4页 / 共138页
看透SpringMVC:源代码分析与实践.html.pdf_第5页
第5页 / 共138页
点击查看更多>>
资源描述

《看透SpringMVC:源代码分析与实践.html.pdf》由会员分享,可在线阅读,更多相关《看透SpringMVC:源代码分析与实践.html.pdf(138页珍藏版)》请在三一文库上搜索。

1、前言 当前网络正在改变人们生活的方方面面,从企业内部的管理和运营到我们个人的吃穿住行,所有这些都跟网络有着密切联系。不过这一切才刚刚开始,未来的网络将会给人们带来更多的惊喜,特别是 在2015年“两会”中将“互联网+”纳入我国的发展战略之后,网络未来几年的高速发展更会超出我们的想象。 在网络技术中基于浏览器的B/S结构无论在PC端还是手机端都充当着至关重要的角色。PC端自不必说,手机中很多应用虽然是以APP的形式存在,但它采用的还是B/S结构,如今日头条、微信的朋友圈 等,这些应用在内部封装了浏览器,后端仍然是Web站点。 在大型网站和复杂系统的开发中,Java无疑具有很大的优势,而在Java

2、的Web框架中Spring MVC以其强大的功能和简单且灵活的用法受到越来越多开发者的青睐。 Spring MVC入门很简单,但是要想真正使用好却并非易事,而且现在也没有全面、深入的使用资料,以致在实际使用的过程中程序员经常会遇到各种各样的问题而不知道如何解决。对Spring MVC这样 的开源项目来说,最好的学习方法当然是分析它的源代码,分析透源代码不仅可以让我们更灵活地使用Spring MVC来开发高质量的产品,而且可以学习到其中的很多优秀的编程技巧和设计理念。 本书除了分析Spring MVC的源代码,还系统地介绍了各种网站架构的演变以及Web开发中所涉及的协议和Tomcat的实现方法,

3、现在很多程序员都想了解这方面的知识,但苦于缺乏通俗易懂的资料,而 且这些也是程序员达到更高的层次所需要的知识。 通过本书你可以得到什么 系统学习网站的各种架构以及相应问题的解决方案。 零基础系统学习Web底层协议及其实现方法。 系统、深入地理解Spring MVC,为灵活开发高质量产品打下基础。 学习Spring MVC的编程技巧和设计理念,提高自己综合思考、整体架构的能力。 学习到笔者设计的一套分析源码的方法器用分析法,古人说“授人以鱼不如授人以渔”,虽然这套方法并不复杂但是对于分析复杂的代码却非常有用。 当然,并不是说像看小说一样翻一遍本书就可以获得这么多东西,这需要大家真正沉下心来认真地

4、去看,而且最好能对照着源代码去看。俗话说“磨刀不误砍柴工”,分析源代码就是磨刀的过程,是 真正提升自己实力的过程,就像武术里的内功修炼一样,只有花足够的时间和精力才能到达一定的高度,这就是我们经常说的“功夫”,当功夫达到一定的高度时很多棘手的问题就可以轻而易举地解决 了。 本书读者对象 有Java编程基础,想学习JavaWeb开发的读者。 有JavaWeb开发经验,想学习Spring MVC的读者。 有基础Spring MVC开发经验,想深入学习的读者。 有丰富Spring MVC开发经验,想学习Spring MVC底层代码的读者。 想自己开发Spring MVC插件的读者。 本书特点 本书从

5、最底层的架构和协议开始讲解,即使没有太多开发经验的读者也可以理解,同时由于本书包含的内容全面而且深入,所以即使有丰富Web开发经验的读者读过之后也会有所收获。 本书采用了总分总的结构,首先概述全书内容,让大家在脑子里建立起整个框架,然后再对每个点展开分析,最后总结。这就好像一栋建筑,首先把它的整体结构展示给大家,然后再具体介绍每个 细节,这样就可以让大家思路清晰而不至于迷失方向。这种模式最符合人的认知方式,所以不仅仅适用于学习,而且可以使用到别的很多地方,比如,进入一个新公司后(特别是大型公司),首先要了解 一下公司都有哪些部门,各个部门之间是怎么协调配合的,弄明白整体结构之后再思考自己的业务

6、,这样就可以理解得更加深,做得更好,如果有机会再多了解点其他部门的业务,这样成长得就会更快。 本书讲解的过程通俗易懂、深入浅出,对于不容易理解的内容,通过简单的例子让大家一目了然。在分析源代码的过程中还对一些代码分析了Spring MVC为什么要那么处理,那么处理有哪些好处, 有些地方还为大家指出了需要注意的问题、可以实现的需求以及可以借鉴的东西等内容。 本书结构安排 本书一共分为四篇。 第一篇首先讲解了网站基础知识,包括网站架构的演变以及每种架构所针对的问题、Web底层的协议以及简单的实现方法,最后分析了Tomcat的实现方法,这样可以让大家对Web有整体而且深入的理 解,从而为分析Spri

7、ng MVC打下坚实的基础。 第二篇分析了Spring MVC的整体结构,帮助大家理解请求是怎么到Spring MVC中的,以及在Spring MVC中都做了些什么,这部分主要是帮大家建立框架,让大家对Spring MVC的整体结构了然于胸,在后 面内容中只需要对具体的组件进行分析即可。 第三篇分别对Spring MVC中的9大组件进行了分析,这部分又分了两步:第一步先分析了每个组件的接口、作用和用法,让大家对每个组件有个大体的认识;第二步详细分析了9大组件的实现。 第四篇对Spring MVC的整体结构做了总结,并对异步请求的原理及用法做了补充。总结分为两步,首先是对Spring MVC的结

8、构进行总结,并从更高的层次分析其设计理念;然后通过跟踪一个具体的请 求帮助大家整体梳理请求的处理过程。异步请求是一块相对独立的内容,如果将其放入Spring MVC的分析过程中将增加大家对Spring MVC的理解难度,所以在最后对其进行单独讲解。 本书源代码可以到 致谢 我最想感谢的就是我的父亲韩志荣,正是因为他的大力支持和背后的默默付出才让笔者可以将更多的时间和精力放在本书的创作上,从而让本书可以在保证质量的前提下以最快的速度跟大家见面。 虽然笔者已经尽了自己最大的努力,但是受水平所限,难免会有遗漏或者讲解不够准确的地方,还请大家批评指正。如果大家通过本书可以对Web开发、对Spring

9、MVC的理解以及对设计的理念有些许 收获,那将是笔者最感到欣慰的事情。 第一篇 网站基础知识 本篇主要给大家介绍网站的基础知识,为后面具体分析Spring MVC打下基础。内容主要包括架构的演变、Web中涉及的协议、协议的实现方法、Java中的Servlet以及对一个完整的产品Tomcat的分析等5部 分。 本篇的很多内容,如底层协议和Tomcat的实现方法,在正常做开发的时候并不会直接使用到,不过理解了之后可以让我们在进行具体开发的时候更加得心应手,就好像数学中的基本运算,我们不需要 知道原理也可以借助计算器计算出结果,但是如果明白了其中的原理就可以对计算带来很多帮助。比如,可以预先大概估计

10、计算结果,当计算器的计算结果偏差很大时就可以看出来;可以使用一些简单的 计算方法;还可以通过对具体内容的学习学到一些优秀思想,思想本身是很难学习的,需要通过一定的载体才可以传播,底层的知识就是这样的载体。 现在社会中普遍注重创新,其实创新是建立在扎实的基础之上的,如果没有扎实的基础就很难做出合理而且易用的创建成果。所以本篇的内容虽然在开发中一般不会直接使用到,但是对于提高自己的 能力非常重要。 第1章 网站架构及其演变过程 本章介绍网站的架构及其演变的过程。现在大型网站的架构变得越来越复杂,不过架构的演变过程并不是没有规律的,它们是在遇到相应问题之后为了解决问题才演变出来的。本章首先从软件的三

11、大 类型说起,然后介绍各种架构的演变过程及其背后的本质。 1.1 软件的三大类型 记得在上学的时候,计算机考试中很经典的一道题是“开电脑时应该先开主机电源还是先开显示器电源”,那个时代的软件主要以单机软件为主,如画图板、五笔打字等,当时学习使用电脑跟学习打 字基本上是一个概念,那些不需要联网的单机软件就是最开始的软件。 后来有的程序需要统一管理软件中使用的数据,所以就将保存数据的数据库统一存放在一台主机中,所有的用户在需要数据时都要从主机获取,这时就分出了客户端和服务端,用户安装的软件叫客户 端(Client),统一管理数据的主机中的软件就叫服务端(Server),这种结构就叫CS结构。再后来

12、这种结构的服务端就不只是管理数据了,另外还可以处理一些业务逻辑,哪些业务放到客户端处理,哪 些业务放到服务端处理就是见仁见智的问题了。业务放到服务端统一处理可以提供更好的安全性和稳定性而且升级比较容易,不过服务器的负担就增加了;业务放到客户端处理可以将负担分配到每个用户 的机器上,从而可以节省服务器的资源,不过安全性和稳定性可能会有一些问题,而且升级也比较麻烦,每个用户安装的客户端程序都需要升级。另外,为了节省网络资源,通过网络传输的数据应该尽量 少。CS结构如图1-1所示。 图1-1 CS结构图 CS结构的程序已经可以完成网络通信了,不过使用起来还是有点麻烦,首先软件提供商需要同时开发客户端

13、和服务端两套软件;其次每个用户在使用时都需要单独安装客户端软件,而且升级的时候也 需要每个用户都进行升级。为了解决这个问题而设计了统一的客户端,而且默认安装在用户电脑里面,这就是我们电脑中的浏览器(Browser),而且一个浏览器可以访问所有同种类型的网站,当然它主 要用作展示数据,具体业务处理是在不同的服务端进行的,这种结构就叫BS结构。BS结构除了提供了统一的客户端,还根据相应协议和标准提供通用的服务器程序,服务器程序统一处理数据连接、封装和 解析等工作。BS结构如图1-2所示。 图1-2 BS结构图 这就是软件的三大类型:单机类型、CS类型和BS类型。在这三种类型中,因为BS类型开发简单

14、、使用方便而且功能强大,所以现在使用最广,当然并不是说BS结构是最好的,具体使用什么结构还需 要根据实际的需求来决定,比如,现在我们电脑中的记事本、Office以及压缩软件等都是单机软件,而它们使用得也非常广泛,另外BS结构虽然比CS结构在开发和使用上都简单,但是BS结构的灵活性和处 理效率都不如CS结构,所以像QQ、大型游戏等软件使用的还是CS结构。 1.2 基础的结构并不简单 前面介绍的BS结构是最基础的结构,不过即使这种最基础的结构的底层实现也并不简单,因为它需要通过互联网传输数据,而互联网是一个错综复杂的网络,其中包含的节点不计其数,而且每两个节 点之间的距离以及连接的路线都是不确定的

15、,数据在传输的过程中还可能会丢失,所以非常复杂。所有问题都有它对治的方法,对于复杂问题的对治方法就是将其分解成多个简单的问题,然后通过解决每 个简单问题,最终解决复杂问题。BS结构网络传输的分解方式有两种:一种是标准的OSI参考模型,另一种是TCP/IP参考模型。它们的分层方式及对应关系如图1-3所示。 图1-3 OSI和TCP/IP分层模型及对应关系 OSI参考模型一共分7层,不过它主要用于教学,实际使用中更多的是TCP/IP的4层模型。对于TCP/IP的4层模型可以简单地理解为: 网络接入层:将需要相互连接的节点接入网络中,从而为数据传输提供条件。 网际互联层:找到要传输数据的目标节点。

16、传输层:实际传输数据。 应用层:使用接收到的数据。 这种分层模型非常容易理解,就好像我们要在网上买东西,首先要确定自己所在的位置有相应的快递,这就相当于网络接入层,然后需要告诉卖家地址,地址就相当于网际互联层,快递送货相当于传 输层,最后我们收到货物之后拆包使用就相当于应用层。 对于广泛使用的东西就需要制定相应的标准,没有规矩不成方圆,如果都按自己的想法去做就乱套了。对一个小作坊来说,做事情可以比较随意,但是一个大型公司就需要有很多制度来规范做事情的 流程了。由于网络传输应用非常广泛,所以需要大家都遵守的规矩,不过网络传输中的这些规矩并不是强制性的,所以不叫制度也不叫标准而叫协议,其实TCP/

17、IP参考模型也可以看作一种协议。BS结构中 TCP/IP模型中的网络接入层没有相应协议,网际互联层是IP协议,传输层是TCP协议,应用层是HTTP协议。 另外在BS结构中还使用到了DNS协议,而且在HTTP上层还有相关的规范,如Java Web开发中使用的是Servlet标准。 数据传输的本质就是按照晶振震动周期或者其整数倍来传输代表0/1的高低电平,传输过程中最核心就是各种传输协议,对直接连接的硬件来说就是各种总线协议,对网络传输来说就是网络协议,如果 将传输的协议弄明白了,那么也就掌握了传输的核心,第2章会介绍BS结构中常用的协议和标准。下面先接着看网站架构的演变过程,开发一套前面介绍的那

18、种BS结构的程序并非难事,特别是使用现在成 形的框架来做就更加简单了,只需要写好核心的业务就可以了。不过这种基础架构的网站虽然可以用但并不代表好用,除了用户交互(那是另外一个话题),最重要的就是速度问题。如果打开一个连接的 时间都可以喝完一杯咖啡,那样的系统能不能使用就看每个人自己的理解了。不过无论怎么理解,如果不是企业内部办公必须使用的系统,也不是像12306那种具有垄断资源的系统,相信大部分人是不会 有那个耐心去等待的。解决速度问题的核心主要就是解决海量数据操作问题和高并发问题,网站复杂的架构就是从这两个问题演变出来的。 1.3 架构演变的起点 基础架构中服务端就一台主机,其中存储了应用程

19、序和数据库,刚上线时是没有问题的,当数据和流量变得越来越大的时候就难以应付了,这时候就需要将应用程序和数据库分别放到不同的主机中, 其结构如图1-4所示。 图1-4 应用和数据分离结构图 1.4 海量数据的解决方案 现在无论是企业的业务系统还是互联网上的网站程序都面临着数据量大的问题,这个问题如果解决不好将严重影响系统的运行速度,下面就针对这个问题的各种解决方案进行系统介绍。 1.4.1 缓存和页面静态化 数据量大这个问题最直接的解决方案就是使用缓存,缓存就是将从数据库中获取的结果暂时保存起来,在下次使用的时候无需重新到数据库中获取,这样可以大大降低数据库的压力。 缓存的使用方式可以分为通过程

20、序直接保存到内存中和使用缓存框架两种方式。程序直接操作主要是使用Map,尤其是ConcurrentHashMap,而常用的缓存框架有Ehcache、Memcache和Redis 等。缓存使用过程中最重要问题是什么时候创建缓存和缓存的失效机制。缓存可以在第一次获取的时候创建也可以在程序启动和缓存失效之后立即创建,缓存的失效可以定期失效,也可以在数据发生变化 的时候失效,如果按数据发生变化让缓存失效,还可以分粗粒度失效和细粒度失效。 多知道点 缓存中空数据的管理方法 如果缓存是在第一次获取的时候创建的,那么在使用缓存的时候最好将没有数据的缓存使用特定的类型值来保存,因为这种方式下如果从缓存中获取不

21、到数据就会从数据库中获取,如果数据库中本来 就没有相应的数据就不会创建缓存,这样将每次都会查询数据库。比如有个专门保存文章评论的缓存,不同的评论按照不同文章的Id来保存,如果有一篇文章本来就没有评论,那么就没有相应的缓存或者 缓存的值为null,这样程序在每次调用这篇文章的评论时都会查询数据库。这就没起到缓存的作用,我们可以创建一个专门的类(如NoComment)来保存没有评论的缓存,这样程序从缓存中查询后就可以知 道是还没有创建缓存还是本来就没有评论内容。 不过缓存也不是什么情况都适用,它主要用于数据变化不是很频繁的情况。而且如果是定期失效(数据修改时不失效)的失效机制,实时性要求也不能太高

22、,因为这样缓存中的数据和真实数据可能会 不一致。如果是文章的评论则关系不是很大,但如果是企业业务系统中要生成报表的数据则问题就大了。 跟缓存相似的另外一种技术叫页面静态化,它在原理上跟缓存非常相似,缓存是将从数据库中获取到的数据(当然也可以是别的任何可以序列化的东西)保存起来,而页面静态化是将程序最后生成的 页面保存起来,使用页面静态化后就不需要每次调用都重新生成页面了,这样不但不需要查询数据库,而且连应用程序处理都省了,所以页面静态化同时对数据量大和并发量高两大问题都有好处。 页面静态化可以在程序中使用模板技术生成,如常用的Freemarker和Velocity都可以根据模板生成静态页面,另

23、外也可以使用缓存服务器在应用服务器的上一层缓存生成的页面,如可以使用Squid, 另外Nginx也提供了相应的功能。 1.4.2 数据库优化 要解决数据量大的问题,是避不开数据库优化的。数据库优化可以在不增加硬件的情况下提高处理效率,这是一种用技术换金钱的方式。数据库优化的方法非常多,常用的有表结构优化、SQL语句优 化、分区和分表、索引优化、使用存储过程代替直接操作等,另外有时候合理使用冗余也能获得非常好的效果。 表结构优化 表结构优化是数据库中最基础也是最重要的,如果表结构优化得不合理,就可能导致严重的性能问题,具体怎么设计更合理也没有固定不变的准则,需要根据实际情况具体处理。 SQL语句

24、优化 SQL语句优化也是非常重要的,基础的SQL优化是语法层面的优化,不过更重要的是处理逻辑的优化,这也需要根据实际情况具体处理,而且要和索引缓存等配合使用。不过SQL优化有一个通用的做法 就是,首先要将涉及大数据的业务的SQL语句执行时间详细记录下来,其次通过仔细分析日志(同一条语句对不同条件的执行时间也可能不同,这点也需要仔细分析)找出需要优化的语句和其中的问题, 然后再有的放矢地优化,而不是不分重点对每条语句都花同样的时间和精力优化。 分区 当数据量变多的时候,如果可以分区或者分表,那将起到非常好的效果。当一张表中的数据量变多的时候操作速度就慢了,所以很容易想到的就是将数据分到多个表中保

25、存,但是这么做之后操作起来 比较麻烦,想操作(增删改查)一个数据还需要先找到对应的表,如果涉及多个表还得跨表操作。其实在常用的数据库中可以不分表而达到跟分表类似的效果,那就是分区。分区就是将一张表中的数据按 照一定的规则分到不同的区来保存,这样在查询数据时如果数据的范围在同一个区内那么可以只对一个区的数据进行操作,这样操作的数据量更少,速度更快,而且这种方法对程序是透明的,程序不需要 做任何改动。 分表 如果一张表中的数据可以分为几种固定不变的类型,而且如果同时对多种类型共同操作的情况不多,那么都可以通过分表来处理,这也需要具体情况具体对待。笔者之前对一个业务系统进行重构开发 时就将其中保存工

26、人工作卡片的数据表分成了三个表,并且对每个表进行分区,在同时使用缓存(主要用于在保存和修改时对其他表的数据获取中,如根据工人Id获取工人姓名、工人类别、所在单位、所 在工段及班组等信息)、索引、SQL优化等的情况下操作速度比原来提高了100倍以上。那时的分表是按照工作卡片的类型来划分的,因为当时的要求是要保留所有的记录。比如,修改了卡片的信息,则需 要保存是谁在什么时候对卡片进行修改,修改前的数据是什么,添加删除也一样,这种需求一般的做法就是用一个字段来做卡片状态的标志位,将卡片分成不同的类型。不过这里由于数据量非常大所以就 将卡片分别保存到了三个表中,第一个表保存正常卡片,第二个表保存删除后

27、的卡片,第三个表保存修改之前的卡片,并且对每个表都进行了分区。由于报表一般是按月份、季度、半年和年来做的,所以 分区是按月份来分的,每个月一个分区,这样问题就解决了。当然随着时间的推移,如果总数据量达到一定程度,还需要进一步处理。 另外一种分表的方法是将一个表中不同类型的字段分到不同的表中保存,这么做最直接的好处就是增删改数据的时候锁定的范围减小了,没被锁定的表中的数据不受影响。如果一个表的操作频率很 高,在增删改其中一部分字段数据的同时另一部分字段也可能被操作,而且(主要指查询)用不到被增删改的字段,那么就可以把不同类型的字段分别保存到不同的表中,这样可以减少操作时锁定数据的 范围。不过这样

28、分表之后,如果需要查询完整的数据就得使用多表操作了。 索引优化 索引的大致原理是在数据发生变化(增删改)的时候就预先按指定字段的顺序排列后保存到一个类似表的结构中,这样在查找索引字段为条件的记录时就可以很快地从索引中找到对应记录的指针并从 表中获取到记录,这样速度就快多了。不过索引也是一把双刃剑,它在提高查询速度的同时也降低了增删改的速度,因为每次数据的变化都需要更新相应的索引。不过合理使用索引对提升查询速度的效果 非常明显,所以对哪些字段使用索引、使用什么类型的索引都需要仔细琢磨,并且最好再做一些测试。 使用存储过程代替直接操作 在操作过程复杂而且调用频率高的业务中,可以通过使用存储过程代替

29、直接操作来提高效率,因为存储过程只需要编译一次,而且可以在一个存储过程里面做一些复杂的操作。 上面这些就是经常用到的数据库优化的方法,实际环境中怎么优化还得具体情况具体分析。除了这些优化方法,更重要的是业务逻辑的优化。 1.4.3 分离活跃数据 虽然有些数据总数据量非常大,但是活跃数据并不多,这种情况就可以将活跃数据单独保存起来从而提高处理效率。比如,对网站来说,用户很多时候就是这种数据,注册用户很多,但是活跃用户却 不多,而不活跃的用户中有的偶尔也会登录网站,因此还不能删除。这时就可以通过一个定期处理的任务将不活跃的用户转移到别的数据表中,在主要操作的数据表中只保存活跃用户,查询时先从默认表

30、 中查找,如果找不到再从不活跃用户表中查找,这样就可以提高查询的效率。判断活跃用户可以通过最近登录时间,也可以通过指定时间段内登录次数。除了用户外还有很多这种类型的数据,如一个网站 上的文章(特别是新闻类的)、企业业务系统中按时间记录的数据等。 1.4.4 批量读取和延迟修改 批量读取和延迟修改的原理是通过减少操作的次数来提高效率,如果使用得恰当,效率将会呈数量级提升。 批量读取是将多次查询合并到一次中进行,比如,在一个业务系统中需要批量导入工人信息,在导入前需要检查工人的编码是否已经在数据库中、工人对应的部门信息是否正确(在部门表中是否存 在)、工人的工种信息在工种表中是否存在等,如果每保存

31、一条记录都查询一次数据库,那么对每个需要检查的字段,都需要查询与要保存的记录条数相同次数的数据库,这时可以先将所有要保存的数据 的相应字段读取到一个变量中,然后使用in语句统一查询一次数据库,这样就可以将n(要保存记录的条数)次查询变为一次查询了。除了这种对同一个请求中的数据批量读取,在高并发的情况下还可以将 多个请求的查询合并到一次进行,如将3秒或5秒内的所有请求合并到一起统一查询一次数据库,这样就可以有效减少查询数据库的次数,这种类型可以用异步请求来处理。 延迟修改主要针对高并发而且频繁修改(包括新增)的数据,如一些统计数据。这种情况可以先将需要修改的数据暂时保存到缓存中,然后定时将缓存中

32、的数据保存到数据库中,程序在读取数据时可 以同时读取数据库中和缓存中的数据。这里的缓存和前面介绍的缓存有本质的区别,前面的缓存在使用过程中,数据库中的数据一直是最完整的,但这里数据库中的数据会有一段时间不完整。这种方式下 如果保存缓存的机器出现了问题将可能会丢失数据,所以如果是重要的数据就需要做一些特殊处理。笔者之前所在的单位有一个系统需要每月月末各厂分别导入自己厂当月的相应数据,每到月末那个系统 就处于基本瘫痪的状态了,而且各厂从整理出数据到导入系统只有几天的时间,所以有的厂就专门等晚上人少的时候才进行操作,对于这种情况就可采用延迟修改的策略来解决。 1.4.5 读写分离 读写分离的本质是对

33、数据库进行集群,这样就可以在高并发的情况下将数据库的操作分配到多个数据库服务器去处理从而降低单台服务器的压力,不过由于数据库的特殊性每台服务器所保存的数 据都需要一致,所以数据同步就成了数据库集群中最核心的问题。如果多台服务器都可以写数据那么数据同步将变得非常复杂,所以一般情况下是将写操作交给专门的一台服务器处理,这台专门负责写的 服务器叫做主服务器。当主服务器写入(增删改)数据后从底层同步到别的服务器(从服务器),读数据的时候到从服务器读取,从服务器可以有多台,这样就可以实现读写分离,并且将读请求分配到多 个服务器处理。主服务器向从服务器同步数据时,如果从服务器数量多,那么可以让主服务器先向

34、其中一部分从服务器同步数据,第一部分从服务器接收到数据后再向另外一部分同步,这时的结构如图1-5 所示。 图1-5 数据库读写分离结构图 简单的数据同步方式可以采用数据库的热备份功能,不过读取到的数据可能会存在一定的滞后性,高级的方式需要使用专门的软硬件配合。另外既然是集群就涉及负载均衡问题,负载均衡和读写分离 的操作一般采用专门程序处理,而且对应用系统来说是透明的。 1.4.6 分布式数据库 分布式数据库是将不同的表存放到不同的数据库中然后再放到不同的服务器。这样在处理请求时,如果需要调用多个表,则可以让多台服务器同时处理,从而提高处理速度。 数据库集群(读写分离)的作用是将多个请求分配到不

35、同的服务器处理,从而减轻单台服务器的压力,而分布式数据库是解决单个请求本身就非常复杂的问题,它可以将单个请求分配到多个服务器处 理,使用分布式后的每个节点还可以同时使用读写分离,从而组成多个节点群,结构图如图1-6所示。 图1-6 分布式数据库架构图 实际使用中分布式数据库有很多复杂的问题需要解决,如事务处理、多表查询等。分布式的另外一种使用的思路是将不同业务的数据表保存到不同的节点,让不同的业务调用不同的数据库,这种用法 其实是和集群一样起分流的作用,不过这种情况就不需要同步数据了。使用后面这种思路时架构还是和上面图中的一样,所以技术和架构只是一个工具,真正重要的是思路,也就是工具的使用方法

36、。 1.4.7 NoSQL和Hadoop NoSQL是近年来发展非常迅速的一项技术,它的核心就是非结构化。我们一般使用的数据库(SQL数据库)都是需要先将表的结构定义出来,一个表有几个字段,每个字段各是什么类型,然后才能往 里面按照相应的类型保存数据,而且按照数据库范式的规定,一个字段只能保存单一的信息,不可以包括多层内容,这就对使用的灵活性带来了很大的制约,NoSQL就是突破了这些条条框框,可以非常灵 活地进行操作,另外因为NoSQL通过多个块存储数据的特点,其操作大数据的速度也非常快,这些特性正是现在的互联网程序最需要的,所以NoSQL发展得非常快。现在NoSQL主要使用在互联网的程序 中

37、,在企业业务系统中使用的还不多,而且现在NoSQL还不是很成熟,但由于灵活和高效的特性,NoSQL发展的前景是非常好的。 Hadoop是专门针对大数据处理的一套框架,随着近年来大数据的流行Hadoop也水涨船高,出世不久就红得发紫。Hadoop对数据的存储和处理都提供了相应的解决方案,底层数据的存储思路类似于 1.4.6节介绍的分布式加集群的方案,不过Hadoop是将同一个表中的数据分成多块保存到多个节点(分布式),而且每一块数据都有多个节点保存(集群),这里集群除了可以并行处理相同的数据,还可 以保证数据的稳定性,在其中一个节点出现问题后数据不会丢失。这里的每个节点都不包含一个完整的表的数据

38、,但是一个节点可以保存多个表的数据,结构图如图1-7所示。 图1-7 Hadoop数据存储结构图 Hadoop对数据的处理是先对每一块的数据找到相应的节点并进行处理,然后再对每一个处理的结果进行处理,最后生成最终的结果。比如,要查找符合条件的记录,Hadoop的处理方式是先找到每一 块中符合条件的记录,然后再将所有获取到的结果合并到一起,这样就可以将同一个查询分到多个服务器处理,处理的速度也就快了,这一点传统的数据库是做不到的。 1.5 高并发的解决方案 除了数据量大,另一个常见的问题就是并发量高,很多架构就是针对这个问题设计出来的,下面分别介绍。 1.5.1 应用和静态资源分离 刚开始的时候

39、应用和静态资源是保存在一起的,当并发量达到一定程度时就需要将静态资源保存到专门的服务器中,静态资源主要包括图片、视频、js、css和一些资源文件等,这些文件因为没有状 态,所以分离比较简单,直接存放到相应的服务器就可以了,一般会使用专门的域名去访问,比如,新浪的图片保存在域名对应的服务器中,而百度的图片则是通过二级域名 访问的,通过不同的域名可以让浏览器直接访问资源服务器而不需要再访问应用服务器了,这时的架构如图1-8所示。 图1-8 应用和静态资源分离架构图 1.5.2 页面缓存 页面缓存是将应用生成的页面缓存起来,这样就不需要每次都重新生成页面了,从而可以节省大量CPU资源,如果将缓存的页

40、面放到内存中速度就更快了。如果使用了Nginx服务器就可以使用它自带 的缓存功能,当然也可以使用专门的Squid服务器。页面缓存的默认失效机制一般是按缓存时间处理的,当然也可以在修改数据之后手动让相应缓存失效。 多知道点 有部分经常变化的数据的页面怎么使用页面缓存 页面缓存主要是使用在数据很少发生变化的页面中,但是有很多页面是大部分数据都很少发生变化,而其中有很少一部分数据变化的频率却非常高,比如,一个显示文章的页面正常来说是完全可以静 态化的,但是如果在文章后面有“顶”和“踩”的功能而且显示的有相应的数量,这个数据的变化频率就比较高了,这就会影响静态化,在电商系统中显示商品详情的页面中的销售

41、数量也是这种情况,对 于这个问题可以先生成静态页面然后使用Ajax来读取并修改相应的数据,这样就可以一举两得了,既可以使用页面缓存也可以实时显示一些变化频率高的数据了。 1.5.3 集群与分布式 集群和分布式处理都是使用多台服务器进行处理的,集群是每台服务器都具有相同的功能,处理请求时调用哪台服务器都可以,主要起分流的作用,分布式是将不同的业务放到不同的服务器中,处理 一个请求可能需要用到多台服务器,这样就可以提高一个请求的处理速度,而且集群和分布式也可以同时使用,结构图如图1-9所示。 集群有两个方式:一种是静态资源集群。另一种是应用程序集群。静态资源集群比较简单,而应用程序集群就有点复杂了

42、。因为应用程序在处理过程中可能会使用到一些缓存的数据,如果集群就需要 同步这些数据,其中最重要的就是Session,Session同步也是应用程序集群中非常核心的一个问题。Session同步有两种处理方式:一种是在Session发生变化后自动同步到其他服务器,另外一种方式是用 一个程序统一管理Session。所有集群的服务器都使用同一个Session,Tomcat默认使用的就是第一种方式,通过简单的配置就可以实现,第二种方式可以使用专门的服务器安装Memcached等高效的缓存 程序来统一管理Session,然后在应用程序中通过重写Request并覆盖getSession方法来获取指定服务器中

43、的Session。对于集群来说还有一个核心的问题就是负载均衡,也就是接收到一个请求后具体分配 到哪个服务器去处理的问题,这个问题可以通过软件处理也可以使用专门的硬件(如F5)解决。 图1-9 应用程序分布式集群结构图 另外笔者还想到了一种思路可以简单地解决Session同步的问题,Session需要同步的本质原因就是要使用不同的服务器给同一个用户提供服务,如果负载均衡在分配请求时可以将同一个用户(如按 IP)分配到同一台服务器进行处理也就不需要Session同步了,而且这种方法一般也不会对负载均衡带来太大的问题,如果考虑到稳定性,为了防止有机器宕机后丢失数据还可以将集群的服务器分成多个 组,然

44、后在小范围的组(如2、3台服务器)内同步Session。 架设分布式应用程序是一件非常复杂的事情,Session同步肯定是需要的,分布式事务处理和各个节点之间复杂的依赖关系也是分布式中非常复杂的问题,如果要使用分布式一定要做好足够的准备。 1.5.4 反向代理 反向代理指的是客户端直接访问的服务器并不真正提供服务,它从别的服务器获取资源然后将结果返回给用户的,如图1-10所示。 图1-10 反向代理服务器 多知道点 反向代理服务器和代理服务器的区别 代理服务器的作用是代我们获取想要的资源然后将结果返回给我们,所要获取的资源是我们主动告诉代理服务器的,比如,我们想访问Facebook,但是直接访

45、问不了,这时就可以让代理服务器访问, 然后将结果返回给我们。 反向代理服务器是我们正常访问一台服务器的时候,服务器自己调用了别的服务器的资源并将结果返回给我们,我们自己并不知道。 代理服务器是我们主动使用的,是为我们服务的,它不需要有自己的域名;反向代理服务器是服务器自己使用的,我们并不知道,它有自己的域名,我们访问它跟访问正常的网址没有任何区别。 反向代理服务器可以和实际处理请求的服务器在同一台主机上,而且一台反向代理服务器也可以访问多台实际处理请求的服务器。反向代理服务器主要有三个作用:可以作为前端服务器跟实际处理 请求的服务器(如Tomcat)集成;可以用做负载均衡;转发请求,比如,可以

46、将不同类型的资源请求转发到不同的服务器去处理,可以将动态资源转发到Tomcat、Php等动态程序而将图片等静态资 源的请求转发到静态资源的服务器,另外也可以在url地址结构发生变化后将新地址转发到原来的旧地址上。 1.5.5 CDN CDN其实是一种特殊的集群页面缓存服务器,它和普通集群的多台页面缓存服务器比主要是它存放的位置和分配请求的方式有点特殊。CDN的服务器是分布在全国各地的,当接收到用户的请求后会将 请求分配到最合适的CDN服务器节点获取数据,比如,联通的用户会分配到联通的节点,电信的用户会分配到电信的节点;另外还会按照地理位置进行分配,北京的用户会分配到北京的节点,上海的用户 会分

47、配到上海的节点。CDN的每个节点其实就是一个页面缓存服务器,如果没有请求资源的缓存就会从主服务器获取,否则直接返回缓存的页面。CDN分配请求的方式比较特殊,它并不是使用普通的负载 均衡服务器来分配的,而是用专门的CDN域名解析服务器在解析域名的时候就分配好的,一般的做法是在ISP那里使用CNAME将域名解析到一个特定的域名,然后再将解析到的那个域名用专门的CDN服 务器解析到相应的CDN节点,结构图如图1-11所示。 图1-11 CDN结构图 第二步访问CDN的DNS服务器是因为CNAME记录的目标域名使用NS记录指向了CDN的DNS服务器。CDN的每个节点可能也是集群了多台服务器。CDN的原

48、理并不复杂,不过如果要自己去架设则需 要投入大量的资金,现在有专门的CDN服务商,可以直接购买它们的服务。 1.6 底层的优化 我们前面讲到的所有架构都是建立在最前面介绍的基础架构之上的,而且很多地方都需要通过网络传输数据,如果可以加快网络传输的速度,那将会让整个系统从根本上得到改善。网络传输数据都是 按照各种协议进行的,不过协议并不是不可以改变,Google就迈出了这一步,它制定了Quic、Spdy等协议来传输数据,Quic比TCP效率高而且比UDP安全,Spdy协议在现有HTTP协议的基础上增加了很 多新特性,提高了传输的效率,不过有些特性已经包含到了HTTP/2协议中,而且Google也

49、已经放弃了Spdy而使用HTTP/2了。 1.7 小结 网站架构的整个演变过程主要是围绕大数据和高并发这两个问题展开的,解决的方案主要分为使用缓存和使用多资源两种类型。多资源主要指多存储(包括多内存)、多CPU和多网络,对于多资源来 说又可以分为单个资源处理一个完整的请求和多个资源合作处理一个请求两种类型,如多存储和多CPU中的集群和分布式,多网络中的CDN和静态资源分离。理解了整个思路之后就抓住了架构演变的本 质,而且自己可能还可以设计出更好的架构。 一个网站具体使用什么样的架构需要根据实际需要做出选择,网站架构并不是竞技场,更不是使用的技术越复杂越好,只要可以满足自己的需要、可以解决自己所遇到的问题就可以了。要想设计出合 理的架构首先需要理解每种架构所针对的问题和它背后的本质,只有这样才能真正把架构用做解决问题的工具,而不是为了架构而架构最后问题不一定能解决还浪费了资源。另外在使用复杂架构之前一定 要先将自己的业务优化好,这是基础中的基础,非常重要! 无论架构还是协议都要以正确的态度对待,它们都是为了解决特定的问题而设计出来的,我们要认真并且谦虚地学习,不过也不需要将它们当成神圣不可侵犯的东西,它们的本质还是为我们解决

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/环境 > 建筑资料


经营许可证编号:宁ICP备18001539号-1