关于大型网站技术演进的思考

网站静态化处理--总述(1)

存储瓶颈的开篇我提到像hao123这样的导航网站只要它部署的web服务器数 量足够,它能够承载超大规模的并发访问量,若是是一个动态的网站,特别是使用到了数据库的网站是很难作到经过增长web服务器数量的方式来有效的增长网站 并发访问能力的。可是现实状况是像淘宝、京东这样的大型动态网站在承担高并发的状况下任然能保证快速的响应,这其中有什么样的技术手段能够达到动态网站支 撑高并发的场景了,这也许是每一个作web开发的朋友都很感兴趣的问题,今天我将写一个新的系列来探讨下这个问题,但愿个人经验和研究能给大多数人以启迪。 这里要说明下,本系列的写法和存储的瓶颈的写法有所不一样,本系列开始部分主要是讲解原理,后面部分会针对原理讲解具体的实现手段,若是有朋友感受这种写法 不适应,还请谅解。javascript

  我我的总结下来,这些大型动态网站之因此能够作到能快速响应高并发,它们都是尽可能让本身的网站静态化,固然这种静态化毫不是把网站就作成静态网站,而 是在充分理解了静态网站在提高网站响应速度的基础上对动态网站进行改良,因此我这里首先要讨论下静态网站那些特色能够用于咱们提高网站的响应速度。php

  静态网站很是简单,它就是经过一个url访问web服务器上的一个网页,web服务器接收到请求后在网络上使用http协议将网页返回给浏览器,浏览 器经过解析http协议最终将页面展现在浏览器里,有时这个网页会比较复杂点,里面包含了一些额外的资源例如:图片、外部的css文件、外部的js文件以 及一些flash之类的多媒体资源,这些资源会单独使用http协议把信息返回给浏览器,浏览器从页面里的src,href、Object这样的标签将这 些资源和页面组合在一块儿,最终在浏览器里展现页面。可是无论什么类型的资源,这些资源若是咱们不是手动的改变它们,那么咱们每次请求得到结果都是同样的。 这就说明静态网页的一个特色:静态网页的资源基本是不会发生变化的。所以咱们第一次访问一个静态网页和咱们之后访问这 个静态网页都是一个重复的请求,这种网站加载的速度基本都是由网络传输的速度,以及每一个资源请求的大小所决定,既然访问的资源基本不会发生变化,那么咱们 重复请求这些资源,本身在那里空等不是很浪费时间吗?如是乎,浏览器出现了缓存技术,咱们开发时候能够对那些不变的资源在http协议上编写相应指令,这 些指令会让浏览器第一次访问到静态资源后缓存起这些静态资源,用户第二次访问这个网页时候就再也不须要重复请求了,由于请求资源本地缓存,那么获取它的效率 就变得异常高效。css

  因为静态网站的请求资源是不会常常发生变化的,那么这种资源其实很容易被迁移,咱们都知道网络传输的效率是和距离长短有关系的,既然静态资源很容易被迁移那么咱们就能够把静态资源服务器按地域分布在多个服务节点上,当用户请求网站时候根据一个路由算法将请求落地在离用户最近的节点上,这样就能够减小网络传输的距离从而提高访问的效率,这就是咱们长提的大名鼎鼎的CDN技术,内容分发网络技术。html

  网络传输效率还和咱们传输资源的大小有关,所以咱们在资源传输前将其压缩,减少资源的大小从而达到提高传输效率的目的;另外,每一个http请求其实都 是一个tcp的请求,这些请求在创建链接和释放链接都会消耗不少系统资源,这些性能的消耗时常会比传输内容自己还要大,所以咱们会尽力减小http请求的 个数来达到提高传输效率的目的或者使用http长链接来消除创建链接和释放链接的开销(长链接的使用要看具体场景,这个我会在后面文章讲到)。前端

  其实雅虎提出的网站优化的14条建议大部分都是基于以上原理得出的,关于雅虎的14条件建议,本系列后面内容将作详细的讨论,这里就不展开了。html5

  我经常认为最佳的性能优化手段就是使用缓存了,可是缓存的数据通常都是那些不会常常变化的数据,上文里说到的浏览器缓存,CDN其实都是能够当作缓存手段来理解,它们也是提高网站性能最为有效的方式之一,可是这些缓存技术到了动态网站却变得异常很差实施,这究竟是怎么回事了?java

  首先动态网站和静态网站有何不一样呢?我以为动态网站和静态网站的区别就是动态网站网页虽然也有一个url,可是咱们若是传输参数不一样那么这个url请求的页面并非彻底同样,也就是说动态网站网 页的内容根据条件不一样是会发生改变的,可是这些变化的内容倒是同一个url,url在静态网站里就是一个资源的地址,那么在动态网站里一个地址指向的资源 实际上是不一样的。由于这种不一样因此咱们无法把动态的网页进行有效的缓存,并且不恰当的使用缓存还会引起错误,因此在动态网页里咱们会在meta设定页面不会 被浏览器缓存。node

  若是每次访问动态的网页该网页的内容都是彻底不一样的,也许咱们就没有必要写网站静 态化的主题了,现实中的动态网页每每只是其中一部分会发生变化,例如电商网站的菜单、页面头部、页面尾部这些其实都不会常常发生变化,若是咱们只是由于网 页一小部分常常变化让用户每次请求都要重复访问这些重复的资源,这实际上是很是消耗计算资源了,咱们来作个计算吧,假如一个动态页面这些不变的内容有 10k,该网页一天有1000万次的访问量,那么天天将消耗掉1亿kb的网络资源,这个其实很不划算的,并且这些重复消耗的宽带资源并无为网站的用户体 验带来好处,相反还拖慢了网页加载的效率。那么咱们就得考虑拆分网页了,把网页作一个动静分离,让静态的部分当作不变的静态资源进行处理,动态的内容仍是 动态处理,而后在合适的地方将动静内容合并在一块儿。nginx

  这里有个关键点就是动静合并的位置,这个位置的选择会直接致使咱们整个web前端的架构设计。咱们这里以java的web开发为例,来谈谈这个问题。程序员

  java的web开发里咱们通常使用jsp来编写页面,固然也能够使用先进点的模板引擎开发页面例如velocity,freemark等,无论咱们 页面使用的是jsp仍是模板引擎,这些相似html的文件其实并非真正的html,例如jsp本质实际上是个servlet也就是一个java程序,因此 它们的本质是服务端语言和html的一个整合技术,在实际运行中web容器会根据服务端的返回数据将jsp或 模板引擎解析成浏览器能解析的html,而后传输这个html到浏览器进行解析。因而可知服务端语言提供的开发页面的技术实际上是动静没法分离的源头,可是 这些技术能够很好的完成动静资源中的动的内容,所以咱们想作动静分离那么首先就要把静的资源从jsp或者模板语言里抽取出来,抽取出来的静态资源固然就要 交给静态的web服务器来处理,咱们经常使用的静态资源服务器通常是apache或ngnix,因此这些静态资源应该放置在这样的服务器上,那么咱们是否能够在这些静态web服务器上作动静结合呢?答案是还真行,例如apache服务器有个模块就能够将它自身存储的 静态资源和服务端传输的资源整合在一块儿,这种技术叫作ESI,这个时候咱们能够把不变的静态内容制做成模板放置在静态服务器上,动态内容达到静态资源服务 器时候,使用ESI或者CSI的标签,把动静内容结合在一块儿,这就完成了一个动静结合操做。这里就有一个问题了,我前面提到过CDN,CDN其实也是一组 静态的web服务器,那么咱们是否能够把这些事情放到CDN作了?理论上是能够作到,可是现实倒是不太好作,由于除了一些超有钱的互联网公司,大部分公司 使用的CDN都是第三方提供的,第三方的CDN每每是一个通用方案,再加上人家毕竟不是本身人,并且CDN的主要目的也不是为了作动静分离,所以大部分情 况下在CDN上完成这类操做并非那么顺利,所以咱们经常会在服务端的web容器前加上一个静态web服务器,这个静态服务器起到一个反向代理的做用,它能够作不少事情,其中一件事情就是能够完成这个动静结合的问题。

  那么咱们把这个动静结合点再往前推,推到浏览器,浏览器能作到这件事情吗?若是浏览器能够,那么静态资源也就能够缓存在客户端了,这比缓存在CDN效 率还要高,其实浏览器还真的能够作到这点,特别是ajax技术出现后,浏览器来整合这个动静资源也就变得更加容易了。不过通常而言,咱们使用ajax作动 静分离都是都是从服务端请求一个html片断,到了浏览器后,使用dom技术将这个片断整合到页面里,虽然这个已经比全页面返回高效不少,可是他仍是有问 题的,服务端处理完请求最终返回结果其实都是很纯粹的数据,但是这些数据咱们不得不转化为页面片断返回给浏览器,这本质是为纯粹的数据上加入了不少与服务 端无用的结构,之因此说无用是由于浏览器自身也能够完成这些结构,为何咱们必定要让服务端作这个事情了?如是乎javascript的模板技术出现了,这些模板技术和jsp,velocity 相似,只不过它们是经过javascript设计的模板语言,有了javascript模板语言,服务端能够彻底不用考虑对页面的处理,它只须要将有效的 数据返回到页面就好了,使用了javascript模板技术,可让咱们动静资源分离作的更加完全,基本上全部的浏览器相关的东西都被静态化了,服务端只 须要把最原始的数据传输到浏览器便可。讲到这里咱们就说到了web前端最前沿的技术了:javascriptMVC架构了。

 

网站静态化处理—动静整合方案(2)

上篇文章我简要的介绍了下网站静态化的演进过程,有朋友可能认为这些知识有点过于稀松日常了,并且网站静态化的技术基点也不是那么高深和难以理解, 所以它和时下突飞猛进的web前端技术相比,就显得不三不四了。其实当我打算写本系列的以前我我的以为web前端有一个点是不少人都知道重要,可是有经常 低估它做用的,那就是web前端和web服务端如何融合的这个点上,这个点再加上咱们要作出一个规模庞大,高并发,快速响应的网站时候它对于web前端的架构技术的演进起到了一个不可忽视的做用。

  网站的web前端要实现高效,第一个要解决的短板就是网络的延迟性对网站的加载效率的影响,固然不少人会说网速快不快这是网络运营商的问题,不是网站 的问题,可是你们确定也见过就算咱们用上了千兆宽带也会有些网站加载速度慢的让人没法忍受,网站自己的确是无法控制网络速度的能力,可是若是咱们不下降网 络对页面加载效率的影响,其余任何优化网站的手段也就无从谈起,缘由就是网络效率对于网页加载效率的影响是起到大头做用的,只有这个大头被解决了,那么解 决其余的小头才能发挥做用。

  回到上文讲到的网站静态化的关键点动静分离,解决这个关键点的本质就是为了下降网速对网站加载效率的影响,可是咱们在处理动静分离问题时候采起的策略不一样会对咱们整个网站架构产生重大影响,特别是将网页作好动静拆分后,静态的资源尽力向浏览器端推移,这就致使了前端架构出 现了之前服务端才有的MVC模式,这就致使web前端架构产生了质的变化,如是一些原来适用于flash这样的重客户端的技术也被传统的web前端所采 用,MVC模式在web前端进一步演进由此而出现了MVP(Model-View-Presenter)模式,MVVM(Model-View- ViewModel)模式。也许上篇文章里有人对讲述动静分离的原理有点异议,可是当今突飞猛进的web前端技术就是这些常见技术不断演化而来,这就是我 上篇想表达的内容,我以为这个系列的特色应该是细节,这是和上个系列存储的瓶颈注重思想是有所不一样的。

  动态网站最难以动静分离的就是页面了,其余的静态资源例如:图片、外部脚本文件等等这些和静态网站的 手法基本一致,其实业界很早就关注了动态网站的动静分离问题,而且为不一样的动静分离方案都进行了总结,今天我就介绍下这些技术。本人web服务端的工做语 言是java,所以下面服务端的例子是使用java的web技术阐述的,其余语言例如php都有与之对应的技术,因此请那些不是使用java做为服务端工 做语言的朋友能够类比学习。

  在java的web开发里,页面技术jsp自己就包含了将页面动静分离的手段,例以下面的代码:

1
2
3
4
5
6
7
<%@ include file=”header.<span style="width: auto; height: auto; float: none;" id="10_nwp"><a style="text-decoration: none;" mpid="10" target="_blank" href="http://cpro.baidu.com/cpro/ui/uijs.php?c=news&cf=1001&ch=0&di=128&fv=16&jk=8b18a605b896566a&k=jsp&k0=jsp&kdi0=0&luki=2&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=6a5696b85a6188b&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5967%2Ehtml&urlid=0" id="10_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">jsp</span></a></span>” %>
 
<body>
 
          ……….
 
<%@ include file=”footer.jsp” %>

  通常一个网站的头部和尾部都是同样,所以咱们把头部的代码单独放置在一个header.jsp页面里,页面尾部的代码放置下footer.jsp页面 里,这样技术人员在开发页面时候就再也不须要重复编写这些重复的代码,只须要引用便可,这个作法最大的好处就是能够避免不一样页面在相同代码这块的不一致性, 假如没有这个统一引用的话,手动编写或者复制和粘贴,出错的几率是很是的高的。

  可是这个作法有一个问题,问题就是这种动静分离其实都是做用于单个页面的,也就是说每一个页面都要手动的重复这个动静分离的操做,大多数状况这种作法都不会有什么问题,可是对于一个大型网站而言这种作法就有可能会制造没必要要的麻烦,这里我截取了一张京东的首页,以下图所示:

 

  讲述前我要事先声明下,京东网站可 能不存在我要讲述的问题,我这里只是使用京东网站的首页作例子来讲明,看图里的首页和食品两个条目,有些公司作这样的网站时候这些导航进入的页面会是一个 独立的工程,每一个工程都是由独立的项目组开发维护的,虽然项目组不一样可是他们页面的总体结构会是一致的,若是按照上面的动静分离手段,那么每一个项目组都要 独立维护一份相同的头部尾部资源,这个时候麻烦来了,若是该公司要新增个新的条目,那么每一个项目组都要更新本身不变的资源,若是该企业一共分了5个项目 组,如今又作了一个新的条目,那么其余与之无关的项目组都得折腾一次更改统一引用文件的工做,要是作的不仔细就有可能出现页面展现不一致的问题,为了解决 这个问题,java的web开发里就会考虑使用模板语言替代jsp页面技术,例如模板语言velocity,这些模板语言都包含一个布局的功能,例如velocity就有这样的功能,咱们看看velocity的布局模板实例,以下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
 
<head>
 
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 
     <title>#springMessage("page_upop_title")</title>
 
     <meta http-equiv="X-UA-Compatible" content="requiresActiveX=true"/>
 
     <meta name="keywords" content='#springMessage("page_upop_keywords")'/>
 
     <meta content='#springMessage("page_upop_description")' name="description"/>
 
</head>
 
<body oncontextmenu="return false" onselectstart="return false">
 
     #if($pageHead)
 
         #parse($pageHead)
 
     #end
 
     $screen_content
 
     #parse($page_footer)
 
</body>
 
</html>

  页面里咱们能够引入这个布局格式,这个布局文件其实就是页面里不变的东西抽取了出来,它完成了页面动静分离,页面只要应用这个布局文件便可,到了这里这个布局文件和前面的include方式区别不大,那么咱们再看看下面的代码:

1
<property name="layoutUrl" value="layout/default.vm"/><!--指定layout文件-->

  这是布局文件的引用方式,咱们能够把布局文件放置在网络上,项目里应用这个文件所在地址便可,这样咱们就把项目里不变的静态资源抽取在同一个地方,若是在碰到布局要作修改,那么咱们只须要改一个地方便可。

  无论服务端采起何种动静分离,动静资源的整合都是有服务端完成,按照上文提到网站静态化的思想,这些作法不会给网站性能提高带来任何好处,它们只是给 开发,运维提供了便利而已,按前文的思路,咱们要把动静分离往前移,服务端往前移碰到的第一个点就是静态的web服务器例如apache或ngnix。

  在讲解静态的web服务器动静分离前我要先讲一下为何咱们要在服务端前面加个静态web服务器的道理。我我的以为在每一个服务端以前都布置一个静态web服务器,该服务器起到一个反向代理的做用,并且我以为无论咱们是否使用CDN,最好都这么作,这么作有以下好处:

  好处一:方便日志的记录。

  好处二:在服务端以前设立了一个安全屏障,即静态web服务器能够在必要时候过滤有害的请求。

  好处三:能够控制流入到服务端的请求个数,当并发很高时候,能够利用静态web服务器能承担更高并发的能力来缓冲服务端的压力,这 里我补充一些实践技巧,以java里经常使用的web容器tomcat为例,通常官方给出它的最大并发数应该不会超过200,若是咱们在tomcat前放置了 一个apache服务器,那么咱们能够把tomcat的最大并发数设置为无效大,把并发数的控制放置在apache这边控制,这么作会给咱们系统运维带来 很大的好处,tomcat虽然有一个建议最大并发数,可是实际运行里java的web容器到底能承受多大并发其实要看具体场景了,所以咱们若是能够动态控 制apache的并发数,这个操做很方便的,那么咱们就能够动态的调整tomcat这样容器的承载能力。

  好处四:能够便于咱们作动静分离。

  这里咱们以apache为例子讲解将动静分离前移到apache的一些作法,apache有一个功能叫作SSI,英文全称是Server Side Include,页面上咱们通常这样使用SSI,SSI有一种标签,例如:

1
<!--#include file="info.htm"-->

  页面通常使用注释的方式引入,这个和jsp的 引入有点区别的,SSI的作法其实和服务端的引入相似,只不过使用SSI将原本服务端作的动静整合交由了apache完成了,咱们能够把静态文件直接放置 在Apache这里,若是这个静态web服务器上升到CDN,那么这些静态资源就能够在靠近用户的地方使用,SSI说白了就是像apache这样的静态资 源服务器接收到服务端返回后,将一部份内容插入到页面了,而后将完整页面返回至浏览器。这个作法若是优化的得当,能够很好的提高网站的加载效率。

  Apache这样的静态资源服务器还支持一种动静整合的技术,这个技术就是ESi,它的英文全称叫作Edge Side Includes,它和SSI功能相似,它的用法以下所示:

1
<esi:include src="test.vm.esi?id=100" max-age="45"/>

  它和SSI区别,使用esi标签获取的资源来自于缓存服务器,它和SSI相比有明显的性能优点,其实网页特别是一个复杂的网页咱们作了动静分离后静态 的资源自己还能够拆分,有的部分缓存的时间会长点,有点会短点,其实网页里某些动态内容自己在必定时间里有些资源也是不会发生变化的,那么这些内容咱们可 以将其存入到缓存服务器上,这些缓存服务器能够根据页esi传来的命令将各个不一样的缓存内容整合在一块儿,由此咱们能够发现使用esi咱们会享受以下优势:

  优势一:静态资源会存放在缓存里,那么获取静态资源的效率会更高。

  优势二:根据静态资源的时效性,咱们能够对不一样的静态资源设置不一样的缓存策略,这就增长了动静分离方案的灵活性。

  优势三:缓存的文件的合并交由缓存服务器完成,这样就减小了web服务器自己抓取文件的开销,从而达到提高web服务器的并发处理能力,从而达到提高网站访问效率的目的。

  (友情提示:ESI这块我还了解的不太深刻,据说它其实能够直接使用在jboss上,相关知识我还要继续收集资料学习)

  SSI和ESI是静态web服务器处理动静资源整合的手段,那么咱们再把动静整合操做往前移,这个时候就到了浏览器端了。浏览器端的动静整合的技术称之为CSI,英文全称叫作Client Side Includes,这个技术就是时下javascriptMVC、 MVVM以及MVP技术采起的手段,实现CSI通常是采用异步请求的方式进行,在ajax技术还没出现的年代咱们通常采起iframe的方式,不过使用 CSI技术页面加载就会被人为分红两次,一次是加载静态资源,等静态资源加载完毕,启动异步请求加载动态资源,这么一作的确会发生有朋友提到的一种加载延 迟的问题,这个延迟咱们能够使用适当的策略来解决的,关于CSI的使用是本系列的重点,我会在后面文章里重点讲解。

 

网站静态化处理—动静分离策略(3)

前文里我讲到了网站静态化的关键点是动静分离,动静分离是让动态网站里的动态网页根据必定规则把不变的资源和常常变的资源区分开来,动静资源作好了拆分之后,咱们就能够根据静态资源的特色将其作缓存操做,这就是网站静态化处理的核心思路。因而可知,网站静态化处理的核心就是动静分离和缓存两大方面,上篇我简单讲述了动静整合的基础知识,本篇将会讲述两大核心之一的动静分离策略,只有把动静分离策略作好了,缓存才能发挥出它应有的效果。

 

  下面咱们要讨论下动静分离的策略了,一个页面什么内容是动态的,什么内容是静态的,这个咱们到底该如何来区分了?这个问题学问很是大,咱们的标准不 同,最后拆分出来的动静资源就会存在很大的不一样。在本系列开篇里,我提到了什么样的页面是静态页面,什么样的页面是动态页面,我是以一个url的角度定义 的,每一个独立的页面都会有一个url,这个url就比如这个页面的门牌号,咱们每次访问这个url时候若是获得的响应页面都是同样的那么咱们就认为该页面 是静态页面,若是访问某个url,咱们访问的时间不一样,最后展现的页面也不同那么这个页面就是动态页面,动态页面就是咱们要进行动静分离的载体了,咱们 能够看到个人定义实际上是和时间相关的,也就是说访问时间不一样,获得的结果会不一致,因此咱们能够根据时间这个维度分析页面里那些内容是静态的,那些是动 态,可是这个划分在实际状况里就会变得很是复杂,下面我就讲讲这个复杂度。

  场景一:假如咱们是一个商户,咱们查询本身网店的交易数据,通常这个交易数据咱们会放置在页面的右下部分,这个部分咱们很天然把它当作动态资源,就算咱们的网店交易量很小,咱们也不敢把这个部分当作静态资源处理。

  场景二:咱们网站为了给用户一个友好的体验,会在用户登陆网站后在页面某个地方显示欢迎语,例如:上午好,夏天 的森林,欢迎使用咱们的网站!,到了下午,这个欢迎语可能就变成了下午好,夏天的森林,欢迎使用咱们的网站!,那么这块内容咱们应该是当作静态内容仍是动 态内容呢?这个就须要思考了。

  场景三网站页 面里会有不少图片,有些图片的确是好久好久都不会发生变化,例如网站的图标,可是有的图片却不一样了,例若有一个星期咱们要为某个商户作营销活动,那么营销 图片这块更新后就会有一个星期的有效期,复杂点的话,咱们可能会在营销活动期间在页面的某一块专设给这个商户营销活动的内容区,这个内容区使用一个 html片断,可是当营销活动结束了,这个营销的图片可能就要发生变化,营销的内容区可能会被去掉,那么这些东西咱们是当作静态内容仍是动态内容处理了?

  由上面的场景咱们能够知道,这个动静分离是要讲究策略的,若是策略设计的很差,可能咱们把网站静态化处理后,效果并无达到咱们的预期。其实,我认为 动静分离除了以时间维度考虑外,还应该有个维度,就是被拆分的资源是否须要服务端应用加以配合,例如像交易查询这样的动态内容,咱们其实须要服务端程序按 照必定的业务逻辑处理请求后从存储层 获取数据,那么这种动态资源是无法作静态化处理的,还有一部分资源例如场景三里的图片以及营销的html片断,这些资源写好后在有效时间内是不会发生变化 的,那么这块内容虽然时效性可能会有差别,可是它倒是能够在这段时间作静态化处理的,还有种情形就是场景二了,这个场景虽然使用数据须要服务端参入计算, 可是计算结果在必定时间范围内是不变的,也就是说结果是能够被缓存的,那么这块的资源也是能够当作静态化资源进行处理的,为何说拆分策略要考虑服务端应 用的因素了?由于上面这些场景都是由服务端应用参入的形式所决定,在有效时间里服务端应用不须要参入,或者参入一次后,能够长期保存结果,那么咱们能够把 这些资源当作静态资源处理。

  除此以外,服务端应用和结果的密切度也是要当作考虑的因素的。在web开发里,除了须要浏览器处理的,其余技术均可以当作服务端来理解,若是咱们网站使 用到了CDN,使用到了静态web服务器例如apache,以及服务端的web容器例如jboss,那么按请求的行进路径,咱们结果处理越早那么网站响应 效率也就越高,因此当请求在CDN返回了,那么确定比在apache返回效率高,在apache就返回了确定比jboss返回的效率高,再则服务端的 web容器自己由于服务端程序运行要消耗部分系统资源,因此它在处理请求的效率会比CDN和apache差不少,因此当咱们按照动静分离策略拆分出了静态 资源后,这个资源能不放在最底层的服务端的web容器处理就不要放在服务端的web容器里处理。

  由上所述,咱们再回过头来看看静态web服务器的SSI技术,这个技术使用起来和咱们在服务端使用include相似,可是在SSI使用include必定会比在服务端效率高,由于服务端在整合动静资源时候还会掺杂不少服务端程序处理,所以动静资源的效率就会大打折扣。咱们再看看SSI的include的用法,以下所示:

<!--#include file="info.htm"-->

  这个写法是使用页面的注释标签, 当静态web容器处理请求时候,它会扫描里面的SSI标签,接着就会处理这个标签的内容,若是找到了资源那么web容器会将资源插入到页面里,若是web 没有处理这个SSI标签,那么等结果到了浏览器,这个也就是一个注释而已,不会影响页面的展现,并且SSI标签处理的资源也是很是丰富的,无论这个资源是 静态的,仍是动态的,只要获取时候是个完整的资源都能被正常加入到页面里,因此像前面的场景二这种动态的内容也是能够正常处理的。所以场景二,场景三这样 的状况均可以使用SSI来解决。SSI的做用固然不只仅只是能够作include操做,它的标签也能够作一些逻辑上的操做,讲述如何使用SSI不是本文的 重点,有兴趣的朋友能够去研究下。

  不过SSI也有本身的局限性,它的第一个局限就是SSI解析是静态web容器来完成,所以它会消耗web容器的性能,若是SSI使用时候还有必定的逻辑,那么这种性能消耗就会更大,其实我以为更加剧要的是若是静态web容器过渡使用SSI,那么就会把本身变成了一个服务端的web容器,除了会影响到请求处理的效率,它还会下降自身的并发处理能力,因此咱们但愿资源整合策略交给外部服务处理效果会更好些,如是有些大型互联网公司使用ESI技术,ESI技术和缓存关系密切,这个内容我就放到下篇讨论了。

  本篇最后我要再讲讲CDN的问题,上篇我讲到静态web容器整合动静资源的好处,由此我说若是CDN能够作动静整合,那么就能作到就近处理,这样效果 会更高,今天我对这个作法作了一些考证,以为该说法有点不妥,至少我如今的公司没有使用到这样的技术,CDN技术应该由三个步骤组成,首先是解析DNS, 找到离用户最近的CDN服务器,接下来CDN要作一下负载均衡, 根据负载均衡策略将请求落地到最合适的一个服务器上,若是CDN服务器上就有用户所须要的静态资源,那么这个资源就会直接返回给浏览器,若是没有CDN服 务器会请求远端的服务器,拉取资源再把资源返回给浏览器,如此同时拉取的资源也被缓存在CDN服务器上,下次访问就不须要在请求远端的服务器了,CDN存储资 源的方式使用的是缓存,这个缓存的载体是和apache,nginx相似的服务器,咱们通常称之为http加速器,之因此成为http加速器是为了和传统 静态web服务器区别开来,传统的静态资源服务器通常都是从持久化设备上读取文件,而http加速器则是从内存里读取,不过具体存储的计算模型会根据硬件 特色作优化使得资源读取的效率更高,常见的http加速器有varnish,squid。Ngnix加上缓存模块也是能够当作http加速器使用的,无论 使用什么技术CDN的服务器基本都是作一个就近的缓存操做,这也就是说CDN是否能够完成SSI操做是值得商榷的,因此前文的说法仍是有点问题的。

来源:夏天的森林

 

网站静态化处理—缓存(4)

 

上篇我补充了下SSI的知识,SSI是一个十分常见的技术,记得多年前我看到不少门户网站页面的后缀是.shtml,那么这就说明不少门户网站都曾经使用过SSI技术,其实如今搜狐网站也还在用shtml,以下图所示:

 

 

  因而可知SSI在互联网的应用仍是很是普遍的。其实互联网不少网页若是咱们按照动静分离策略拆分,绝大部分都是能够当作静态资源处理,例如新闻网站, 文学网站,这些网页生成后,大部分的资源都是不变的,说白了这些网页本质就是一个静态页面,咱们开发他们时候也不须要服务端的参入,每个网站都有本身固 定的板式,假如每一个新网页都要完完整整的开发,重复性的工做实在太多了,出错的几率也很是高,在本系列第二篇里我曾经详细介绍了velocity的布局模 板技术,其实SSI也能够制做出一套固定的模板,开发时候咱们只须要在定义好的模板里添加或者修改咱们须要更改的内容就能够完成一个页面的制做,可见 SSI技术为了咱们开发网页提供了很大的便利。

 

  与SSI相对应的还有ESI,这个技术不是太经常使用,在网上能收集到的资料也不是太多,网上有限的资料也基本都是和淘宝相关的,不过仔细研究下淘宝对ESI的运用,对于理解网站静态化处理是很是有借鉴意义的,下面我将重点讲讲ESI的知识。首先看个场景啊。

 

  咱们登陆支付宝网站,到了我的首页咱们发如今支付宝下面有一个条目,以下图所示:

 

 

  这是支付宝默认给咱们显示的【生活好助手】,右边有个箭头,咱们点开它,以下图所示:

 

 

  咱们看到这里有添加的按钮,经过添加按钮,咱们能够添加其余经常使用的组件图标。(注意:我这里只是以支付宝这个功能为例,支付宝是否按照我说的设计,这个我就不清楚了)

 

  若是咱们按照本身个性化添加了本身的组件,不一样的人添加的经常使用组件也会是不尽相同的,若是咱们本身开发的网站也有这样的功能,那么咱们该如何设计了? 咱们通常都会很直观的把这个新增的组件信息存储在数据库里,用户每次登陆时候该信息也会随之从数据库里读取,可是这个场景对于像支付宝这种用户量极大,日 均访问量极高的大型网站,这种个性化又非核心的功能都从数据库里读取,那么它对数据库形成的压力必定是十分巨大的,在存储的瓶颈里咱们讲了那么多优化数据 库的手段,其核心手段有一个就是减小对数据库价值不高的操做,而这种个性化配置跟支付宝的支付操做相比起来,价值度实在过低,所以咱们最好的选择是避免数 据库承担过多此类的操做。

 

  不过像上面这个场景里的功能,它所使用的数据又不是那种无关紧要的,假如数据存储的不可靠形成数据丢失仍是会形成没必要要的麻烦,因此咱们仍是会把这些 信息作持久化存储。此外像上面的【生活好助手】条目仍是页面的一个重要组成部分,所以像SSI那种使用html注释指令,当指令没法正常解析,就直接返回 到浏览器,由于是注释,因此页面也不会显示它,SSI的这种作法用在上面场景确定是不太合适的。这样的场景在电商网站里是十分常见的,例如一个商品页面, 页面里会有商品的图片,还有商品的详细介绍,这些内容其实都是会用持久化系统进行存储,同时它们自己也是网页的重要作成部分,若是碰到问题就忽略最终会造 成页面显示错误。

 

  结合上面的场景咱们来讨论下ESI技术了,ESI技术和SSI技术相似,其实也和jsp里的include指令相似,它也是在页面里使用一个指令标签 web容器解析这个标签后将获取的数据替换掉这个标签。咱们来看看ESI的使用方法,咱们能够在velocity里自定义一个esi标 签,velocity里的使用以下所示:

 

esiTool.setTemplate('test.vm').addQueryData('id', 100)

 

  velocity引擎解析vm模板,最终会把vm解析成html页面,这个时候该页面里使用esi标签的地方就被转化为:

 

<esi:include src="test.vm.esi?id=100" />

 

  当页面到了服务端web容器以前的静态web容器(该web容器要安装好解析esi的模块),静态web容器就会解析这个esi标签,静态web容器 会以test.vm.esi?id=100 做为key,到缓存系统里查找信息,若是查到了信息,缓存服务器就直接返回,用返回内容替换掉esi标签,若是缓存里没有找到则会直接请求持久化系统,持 久化系统返回信息后,缓存系统将信息缓存起来,同时也将信息返回至静态web容器,那么下次用户再访问一样内容就会直接从缓存里读取了。

 

  ESI技术和SSI很像,只不过ESI技术是和缓存技术配合起来的,同时ESI标签也不像SSI标签那样使用注释的形式,所以ESI标签是必定要被解 析的,若是仅仅是缓存,ESI和SSI比较起来也没显得那么有优点和特别,可是对于电商这种场景而言ESI的现实意义很是大,电商网站也是一个由用户产生 内容的网站,每个商家的店铺虽然咱们都知道它是属于淘宝或天猫的,可是单独一个商家的店铺都是个性化很强的,与其余店铺差别很大,为了买卖商品,商家会 上传本身商品的图片,还会使用图片和文字描述本身的商品,单个商品页面咱们作动静分离分析,很容易分辨出动态内容和静态内容,可是若是一个电商平台拥有超 乎想象数量的商家,那么每一个页面的图片,文字和商家页面的关系就会变得有点微妙了。因为电商网站的图片特别多,那么电商网站系统通常都会设计一套管理这些 小图片的分布式存储系统,例如淘宝的TFS文件系统,它是专门针对图片使用的分布式文件系统,这些文件系统里存储的图片会和商家紧密关联,这就让图片自己 拥有了必定的动态属性,可是对于每一个商家页面而言,商家本身的图片资源都是能够静态化的,也就是说图片的读取是要经过商家信息进行计算的,计算出的结果对 于商家而言又是静态的,能够被缓存的。可是这个静态资源的处理时候就变得复杂了,而这些是SSI没法完成的。

 

  首先咱们直接从文件系统读取图片,效率是很是低效,所以咱们仍是会把它们缓存在内存里,可是因为不一样图片和不一样商户是相关联,那么对于缓存查找时候是 须要必定的条件,不一样商户对本身页面的设计方案也会有所不一样,通常商户这些资源,存储系统确定会按照设计模板的维度存储,不一样商家因为商品和文化的不一 样,那么使用的模板也不同,所以资源返回静态web容器前还须要一个整合过程,这样场景下的静态资源获取实际上是须要必定逻辑计算的,那么这个计算通常都 会在开发时候由代码完成,因此从上面ESI使用的例子看到,开发人员会使用velocity的esi标签,这个标签开发人员能够设置参 数,velocity引擎最终会将这个标签解析成静态web容器能够解析的esi标签,标签里有这样的代码test.vm.esi?id=100,文件后 面会带上参数,那么这个参数实际上是动态的,那么这个参数也就是缓存系统获取正确信息的规则了。这样咱们就完成了静态资源获取的逻辑计算,计算完毕后这些资 源会在一段时间里长期有效,所以它就演变为静态资源,能够被缓存了。ESI比SSI强大多了,同时ESI也能够完成SSI的功能,因此使用了ESI也就没 必要用SSI了。

 

  像咱们平时作web开发时候可能没有太留心一个问题,通常的web开发里使用的静态资源例如图片,css文件,js文件咱们都会放置在一个 resource包里,若是是企业开发,这个web应用上线时候也就直接打包在web工程里,一些互联网网站也只不过会将这些资源放置在单独的静态服务器 上,我平时开发时常听到有人说,项目里图片太多了,应该合并下,css文件和js文件也太多了也要合并下,这个多到底多多少了,几十个文件,几百个文件, 这个要和社交网站,电商网站这种用户能够产生图片的网站比起来那就是小巫见大巫了,由于用户能产生内容的网站静态资源会随着时间推移文件规模变得异乎寻常 的大,因此此类网站的静态资源已经无法放置在项目下,它就要求咱们须要有新的手段管理这些静态资源,而且有新的手段使用这些静态资源,那么像TFS文件存 储系统出现了,缓存技术出现了,最后咱们在应用里使用ESI技术把它们整合到咱们网页里,经过这个分析咱们就能明白ESI适用的业务场景了。

 

  网站静态化处理咱们首先要按规则拆分动静资源,拆分出来的静态资源该如何处理就是网站静态化处理的关键所在,把静态资源处理从服务端的web应用里剥 离出来,不让服务端的web应用参入过多的静态资源解析,这样就能够为服务端的web应用减小没必要要的处理操做,从而达到提高服务端web应用的运行效 率,接着咱们就把拆分出来的静态资源处理操做往前推移到静态web服务器,前两篇文章和今天的文章我着重讲解了静态web服务器处理静态资源的手段,那么 这里有个问题了,这些处理能够再往前推到浏览器来完成吗?答案固然是否认的,首先浏览器的缓存是很是不可靠的,若是用户把浏览器设置为不缓存任何数据的模 式,那么浏览器就无法缓存数据了,而用户的行为那是根本无法控制的,其次浏览器缓存的数据量是有限的,若是咱们要在浏览器进行缓存也是缓存最有价值缓存的 数据,更重要的一点,为了作好网站静态化处理咱们对网页的动静资源作了拆分,可是拆分出的静态资源也并非彻底不须要进行任何逻辑处理就能使用的,例如前 面讲到的ESI适用的场景咱们就发现,有些静态资源的获取仍是要不少条件的参入,而这些条件是由动态数据产生的,那么这样的静态数据浏览器是无法作缓存 的,这点也说明了拆分出来的静态化资源绝大部分仍是要停留在服务端的,竟然只能停留在服务端,那么最为高效的处理这些静态资源的地方就是CDN和静态 web容器了。因此在本系列的第一篇里我讲到网站生产部署时候最好是在服务端web应用以前放置一个静态web容器,若是有了这样的静态web容器作反向 代理,那么咱们就可让它来完成静态资源的相关操做,并且静态web容器还能辅助完成一些逻辑上的处理,从而弥补了CDN的不足之处。固然这么作的好处不 仅仅只有这些,第二篇文章里我曾经讨论了反向代理的好处,可能你们印象还不是很深入,我将会在后面文章里对反向代理作更加深刻的分析。

 

  讲完了ESI的妙用后,我下面将讲讲本篇的主题缓存了。其实单独讲缓存真的没啥太多内容,不过在网站静态化处理里的缓存仍是和存储里讲到的分布式缓存 有所不一样,分布式缓存的数据都是存储在内存里,而网站静态处理的缓存既有存储在内存里还有存储在硬盘上,固然存储在内存里读取速度会更快,可是网站的读取 效率还和资源距离用户的远近有关系,例如浏览器的缓存实际上是把静态内容缓存在硬盘上,可是由于不须要经过网络获取资源,所以它的读取效率就显得特别高了, 除了这个因素外还有个因素,咱们前面作动静拆分的目的就是想拆分出静态资源,让这些静态资源远离服务端的web应用,这样能够减小服务端没必要要的压力,从 而达到提高服务端web应用处理能力,而把静态资源放置在静态web容器处理,它的处理静态资源效率又会高于在服务端web应用的处理,从而也达到提高静 态资源读取的效率。不过若是静态资源最终只能放置在服务端,那么这个时候咱们把静态资源存入到缓存里即内存里效率确定比在硬盘上高,因此CDN的服务节点 通常都是采起将静态资源存储在内存里,就算是服务端web应用前的静态web容器,若是咱们让静态资源缓存在内存里,效率确定也是比在硬盘上高。

 

 

网站静态化处理—CSI(5)

讲完了SSI,ESI,下面就要讲讲CSI了 ,CSI是浏览器端的动静整合方案,当我文章发表后有朋友就问我,CSI技术是否是就是经过ajax来加载数据啊,我当时的回答只是说你的理解有点片面,那么到底什么是CSI技术了?这个其实要和动静资源整合的角度来定义。

  CSI技术实际上是在页面进行动静分离后,将页面加载分为两个步骤完成,第一步是加载静态资源,静态资源加载完毕后进行第二步骤加载动态资源。不 过这个定义仍是表述的不全面,不全面的地方就是咱们要强调动静分离的目的,咱们把页面里的动静资源拆分出来是为了将静态资源作有效的缓存,这个静态资源可 能是在静态web容器上,也有多是在CDN上,也有多是在浏览器上,无论静态资源是如何缓存的,咱们的目的都是为了让静态资源加载的速度更快,若是我 们没有让静态资源加载变得高效,就算咱们使用了CSI的形式来设计页面,其实也没有发挥CSI的优势,反倒还会一不当心引入CSI的缺点。那什么是CSI 的缺点呢?具体以下:

  CSI的缺点一:CSI不利于页面的SEO即搜索引擎优化。搜索引擎的网络爬虫通常是根据url访问页面,获取 页面的内容后去掉没用的信息例如:css样式,js脚本,而后分析剩下的文本内容,所以假如页面的一部份内容须要进行异步加载,那么这个加载控制确定是由 javascript代码来完成的,所以网络爬虫爬下来的页面里异步加载的操做是无法执行的(据说有些高级的爬虫能够执行异步的操做,抓取异步的内容,即 便有这个技术,大部分主流的爬虫仍是会忽略掉javascript代码的也会忽略异步加载的内容的),这就会致使爬虫爬的页面里有部分信息丢失了,因此说 CSI对SEO不太友好。不过这个缺点咱们仔细分析下,可能并不会是那么严重,前面咱们谈论了不少静态分离的策略,若是咱们动静分离策略作的好,那么动态 资源基本都是不能被缓存的内容,常常发生变化的内容,这些变化的内容原本就不须要被网络爬虫爬到,就算真的被爬到,搜索引擎有个查询结果指向了这个页面, 咱们点开这个页面结果也是在页面找不到被搜索的关键字,这种情形我相信不少朋友在使用搜索引擎时候都会碰到过。不过我想若是开发人员没有正确使用CSI, 那么这块他们可能也不会处理的特别好,所以这个缺点仍是很容易被引入的。

  CSI的缺点二:咱们那么费时费力想让本身的网站静态化,目的就是想让页面加载更快点,咱们简简单单把页面加载 分红了两个步骤进行,那么这么作就真的快吗?这可不必定啊,其实动静分离的作法和我上一个系列里讲到的数据库读写分离有相似之处,数据库读写分离咱们是通 过拆分原表的读写之间的关联关系,从而达到解决读的瓶颈问题,而网页的动静分离是由于静态资源很容易被优化,因此咱们要拆分动静资源。因此当咱们对资源进 行了动静分离,可是又没有优化静态资源,这个一看就知道咱们缺乏一个加速页面加载速度的操做,那么真的能让页面加载快点,还真的很难说了,并且异步加载需 要执行javascript代码才行,可是静态资源加载时候很容易形成javascript脚本被阻塞,若是阻塞的脚本正好是异步加载的部分,结果只会是 比之前加载的更慢了。

  因而可知,我在前面讲到的SSI和ESI技术对于咱们在浏览器端发挥CSI技术优势是很是有必要的,SSI和ESI作好了能让动静分离出的静态资源加 载的更加高效,这也就让CSI操做的第一个步骤变得高效,第一个步骤处理好了咱们只要在页面控制好脚本阻塞对异步加载的影响,那么咱们就能够达到提高整个 页面加载效率的目的了。此外我以为CSI对SEO有重大影响是个伪命题,假如使用CSI形成了SEO效果不佳,那么确定是咱们CSI方案设计的不到位。

  有人认为CSI还会有个缺点,不过笔者我并不认为这是一个缺点,这实际上是一个设计问题,好与坏是根据我的的操做习惯所决定的。这个别人认为的缺点是什 么呢?它就是使用CSI技术时候,虽然页面很快的被加载出来了,可是动态内容那部分可能会显示一个正在加载的提示,那么这就致使页面用户友好性下降,其实 这种同步和异步加载混搭操做实在太常见了,几乎全部大型门户网站,电商网站还有一大堆数不尽的网站都是采用同步和异步混搭的加载方式,假如这些网站不这么 作,我相信这些网站例如首页加载必定会慢的让人吐血,由于它们不少网页里面内容实在太多,图片也都有点爆棚了,因此它们不得不使用同步和异步混搭的加载方 式,甚至不少静态资源例如图片,flash这些东西也会采起异步加载方式。说到这里,估计有人仍是以为不服气,他就是不喜欢页面加载时候还要出现个正在加 载提示,可是网页里又很是须要CSI带来的好处,那么咱们该如何解决这个问题呢?这个问题很好解决,首先愿意使用CSI技术也就说明用户仍是很愿意使用异 步的加载技术的,不喜欢则是正在加载的提示,这说明用户想要在作同步加载操做时候不要掺杂异步操做,虽然如今ajax技术大行其道,可是ajax技术有个 同步加载是没有办法解决的,那就是咱们在浏览器地址栏里输入网站url请求页面 ,因此面对上面的需求咱们只要保证这种同步操做只是一个纯粹的同步操做而不要掺杂异步加载便可,这个方案仍是很好实施的,这里我就再也不累述了。

  动静分离后咱们会把静态资源进行缓存,前面文章里讲了一大堆都是在讲服务端的静态资源缓存,如今讲到了CSI已经到了浏览器端,那么咱们就得谈谈浏览 器的缓存操做。页面的缓存操做就是使用http的expires和cache-control,咱们首先看看下面的写法:

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">

  这是我如今作的java的web项目里,jsp和vm文件都会使用的meta配置,它的目的就是让页面不要被浏览器缓存,可是若是使用CSI技术,同 时动静分离作的很好,那么在页面头部其实咱们能够再也不这么写了,咱们可让页面在合理的时间范围内被浏览器缓存,若是该页面作了缓存操做,那么之后咱们再 访问该页面,网页的加载效率就会变得更高了。

  这里还有个问题,在雅虎优化网站的建议里,为了充分利用网页并行加载的特色,咱们每每会把图片,外部的js和css文件放置在单独的静态web容器或 CDN上,那么这些文件每每也是能够被浏览器缓存,这个咱们又如何设置才能让浏览器知道要缓存它们呢?这里咱们以apache为例,为了让静态资源被浏览 器缓存,apache须要使用mod_expires模块,而后在apache的配置文件里添加以下配置:

<FilesMatch "\.(gif|jpg|png|js|css">ExpiresDefault "access plus 10 years"</FilesMatch>

  那么浏览器访问此apache上的静态资源后,浏览器就会把图片和该服务器上的js和css文件缓存在浏览器里。

  咱们看看被缓存的静态资源是如何被使用的,以下图所示:

  当http的响应码是304的时候,那么浏览器就会从缓存里读取资源了,这里有的朋友可能会感到奇怪为何缓存的资源还要发送个http请求了?理解 这个咱们就要了解下缓存的机制,缓存的含义是临时保存某些东西,既然是临时保存,那么就应该有个保存的有效期,咱们定义缓存的方式是经过http完成的, 那么按道理检查缓存是否过时也应该是http来决定的,所以每次使用缓存时候咱们要发个请求到服务端,服务端会检查下资源是否过时了,若是没有过时,服务 端返回个304的响应码,304的返回响应是没有http报文体的,因此这个http请求的返回数据是很是小的,所以这个http效率仍是很高的,若是服 务端发现资源过时了那么服务端就会把新资源返回给浏览器了,其实这个检测资源是否过时的请求有个专有名词叫作条件Get请求。 至于服务端是如何完成检查操做,本系列在讲web前端优化时候会详细阐述,这里就不深刻了。看到这里估计有朋友又有疑问了,为何缓存是否过时不能在浏览 器端来作了?这主要是浏览器作这个检查很是不许,由于用户的电脑时钟不必定准确,或者用户电脑时钟和服务端不一致,若是再加上时区那么就更加麻烦了,因此 缓存失效最好是在服务端进行,这样缓存的有效期的准确性才能获得保证。html5的出现,浏览器缓存的能力大大加强了,不过使用html5技术进行缓存我 尚未深刻研究过,因此这里也不讲述了,有兴趣的朋友能够本身研究下。

  好了,CSI主题内容讲完了,讲到CSI技术和浏览器咱们就能够开始本系列另外一个重要内容先后端分离了,这将是我下篇的主题,我在本身博客里屡次讲到先后端分离,立刻又要再次讲了,此次讲是我这么长时间作先后端分离研究的大总结了。

网站静态化处理—先后端分离—上(6)

前文讲到了CSI技术,这就说明网站静态化技术的讲述已经推动到了浏览器端了即真正到了web前端的范畴了,而时下web前端技术的前沿之一就是前 后端分离技术了,那么在这里网站静态化技术和先后端分离技术产生了交集,因此今天我将讨论下先后端分离技术,先后端分离技术讨论完后,下一篇文章我将会以 网站静态化技术的角度回过头来从新审视下先后端分离技术,但愿经过这种审视来加深咱们对两套技术的理解。

  先后端分离技术我我的认为是web前端被专业化之后的必由之路,而nodejs的出现是先后端分离技术的一个强兴的催化剂,缘由是nodejs的出现 削平了前端技术和服务端技术之间的鸿沟,使得先后端两套不一样技术体系进行真正意义的解耦提供了无限的可能性。可是若是咱们把nodejs技术的使用认为就 是实现了先后端分离,这种理解又实在太肤浅了,下面我将讲讲我研究过的先后端分离技术方案,以及这些技术方案隐藏在背后思考,但愿这些思考能给你们以一个 新的思路来理解先后端分离技术。

  咱们要深入理解先后端分离技术有一个重要的前提,那就是要把先后端分离技术认为是传统的web应用里的MVC设计模式的进一步演进。那么咱们首先来看看MVC的定义,下面的内容摘录于维基百科的解释,具体以下:

MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

MVC模式最先由Trygve Reenskaug在1978年提出[1] ,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式。MVC模式的目的是实现一种动态的程式设计,使后续对程序的修改和扩展简化,而且使程序某一部分的重复利用成为可能。除此以外,此模式经过对复杂度的简化,使程序结构更加直观。软件系统经过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员能够经过自身的专长分组:

(控制器 Controller)- 负责转发请求,对请求进行处理。

(视图 View) - 界面设计人员进行图形界面设计。

(模型 Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(能够实现具体的功能)。

  各种用于Web应用开发的语言里都有属于本身的MVC框架,例如本人最熟悉的服务端语言java里就有大名鼎鼎的struts2,springMVC 的MVC应用框架,我早期从事java的web开发时候认为这些MVC框架都是很是的博大精深,用途普遍,可是当我逐渐转向了web前端技术开发之后又觉 得这些框架的不少功能显得那么的多余和累赘,所以我曾写过一篇文章专门讨论过这些问题,该文章的名字叫作《为何作java的web开发咱们会使用struts2,springMVC和spring这样的框架?》。

  其实这篇文章被写的源头就是在于我认为像struts2和springMVC这样的框架作了太多浏览器自己就能够完成的工做,例如:页面的渲染操做, 由于服务端抢了浏览器端的部分工做,这其实也就等于限制了web前端技术的深刻运用,像不少前端的优化技术以及不少提高用户体验的技术就很难派上用场,之 因此产生这些问题,我认为传统的MVC框架本质实际上是一个服务端的MVC框架,虽然MVC设计模式里的V即View视图层是想把界面开发工做专业化,让界面设计人员能专心于界面开发,可是传统的MVC框架下的View层的本质倒是一个彻彻底底的服务端技术。

  咱们以java的web开发里jsp为例,JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是java里动态网页的技术标准, 这就说明jsp虽然看起来像html,其实它并非真正的html,它须要被java的web容器进行解析转化为浏览器能够解析的html页面,而后经过 网络传输到浏览器后,浏览器才能正确的展现这个jsp页面,其余web开发语言里都有相似的动态网页技术标准,可是无论什么语言的动态网页技术标准,咱们 使用它时候就是让web前端技术被服务端技术所绑架,这也就是为何每一个招聘web前端工程师的岗位都要问你是否会java,php语言的源头。可是随着 互联网的大发展,对web前端的要求是愈来愈专业化,web前端自己所包含的技术难度已经不亚于任何一个服务端语言开发难度,所以咱们须要web前端更高 的专业化,而不但愿web前端工程师被服务端技术束缚的更多而限制了自身能力的发展,这就致使先后端分离技术的出现。

  不过先后端分离技术的第一阶段倒不是从改变view层即视图层开始的,而是从链接客户端和服务端的C层即控制层开始的,控制层既要做用于客户端又要做 用于服务端,若是一个功能页面是一个程序员从浏览器端一直写到模型层,控制层也就不是什么问题了,可是若是当咱们想按MVC的设计思想,让界面开发人员专 注于页面开发,服务端开发人员专一于服务端开发,那么这个时候控制层的归属问题就显的很是重要了。在传统的MVC框架里,由于M层和C层是使用一样的语言 体系,所以咱们很天然会把M层和C层的开发工做都交由服务端开发人员完成,这个决定无可厚非,可是传统的MVC框架里V层和C层其本质也是同一个技术体系 下的(例如java的web开发里的jsp本质就是个servlet),所以V层和C层也是紧耦合的,所以界面开发人员开发页面时候如何没有C层支撑,那 么这个页面实际上是根本跑不起来的,若是前端开发人员这时候跑去写写C层即控制层的代码,这就打破了原有的横向分工,这个时候控制层的编码工做就会变得混乱 而难以控制,看到这里有人必定会说既然控制层是属于服务端的,那么前端技术人员就等等服务端的开发进度,再不行就本身写个mock模拟下服务端的控制层, 听到这种建议,我相信无论是前端的仍是服务端的技术人员都会头脑发麻,第一反应就是这不是自找麻烦啊,还不如一我的所有搞定算了。由此第一阶段的先后端分 离技术方案出现了,这个方案须要解决的问题就是如何能让web前端技术人员和web服务端技术人员协同起来工做,合理的分工,换句话说就是按web前端和 web服务端角度如何能横向的分解web的开发工做。

       先后端分离的第一阶段须要解决问题的核心就是控制层的归属问题,从技术角度而言就是控制层究竟是应该和视图层解耦比较合理仍是跟模型层解耦比较合理的问题。那么咱们这里先回顾下MVC设计模式里对控制层的定义,维基百科里的定义是:

(控制器 Controller)- 负责转发请求,对请求进行处理。

  不过这个解释我认为并不全面,以java的web开发里的控制层设计为例,咱们发现控制层以沟通视图层和模型层的角度而言,控制层其实主要完成三项具体的工做,它们分别是:

  工做一:控制层起到一个路由的做用。客户端请求到达控制层后,控制层根据请求内容将请求路由到服务端某个模型层进行处理,模型层将请求处理完毕后,会把响应结果返回给控制层,控制层在根据响应信息路由到特定的页面。

  工做二:控制层起到一个报文信息格式转化的做用。这里以java的web开发为例,浏览器的数据都是以http报文形式发送给服务端,而控制层就是将http报文信息解析成java的对象,固然也能够是java的基本数据类型,而后控制层把解析好的信息传递给模型层进行处理。

  工做三:传统的MVC框架里,控制层其实深刻参入到了页面渲染的操做。在java的web开发里的控制层无论如 何被包装,其本质就是一个servlet,而jsp页面本质也是个serlvet,所以咱们能够这么理解jsp,jsp就是以页面开发的方式写java, 而servlet就是以java的方式写页面,因此咱们能够在servlet里以文件流的方式输出页面,也可让servlet跳转到jsp页面。

  由上面的论述里咱们发现,其实传统MVC框架里控制层和模型层的联系方式相对很简单的,它们的联系主要是路由和报文格式的转化上,而控制层与视图层的 联系除此以外还多了一个页面渲染,而页面渲染自己应该是属于浏览器的技术范畴,是浏览器技术不可分割的一部分,也是我上面内容里诟病传统MVC框架问题所 在,若是控制层承担了页面渲染工做,那么控制层和视图层的耦合度就变得很是高,要想将其解耦是十分困难,通常只有咱们打破了现有MVC框架的技术体系才能 完成,相比之下,控制层与模型层的解耦就显得容易多了。那么控制层与模型层如何解耦呢?具体以下:

  首先咱们来解决下报文格式转化的问题,这个技术方案很简单就是借鉴http统一报文格式的特色,咱们为控制层和模型层定义一套统一的报文格式,例如我 们定义控制层和模型层都以map的数据类型进行数据传递,这个map里有个专门的字段用来定义被路由到的模型接口信息,有个字段专门存储须要传递的数据, 具体的设计方案能够根据实际的业务须要来设计。

  接下来就是路由的问题了,在解决报文格式转化问题的论述里我讲到要在统一报文格式里专门定义一个字段用来存储该数据到底路由到哪一个模型进行处理,不过 这个字段并不能彻底解决路由问题,所以咱们须要模型层对控制层提供一个统一的接口,任何控制层与模型层的沟通都经过这个统一接口来完成,只不过不一样请求报 文组装的内容不同而已,而这个接口还有个重要职责就是解析报文里的路由信息,让请求能被正确的路由到对应的模型接口所处理。固然这个接口的返回值最好也 是一个统一的报文格式,这样控制层解析模型层的返回数据也会便利的多了。

  由上所述,咱们发现第一阶段的先后端分离工做控制层应该归属于web前端,这么作更加合理,也更加容易实现,其实以后进化版的先后端分离方案,控制层也都是属于web前端,只不过形式不一样而已,这个我在下一篇文章里继续讨论。

  第一阶段先后端分离方案解决的核心就是让控制层和模型层解耦,这个方案进一步演化一下,咱们能够把控制层和视图层独立成一个web应用,模型层也独立成一个web应用,两个web应用之间经过远程调用方式进行沟通,这个方案我在之前文章里写过,这篇文章的名字叫作《我设计的网站的分布式架构》。

  这个进化版的方案增长了系统开发的难度,由于咱们须要增长网络通讯的编程以及远程调用的实现,更麻烦的是咱们还须要进行复杂的多线程编程,既然增长了 开发的难度为何我还要这么作呢?首先咱们经过应用分层,能够动态的调节web前端和web服务端的负载压力,还能够在模型层以前提供一道安全屏障,不过 被服务端绑架的web前端在提高整个web应用负载能力这块仍是颇有限的,其实这种作法的最大好处就是利于SOA框架的设计,也就是说这种架构咱们能够为 服务端的SOA化提供有力的保障,由于控制层和模型层的解耦,可让模型层真正作到专一于业务,而不会再发生那种把业务逻辑写到控制层的问题了从而下降代 码的健壮性。

 

网站静态化处理—先后端分离—中(7)

上篇里我讲到了一种先后端分离方案,这套方案放到服务端开发人员面前比放在web前端开发人员面前或许获得的掌声会更多,我想不少资深前端工程师看 到这样的技术方案可能会有种说不出来的矛盾心情,当个人工做逐渐走向愈来愈专业化的前端开发后,我就时常被这套先后端分离方案所困惑,最近我终于明白了这 个困惑的本源在哪里了,那就是这套先后端分离方案实际上是服务端驱动的先后端分离方案,它的实现手段又是从服务端的 MVC架构体系演化而来,所以该方案最大的问题就是它并无从根本上改变web前端从属于服务端的被动局面。那么问题来了,有没有以web前端为驱动的前 后端分离方案呢,该方案能让web前端的能力得到更大的释放了?答案是绝对有。本篇就要讲讲以web前端驱动的先后端分离方案。

  首先要提的就是javascriptMVC,下面我摘抄的是维基百科里对javascriptMVC的解释,具体以下:

  首先是简介:

JavaScriptMVC 是一套开放源代码的多样化互联网应用程序框架,以 jQuery 与 OpenAJAX 为基础。JavaScriptMVC 利用 MVC 架构与工具扩展这些函式库,以便开发与测试。因为 JavaScriptMVC 不须要任何服务器端的配合,所以它能够和任何的网站服务接口与编程语言整合,如 ASP.NET、Java、Perl、PHP、Python 或 Ruby。

  接下来是历史:

JavaScriptMVC 的第一个版本是在2008年5月释出。稳定版的 JavaScriptMVC 2.0 在2009年6月释出,并以 jQuery 为基础。主要开发目标为维持程式码的简短和专一在它独特的功能上。3.0版本在2010年12月释出。而从 JavaScriptMVC 中所独立出来的 MVC 架构“CanJS”则在2012年4月释出。

  从维基百科里的解释咱们会发现以下启示,它们分别以下:

  启示一:javascriptMVC是一个应用框架的名字,这和jQuery的命名是同样的,因此这里我要声明 一下,本系列里的javascriptMVC不是指代这个框架,而是指代的是使用javascript语言实现出的一类的web前端的MVC框架,本系列 后面的javascriptMVC和前端MVC的含义是一致的。

  启示二:从javascriptMVC历史里咱们能够看到初版的javascriptMVC产生于2008年,这个历史要远早于nodejs出现的时间,这说明了前端的MVC并非由于nodejs的出现而产生的,应该是nodejs推进了前端的MVC框架的应用和普及。

  启示三:维基百科里有一段解释:

因为 JavaScriptMVC 不须要任何服务器端的配合,所以它能够和任何的网站服务接口与编程语言整合,如 ASP.NET、Java、Perl、PHP、Python 或 Ruby。

  这段话说明了前端MVC的一个很重要的特色就是前端MVC能够摆脱服务端语言的束缚作到真正的独立,同时前端MVC又能够和任何服务端语言进行整合, 你们能够试想下若是咱们开发的web应用前端达到了前端MVC的程度,那么公司在招聘web前端工程师的时候就不在会问你“你会java吗?”或者“你会 php吗?”假如这个前端工程师所会的服务端语言能力和公司不匹配,面试官也不会再犹豫和摇头了。

  启示三同时还隐含了一个问题,为何好的前端MVC框架能够作到和任何服务端语言配合呢?这个解决手段之一我在前文中的第一阶段先后端分离方案里就提到了,那就是解决报文格式的统一和交互接口的统一的技术手段,只有这样前端MVC和服务端的灵活对接就不会再是问题了。可是仅仅这个手段仍是远远不够的,咱们要达到这个需求还须要解决一个问题,这个问题就是要把服务端MVC霸占web前端的工做也要抢回来。那如何抢呢?

  上篇文章里我分析过服务端MVC的视图层的问题,服务端MVC的视图层技术例如java里的jsp技术,这个技术是将html和java代码整合的技 术,java的web容器把jsp解析完毕后最终生成为html文件发送给浏览器,浏览器在解析这个html将最终效果展现给用户。那么咱们要抢回服务端 霸占的web前端的工做咱们就得分析下这些动态页面技术到底作了哪些事情特别是侵占web前端的事情。

  这里首先咱们要谈谈服务端在动态页面里的做用,其实服务端为动态页面做用很单一就是提供了网站须要展现的数据而已,服务端是不会创造一个新页面的。服 务端提供的数据的类型也是很统一,要不就是服务端语言提供的基本数据类型例如:字符、数字、日期等等,要不就是复杂点的数据类型例如数组、列表、键值对等 等,不过归属服务端的动态页面还须要服务端语言帮助作一件事情,那就是把服务端提供的数据整合到页面里,最终产生一个浏览器能够解析的html网页,这个 操做无非就是使用服务端语言能够构造文件的能力构建一个符合要求的html文件而已。不过一个页面里须要动态变化的每每只是其中一部分,因此作服务端的动 态页面开发时候咱们能够直接写html代码,这些html代码就等于在构造页面展现的模板而已,而模板的空白处则是使用服务端数据填充,所以在java的 web开发里视图层技术延生出了velocity,freemark这样的技术,咱们将其称之为模板语言的由来。

  因而可知,服务端MVC框架里抢夺的web前端的工做就是抢占了构建html模板的工做,那么咱们在设计web前端的MVC框架时候对于和服务端对接 这块只须要让服务端保持提供数据的特性便可。从这些论述里咱们发现了,其实前端MVC框架要解决的核心问题应该有这两个,它们分别是:

  核心问题一:让模板技术交由浏览器来作,让服务端只提供单纯的数据服务。

  核心问题二:模板技术交由浏览器来承担,那么页面的动态性体现也就是根据不一样的服务端数据进行页面部分刷新来完成的。

  而这两个核心问题解决办法那就是使用ajax技术,ajax技术天生就符合解决这些问题的技术手段了。

  要让web前端承担模板技术,就得使用javascript的模板技术,时下javascript的模板技术可谓是百花齐放,百家争鸣,不少朋友曾为 这些技术称奇,其实探求它的本源无非就是用javascript为基础实现了个jsp,velocity而已,若是有朋友还没接触过javascript 模板技术,能够在百度里搜索下【javascript模板引擎】,本文这里就不展开谈论了。

  前端的MVC讨论到这里又出现了一个新的疑问,我上面讲到解决前端MVC两大核心问题的手段是ajax技术,ajax是异步请求,那么这是否是就是说让网站所有使用异步请求咱们就能够实现前端MVC,而且解决网站全部的问题呢?

  这个问题的回答固然是不可能的。一个网站是永远无法摆脱与异步请求相对的同步请求,就算有个网站把异步作到了极致,可是它也没法摆脱用户第一次访问要 在浏览器地址栏填写网站入口页面url地址的同步请求问题,网站把异步操做作到极致也无非就是把网站作成了一个纯粹的单页面形式而已。

  纯粹单页面的网站不少人一听到就以为好牛逼啊,很前卫,很厉害,对前端有所了解的人还会想到单页面也就意味要运用更多的javascript编程和 DOM编程,前端代码难度也会大大加强,好的单页面应用若是这个应用还包含复杂的业务逻辑,那么单页面前端开发里极可能还会使用到现在很火爆的 javascript模块技术例如requirejs或者seajs技术,单页面听起来实在太完美了,可是咱们冷静下来思考下,单页面真的完美吗?下面我 要为单页面泼泼凉水了,具体以下:

  泼凉水一:单页面其实指的是网站只有一个入口,可是并不表明用户看到的网页就是一个样子的,单页面里也会有不少 页面切换,可是无论页面里的模样如何变化,浏览器地址栏的地址都不会变化,能作到这点就得归功ajax的超强能力了,单页面不一样模样的展现都是在 javascript代码里实现的,那么问题来了,单页面对于搜索引擎的网络爬虫就很是不友好了,由于网络爬虫是根据url抓取页面,抓取完毕后会忽略 javascript代码,那么单页面的设计方案就会致使SEO优化只能做用于首页,而网站其余页面将无非有效的被SEO技术进行优化。

  泼凉水二:一个网站作成单页面之后那么网站不一样的展现都在一个url下面,可是若是有些用户只是对网站的某一部 分功能很感兴趣,而这部分功能又不是被单页面的惟一同步请求所展现的首页里的内容,那么结果就是这些用户每次登录网站时候都要手动操做一下才能进入本身想 要的功能页面里,假如首页进入功能页面的操做步骤比较繁琐,那么这个必然会致使网站用户体验的降低。

  那么上面的问题该如何来破呢?

  这里我首先来说讲第二个问题的解决方案,第二个泼凉水的问题的核心就是要记录单页面的状态问题,这个状态能够帮助首页能快速切换到具体的功能页面,要 让客户端网页有状态最经常使用的手段就是cookie了,若是浏览器支持html5,那么保存状态的手段就更多,能力也更强了。可是这种手段是和客户端紧耦合 的,那么若是碰到这种状况,该手段就会出现问题了,例如若是有我的发现单页面网站里一个颇有趣的功能,这时候他正好和朋友QQ聊天,他告诉了他的朋友,他 的朋友也该兴趣,让他把连接发过来,那么这个朋友就不得不在从首页在重复操做一遍,因而可知,cookie的手段并无全面解决这个问题,那咱们还有其余 手段嘛?

  答案是还真有,那就是使用html的锚连接,锚连接的形式以下所示:

http://www.baidu.com/#sharpxiajun

  下面是我摘抄下百度百科对锚连接的解释:

锚连接实际上就是连接文本,又叫锚文本。能够理解为:带有文本的超连接,就叫锚连接。锚文本能够做为文本连接所在的页面的内容的评估。

通常的来说,网站页面中增长的锚连接都和页面自己的内容有必定的必然联系。网站建设的行业网站上会增长一些同行网站的连接或者一些作网站建设的知名设计网站的连接;

另外一方面,锚文本能做为对所指向页面的评估。锚文本能精确的描述所指向页面的内容,我的网站上增长Google的连接,锚文本为 “搜索引擎”。这样经过锚文本自己就能知道,Google是搜索引擎。

  那么在单页面里的功能切换时候咱们改变一下url上的锚文字,反过来讲使用锚文字作路由器,让其能够路由到对应的功能页面那么上面的问题不就能够解决 了。关于锚连接我这里要补充一些知识,首先锚连接的形式是url#文字,锚的起始标记是#号,这个#号的内容实际上是属于浏览器端的,也就是说#包括#号后 面的内容是不会被发送到服务端的,那么咱们想改变锚连接只能在客户端进行,可是传统的锚连接的变化是很难被javascript语言监控到的,直到 html5的出现才从根本上解决了这个问题,html5提供了hashchange事件,该事件能够监控锚连接的变化,由于javascript语言能够 监控锚连接的变化,那么使用锚连接路由功能页面就成为了可能,那么低版本的浏览器该怎么办了?这个主要是ie的问题了,其实ie8包括ie8都支持 hashchange事件,再低就不行了,不过jQuery有个插件可让低版本的ie支持hashchange事件,有兴趣的童鞋能够百度下啊。

  看来泼凉水二问题是有解的,那么泼凉水一怎么解决了?个人回答是基本无解,这个问题的关键在网络爬虫这边,若是咱们被动解决这个问题,那只能是抛弃 javascript了,这个玩笑就开大了,因此咱们只好祈求各大搜索引擎能不能智能化再厉害点了。这里加个题外话,我最近几天忽然意识到一个问题,那就 是讲到web前端技术我必定要增强对SEO的思考,由于绝大多数网站都会把搜素引擎当作入口的生命线,这是一个很难回避的问题,无论咱们网站作的如何优 秀,假如用户很难找到它,那一切都将会是百搭,而在前端设计里要加入SEO的思考,这必然会致使整个架构的重大变化。这个问题我会在以网站静态化角度审视 先后端分离方案时候重点讲下。

  前端MVC讨论到这里咱们会发现咱们的谈论里缺了一环那就是MVC的M层模型层,web前端要侵入到模型层了,这不就等于web前端要造反了,它不只 仅想改变从属服务端的悲惨命运,还要抢夺服务端的部分功能,让服务端成为浏览器对应的存储系统,这不是无异于虎口夺食,在时下服务端如此强势的大环境下, 这种想法简直就是活得不耐烦了,哈哈,固然这是戏言了,作技术作工程仍是要讲求个合理性和逻辑性的,技术和工程都是实在的东西很讲道理的,只要道理站得住 脚怎么个作法都是其次,回到问题自己,我我的以为在PC端讨论web前端作模型层其实每每利大于弊,就安全而言,模型层意味有大量业务逻辑推移到web前 端,那么安全的保障难度会加大,就技术难度而言,web前端作模型层会让javascript编程巨复杂,因此要作这个抉择时候必定要结合业务作仔细的权 衡,其实我如今接触的一些说包含模型层能力的前端框架在实际运用里模型层的功能仍是使用太少,不过这个问题若是放到移动端,或者是PC和移动端融合可能就 会有些不一样,这个问题我将在本系列的终篇里再谈谈,这里也不累述了。

  说到这里须要总结下了,前端的MVC不该该等于单页面开发,前端MVC也不是把ajajx用到极致,根据实际业务场景,咱们须要适当的把同步请求和异 步请求结合起来。若是前端MVC里包含了更多同步请求,那么对于MVC里的C层即控制层就会有更高的要求。先后端分离主题还有个下篇,下篇里我还会提到一 种先后端分离方案那就是nodejs的运用,而nodejs的运用就是和控制层有密切的关系,上篇里我提到nodejs是先后端分离方案的催化剂,其实我 我的认为nodejs参入的先后端分离方案才是更加完美些的先后端分离方案,这个完美的评价缘由之一就是从前端承担控制层做用角度思考的,因此前端控制层 这个内容我将放在下篇讨论。

  好了,本篇写完了,从本篇咱们能够看到前端MVC的历史很早,它的出现早于nodejs,这就说明前端MVC其实并非什么新技术,只不过是如今才被 你们重视起来,完善它的人也愈来愈多。从本篇咱们还发现前端MVC其实并不完美,问题不少,最致命的就是对网络爬虫的不友好,因此咱们须要考虑到SEO技 术参入其中的先后端分离方案。

 

网站静态化处理—先后端分离—下(8)

我第一次据说nodejs技术大概是在2009年年底,不过我真正认真在网络上进一步了解nodejs仍是在2010年年中,当时对nodejs的 认识和我如今对nodejs的认识有着天壤的区别,开始想了解nodejs我只是为了感慨谷歌公司开发的V8引擎竟然如此强大,它不只仅能够做为 chrome浏览器的javascript内核运行平台,竟然还能为服务端使用javascript语言做为平台,经过对nodejs的了解让我认识到 chrome浏览器是如此的优秀,可是如此相对的是我并不认为javascript做为服务端语言真的会有市场。

  为何我当时会认为javascript做为服务端语言的前景堪忧呢?我当时有以下的思考,这些思考放到时下nodejs已经很是火爆的背景下,我相信对不少朋友任然有参考意义,下面是我当时的思考,具体以下:

  质疑nodejs思考一:2010年以前我还不是敢自称本身是一名专业web前端的工程师,所以对于javascript的 认识和掌握程度也不能和如今相比,可是对于javascript的难学,难深刻倒是有着切肤之痛,所以我想javascript做为服务端语言就是让会其 他服务端语言的工程师更加深刻的学习常被服务端工程师诟病的javascript,这么作的结果无异于逼迫服务端工程师转向成web前端工程师嘛,这个想 想就让人以为不现实。

  质疑nodejs思考二:我对web应用开发的技术选型认识比较肤浅。技术的选型是个很宽泛的问题,回到我对nodejs的质疑思考主要是体如今web应用服务端语言选择上,在中国用做web服务端开发的语言很是多,可是主流的无非就是java、php、C#以及C语言系列,固然web服务端技术发展到如今Python、ruby也是有必定市场,做为一名具体干活的软件工程师对 于项目选择何种技术是没啥发言权的,所以我经常以为技术选型就是项目经理或者是技术经理以及架构师的问题,而大多时候咱们去询问为何用这个服务端语言得 到的答案都是非技术性的回答,例如:公司主要是使用php啊,java比较流行人好找啊,C#开发快啊能很快的完成工做,不多有人会这么告诉你咱们的项目 是个什么样的项目,这个项目使用A语言比使用其余的B语言、X语言有何种好处和优点,其实中国不少软件企业作项目在技术选型这块都很粗,说的难听点其实就 是不少能控制项目的人技术水平很难被恭维,固然大部分项目其实使用什么技术实现并非过重要的问题,可是这个到了技术架构异常复杂的大型网站技术选型问题 就显得尤其重要,这个认识主要是来自于我阅读《淘宝技术这十年》所感觉到的,淘宝网站的技术选型随着业务的发展变化的如此之大,颠覆性如此之高,这个在我 待过的不少项目组都是难以使人想象的。

  Web应用发展这么多年,那些占据了天时、地利和人和的现有技术基本都是处于一个垄断的地位,新的同类型语言想突破重围必然有着本身独有的技术优点, 这就比如在中国作互联网若是有家新型互联网公司能够突破BAT的围追堵截,那么这家公司必定是有着本身得天独厚的优点,因此nodejs必定是得到一种得 天独厚的优点,那么nodejs优点在哪里了?不过在讲述nodejs的优点以前咱们先来说讲上篇文章里遗留下来的问题。

  其实上篇里我讲到前端MVC,文章里只是着重讲到了V层即视图层和M层即模型层的问题,而惟独没有专门讲解C层即控制层的问题。在先后端分离文章第一 篇里,我谈到若是把MVC框架里的C层以做为链接web前端和web服务端的角度来理解,C层主要承担了三个方面的工做,它们分别是:路由、报文格式转化和页面渲染的工做。 前端MVC在处理报文格式转化和页面渲染这两个方面仍是比较容易作到,可是在作路由这块存在必定问题,前端MVC框架对于获取服务端数据这块以及异步请求 处理方面其实和传统MVC框架的处理的手段本质上是相似,只是实现载体有所不一样而已,可是控制层还有一个路由功能,其中用于页面切换的路由存在必定的问 题,不过这个切换也要限定一下范围,页面经过ajax技术让页面部分刷新,假如这种部分刷新让页面展现效果发生很大变化,对于用户而言也是页面发生了切 换,可是这种切换是不会让地址栏的url产生任何改变,这就是问题的根本所在了,我在上篇里已经讨论过这些问题,经过这些问题咱们发现若是页面转化时候地 址栏的地址随之也发生改变是会给用户体验、网站的友好度以及SEO优化带来好处的,如是乎我提供了一种手段,那就是使用锚连接来帮助咱们实现url的变化,由于锚连接只是做用于浏览器,所以这种手段是对前端MVC的C层实现页面路由功能的一种很好的支持,可是由于这种方式须要在javascript里完成,那么对于SEO优化就产生了问题,最后我提出了页面切换咱们最好使用同步请求的方式。

  这个时候问题来了,若是要使用同步请求,那么这个同步操做天然是要让服务端来控制,这么作的结果就是让服务端再去回收部分控制层的功能,这样下来一个 使用前端MVC架构的网站就有点不太纯粹了,具体点就不是一个单页面的网站,这里咱们的讨论又回归到了单页面的问题了,前文讲前端MVC框架不少热心网友 对个人论述发表了有价值的评论,可是我发现个人想法有些朋友可能没有真正理解(这也许是个人表述的问题吧),我前端MVC讲述的一个思路是以批判前端 MVC的角度进行的,我早些时候和一些网友探讨过前端MVC的设计问题,有些朋友在没有作具体web前端MVC架构前老是想实现纯粹的前端MVC框架,延 着这些朋友的思路咱们就会把全部的C层和M层的东西都移到web前端,我常想若是真的这么实现了,结果天然就是单页面网站了,或者就是在前端引入了复杂的 模型层设计,不过探讨毕竟是探讨真的实现时候不少朋友就会知道了难度所在了,因此说理想和现实是有差距的,这话又一次灵验了。

  这种理想和现实的差距,其实就告诉咱们必定有个地方出问题了,那么问题在哪里了?下面我将我对这个问题的思考,总结以下:

  问题思考一:让前端承担大部分MVC的工做,那么前端自己的技术能力是否能达到全部的要求吗?这个回答彷佛是确定的,例如单页面的出现就表明了这种可能性,javascript也是拥有强大的面向对象的编程能力,所以再写复杂的业务模型层也是没问题,可是前端这么作了之后其实并不能知足全部人的需求,例如:SEO的要求,SEO不少技术都是以同步网站请求技术为根基,这个和前端MVC框架以ajax技术为根基产生了冲突,这就让前端技术产生了局限性。使用javascript面向对象技术来实现业务模型,这个也是有问题,javascript的面向对象的学习成本和精通难度超出了传统的面向对象的语言例如像java这样的语言,并且javascript要设计和写出更加容易维护的代码是很是不容易的,这么作不符合我在存储系列里讲到的要用最简单的方式实现的原则,这其实也是说明前端技术能力不足的问题。

  问题思考二:其实无论什么形式的先后端分离方案它最根本的思想就是让先后端进行解耦,让不一样技术语言体系下的人 能作到工做的隔离,最后协同起来各自发挥出本身的最大价值,可是若是咱们只是按前端,后端的角度来作分离,是否是有点粒度过粗,考虑是否是过于片面了?特 别是这个片面的问题,web应用的问题并非一个纯技术问题,而是一个技术和业务结合的问题,所以任何应用于生产的技术方案都会受到业务的影响,例如上面 当咱们要考虑SEO的问题,考虑开发难度的问题,那么纯粹的前端MVC的框架就会显示出本身的局限性。前端技术没法改变浏览器地址栏的url,这个从不少 角度思考是个合理的设计,可是到了前端MVC里对C层的设计而言则变成了一种技术手段的局限性了。由于这种局限性就让咱们不得不回到问题的原点状态,例如 页面的同步请求,而同步请求最合理的控制地点就是服务端了。

  问题思考三:本思考是一个延生性的思考,我从事这么多年的web开发,我其实一直困惑于web应用开发和MVC 的关系,为何咱们作web应用开发时候都要那么强调和重视MVC设计思想呢?难道web应用开发的世界没有MVC就不能活了吗?回首下web应用发展的 历史,在web应用开发的忙慌年代,的确是看不到MVC的影子,那个时代的确很自由,自由到许多web应用混乱不堪,质量和健壮性差的不能再差了,这个时 候一个英雄出现了那就是MVC,MVC表明了一种次序,一种基本的法则,这就比如人类社会创建的根本原则同样,这些原则让人类和野兽有了区别,人类也由于 这些原则而成为万物之灵长,相比之下MVC就是web开发世界里的游戏规则和行为准则,所以只有当咱们从MVC角度思考web应用的建设,才会让web应 用更加的优秀,这也就是在讲述先后端分离技术时候我都是以MVC思想做为准则进行思考的。思考回到具体的场景,MVC思想的运用就是让咱们把web应用开 发里能够归为一类的场景汇集在一个范畴之下,不一样范畴使用一种双发均可以接受的统一准则进行沟通,这么一来咱们就把须要解决的问题简单化了,各个独立的范 畴由于减小许多没必要要的干扰,所以能让它们发挥出更大的潜力,更重要的MVC还让web应用伸缩性,健壮性,可维护性大大加强。例如在不少传统web应用 开发里在控制层这块先后端的矛盾就是属于MVC规则使用不完善所致。

  单页面的应用存在不少问题,所以须要同步请求的介入,这就致使了服务端再度回收了失去的控制层的功能,这么作也无可厚非,可是我很担忧这个改进的引入 会不会致使传统MVC框架里控制层的混乱问题,根据个人经验,这种混乱的程度已经下降了不少不少,基本咱们能够忽视原来C层的问题了。

  不过不少有追求的web前端工程师对于这种不纯粹的前端MVC的异议仍是不少的,大部分异议仍是源自浏览器能力的局限性,当服务端不少方面被弱化后,也许能够解决咱们之前在前端被服务端束缚的不少问题,可是同时又产生了新的问题,这些新问题我总结以下:

  新问题一:在传统的网站动静划分里,咱们常把浏览器端的技术html、css和javascript归结于静态技术的范畴,若是网站使用Web前端MVC那么前端就会接过不少动态网站的功能,这个时候传统的静态技术就被人为的演变为动态技术。回顾网站的发展历程,基本是从静态到动态的转变,这个结论用在时下其实已经有点不太对了,随着网站愈来愈庞大愈来愈复杂,网站技术发展逐渐开始逆向进行了,网站从动态化向静态化转变的需求变得愈来愈强烈了,这也是时下前沿的前端技术正在解决的问题,例如本系列的主题网站静态化技术就是顺应这个发展趋势而来的,因此前端MVC框架在这点上有点逆历史潮流的问题了。

  新问题二:前端MVC让web前端的技术难度和架构难度成指数级上升,而javascript语 言天生有着本身设计的缺陷,这个缺陷在写大规模复杂应用时候就显得尤其突出,例如:javascript没有模块化管理,javascript面向对象的 实现难度,因此前端MVC的应用可能会变相的提高企业的技术成本和开发成本,固然不少新的技术手段能解决javascript固有的缺陷,对这些新技术有 个更大的问题就是“你会吗“,不会的话首先要解决会的问题,这也是个成本问题。

  新问题三:当前端真的愈来愈独立于服务端后,这会致使服务端一些能够优化web前端的重要技术就很难实现了,例如网站静态化系列里讲到了缓存运用,CDN的运用就很难达到预期效果,或者根本无法使用,由于这些技术的根基都是认为网站动态性是由服务端发生的,而客户端霸占了动态性,那么这些技术的做用就被限制住了。

  由此我能够下个结论:若是先后端分离方案是以浏览器和服务器角度来划分并非最好的前端分离方案,那么先后端分离方案还有没有新的解决思路了?这个真的有,那就是nodejs参入的先后端分离方案。

  其实先后端分离的驱动永远都是前端强于服务端,而先后端分离的重要目的也是要给web前端创造一个更加干净的开发环境,那么写的代码是不是在浏览器上跑仍是在服务端上跑这个并非过重要,因此引入nodejs,就是让服务端也能跑javascript代 码并不会是让人没法接受的事情,回到先后端分离方案里以服务端驱动的先后端分离方案,我曾说过这个方案能得到服务端开发人员更多的掌声,我相信这个掌声不 会是服务端为前端的喝彩,而是服务端终于从web前端解脱出来了,这样服务端运用更加高级的SOA技术就成为了可能,那么咱们把web前端的控制层使用 nodejs替代,这么一来咱们既能够继承全部传统MVC框架的优势,同时也达到之前后端分离的根本的问题就是为web前端创造一个很干净的开发环境问 题,那么咱们在前端MVC框架使用时候遇到的问题都会很好的被解决。

  Nodejs的运用让动态网站的动态性再度停留在了服务端,那么我前面讲的那么多网站静态化技术就能够和先后端分离方案很好的融合了,所以本篇先不具体讨论nodejs作先后端分离的实现手段了,在下篇讲从网站静态化角度从新审视先后端分离方案时候一块儿讲解,这么作会更加符合本系列的主题。

  如今咱们能够解答为何nodejs技术能够突破传统服务端技术的包围,由于nodejs可让先后端达到更高程度的分离,从而让先后端各自发挥本身的优点,颇有意思的是,虽然nodejs技术属于服务端范畴,可是它倒是前端工程师驱动来普及的,这绝对是web前端逆袭啊。

 

 

网站静态化处理—知足静态化的先后端分离(9)

先后端分离的主题虽然讲完了,可是先后端分离的内容并无结束,本篇将继续先后端分离的问题,只不过此次先后端分离的讲述将会围绕着本系列的主题网 站静态化进行。在讲本篇主题以前,我须要纠正一下先后端分离主题讲述中会让朋友们产生误导的地方,这种误导就是对时下流行的一些先后端分离方案(没有使用 nodejs的先后端分离方案)的评价问题,其实本人任然以为无论什么样的先后端分离方案只要成功被实施,而且产生了良好的效果,那么它就是一个成功的前 后端分离方案,前面我以一种批判的角度讲述这些先后端分离方案,并非想在否认它们,而是出于一种鸡蛋里挑骨头的较真态度想从新审视这些方案,但愿这种审 视能让咱们的设计方案变得更加优秀,同时本身也在这个较劲的过程里获得自身技术能力的提高。其实那些被我批判的技术方案也许在某些特定场景下它就会变的更 加优秀,我推崇的技术方案在某些场景下可能就变的苍白而无力,这种状况颇有可能发生,不说别的,我之因此批评前端MVC,其私心就是由于它不符合网站静态 化的处理,若是把前端MVC内容放置在网站静态化的主题下谈论,被批的命运那是必然的。

  网站静态化技术相对于先后端分离技术的关注度要低的多,若是业界的一些公司由于看了本人的文章能对网站静态化技术有一种新的认识,从而考虑在本身网站 上使用网站静态化技术,同时也想实现先后端分离技术,那么新的问题出现了,这两种技术同时使用会发生矛盾吗?若是有矛盾,咱们到底将如何解决这些矛盾?解 决这些矛盾的时候咱们是否是能够作好二者的兼顾,而不会发生其中一方妥协于另外一方,最终致使其中一方没有充分的发挥本身的能力。要解答上面的一系列问题, 我首先要探求的就是网站静态化技术和先后端分离方案里那些方面会产生矛盾。

  从我前面对网站静态化技术的阐述,咱们知道网站静态化的技术最佳做用位置应该是服务端而非是浏览器端,之因此会这样是由于网站静态化技术的技术基础是 动静分离和缓存,这两个方面若是落到浏览器端会碰到不少难以解决的问题,那么咱们要分析下这些难以解决的问题,具体以下:

  浏览器之缓存问题:浏览器也有缓存,不过浏览器端的缓存那就不是指内存里的缓存,而是持久化的缓存,实际上浏览 器端的缓存很是不可靠,会被不少非技术的因素所限制,例如咱们手动删除缓存或者使用无痕模式上网,那么这些持久化的缓存就会失效,用户再度访问网站时候都 将是第一次访问这个网站,这就使得不少优秀的缓存策略方案在浏览器端实施效果大打折扣。

  浏览器之动静分离问题:网站静态化技术里一个重要的手段就是如何设计动静分离策略,纯粹的静态内容这个没啥好说 的,可是动态的内容在必定的条件(例如:时间,一些业务属性例如商户属性)下是能够转化为静态内容,这些内容若是能被有效缓存,对网站性能提高是不可估量 的,并且这种动静转化的策略也能够减小业务服务器上处理没必要要的请求,从而减轻业务服务器的压力,达到提高后台核心业务服务端的负载压力。可是若是咱们使 用前端MVC框架,一股脑子把不少服务端功能往前端迁移,那么这种动静处理手段就很难作,并且不少场景基本上是没法应用了。

  所以我认为先后端分离方案使用nodejs价值更高,由于使用nodejs咱们就能够根据网站静态化技术将须要保留在服务端的功能能够继续保留在服务 端,这样就能达到两者兼顾的目的。可是若是咱们认为把nodejs引入后,nodejs的目的就是用来作网站总体MVC架构下的C层即控制层,这个思路到 底合理不合理呢?这个问题仍是很值得玩味的,所以咱们须要分析下网站总体MVC架构下的C层即控制层的做用。

  在前面文章里我曾总结过C层即控制层在MVC框架里的做用,这个做用分别是:路由、报文格式转化以及页面渲染,可是这个做用的总结我是有个前提条件 的,那就是以C层即控制层做为先后端沟通介质的前提下。若是先后端分离方案引入后把控制层归为前端的组成部分,那么控制层跟前端的结合问题都是人民内部的 矛盾,都是比较好解决,可是控制层就仅仅是用来链接先后端一个做用吗?对于网站架构里的控制层,有一个不可避免的功能那就是做为后端服务端的安全入口的做 用,也就是说控制层是作请求安全检查和安全监控的地方,并且不少安全校验还会和业务相关,例如检查报文是否被篡改啊,防钓鱼的功能,若是这些功能被前端来 承担,首先不谈前端技术人员会不会作这些,可是至少一点问题是会发生的,前端工程师在关心页面开始同时还要写服务端的业务逻辑了,无论怎么说,这些功能迁 移到前端总不是太合适。当网站演变为超大型网站后,大型网站每每是不少小中型网站项目的集合体,为了减小网站总体的异构性,咱们经常把不一样的模块网站的入 口整合在一个大型控制层项目下面,这个大型控制层项目通常称为网关项目,它的做用和网络里的网关很是类似。除此以外,还有些网站的控制层很是特别,例如一 些作第三方支付的网站,那么这样网站项目自己就是个大网关,并且这个网关很特别,它后台的服务就是其余银行的系统,它的路由工做就会变得异常复杂,例如: 根据用户使用银行的不一样,控制层要组装不一样的报文信息,而这些功能都是属于控制层,这样的场景无疑大幅度提高了控制层再和模型层对接的技术难度,而增长的 难度问题又和模型层耦合度很高,因而可知,web应用总体的MVC的控制层比咱们想象中要复杂的多。

  回到用nodejs替代控制层这个主题,咱们来看看实际的场景吧,假如咱们的网站控制层相对比较简单,好了,这时候咱们跟领导或老板说“如今很流行前 后端分离,咱们项目也使用下先后端分离技术”,领导或老板一听可能会为之一振,那么就会问你”那么该怎么作了”,你这时对他说“首先把控制层用 nodejs重写下”,领导或老板听到这个回答他会赞成你这么干吗?一个不会给网站增长任何新功能,同时不能很直接有效的提高网站的性能,并且执行它还会 有很大风险的方案,头儿们会赞成吗?好了,假如你终于找到合理理由说服头儿们,那么若是咱们的网站规模已经很大,控制层已经演变成了网关项目,控制层自己 已经巨复杂了,你敢用nodejs重写一遍网关项目吗?因此说吧nodejs直接当作控制层,其实实践起来困难重重,并且nodejs彻底承担控制层,它 的性能,它可否很好的运用于集群开发这都是很难把控的问题。分析到这里,咱们彷佛又进入了死胡同了,那如何来破这个局呢?

  上面的问题只是反映出整个网站MVC里的控制层其实还有部分功能是和服务端的模型层紧耦合的,所以要解决这个问题就是把传统的控制层再细分一下,属于 前端的部分划分给web前端做为web前端的控制层,属于服务端的部分任然留给服务端,这么拆分后,当咱们引入了以nodejs为基础的先后端分离方案, 服务端的控制层改造无非就是去掉页面路由,页面渲染,再修改下返回数据格式便可,由于不用修改服务端的业务代码,其代价是很低的,头儿们也很容易接受这样 的方案,并支持咱们大胆去尝试新技术。

  服务端网站静态化技术SSI和ESI,主要是根据动静分离策略把网页不会常常变化的模板进行缓存,而后在静态资源服务器位置整合动静资源,若是咱们使 用nodejs只是简单替换原来的控制层,那么这些策略其实仍是有问题的,那么怎样作可让nodejs兼容SSI和ESI了?这里我列举个实际的案 例,nodejs有一个模板语言叫作jade,nodejs里还有个技术叫作handlebarsjs,其中handlebarsjs和struts的标 签相似,它能够处理一些简单的业务逻辑,咱们开发时候使用jade编写页面的模板,使用handlebarsjs让动态数据和模板进行整合,项目发布时 候,使用像grunt这样的项目管理工具编译项目,jade文件变成html文件,而handlebarsjs则会转化为javascript代码,这样 咱们就能够把生成的html文件在服务端进行有效缓存,而handlebars生成的javascript文件负责整合动静数据,这样nodejs就能够 达到兼容SSI和ESI的做用了。

  不过引入nodejs会让网站处理请求的过程里增长一个环节,这样可能会致使部分性能的损失,可是我上面的实例却能有另外的方式规避这个问题,由于 nodejs的代码是用javascript语言编写的,那么这个代码是能够运行在浏览器上的,那么这就会产生了一个处理手法,那就是咱们在生产部署时候 其实不须要部署nodejs的,咱们把静态模板就缓存在服务端或者推送到CDN上,而后handlebarsjs生成的js代码就让它传送到浏览器端,因 为这个js代码生成后基本不会变化,浏览器能够缓存它,固然CDN或静态资源服务器也能够缓存它,其实它在浏览器运行时候变化无非就是获取一次服务端数据 而已。这么一来,生产上的web前端又转变成了前端MVC的形式,还把动静整合的事情交由了浏览器来完成,这不只是兼顾的网站静态化要求,还让动静整合推 到了更加靠前的浏览器端,这不是达到了一个共赢的效果了嘛。

 

网站静态化处理—反向代理(10)

反向代理也是一种能够帮助实现网站静态化的重要技术,今天我就来说讲反向代理这个主题。那么首先咱们要了解下什么是反向代理。和反向代理相对应的是 正向代理,正向代理也就是咱们常说的代理服务,正向代理是很是常见的,例如在某些公司里咱们想使用互联网,那么咱们就得在浏览器里设置一个代理服务器,通 过代理服务器咱们才能正常使用互联网,而这个代理服务器就是一个正向代理服务器。正向代理更加让人熟悉的使用场景估计仍是在FQ技术里的使用,咱们使用一 个放置在国外的代理服务器来访问那些在国内没法正常访问的网站,这其实也是在使用一个正向代理服务。

  其实无论是正向代理仍是反向代理,这两个概念的定义都是以浏览器侧为基准进行的,正向代理是代理浏览器来访问互联网,反向代理是指代理再也不是代理浏览 器侧了,而是反过来代理浏览器须要访问的应用服务器。那为何咱们要使用正向代理服务器了?答案固然不是为了FQ了,下面我来列举些实例来讲明这个问题 了。

  例如公司里使用代理服务器主要是为了安全的考虑,不少公司内部都有本身的局域网,通常咱们称之为内网,内网里有公司的各类资源,若是公司员工的电脑随 意链接到互联网,假如碰到那些别有用心的黑客,经过攻击员工的工做电脑截取了公司重要的文件资料,那样就会形成公司的重大损失,正向代理除了能防范外部的 黑客攻击外还能监控和控制公司内部员工将公司重要文件经过互联网传递给不恰当的人,所以公司让员工使用代理上网基本都是出于安全的角度来考虑的。

  正向代理的合理使用还能帮助一些企业提高本身产品的核心竞争力,例如在移动端有一款很是流行的浏览器,它之因此很是受用户的欢迎,是由于使用该浏览器 上网速度比其余浏览器明显的快多了,那么这款浏览器是如何作到这点的呢?奥秘就是这家公司为本身的浏览器对应创建一个十分强大的代理服务器集群,用户使用 该浏览器访问网站时候用户首先访问的是该公司的代理服务器,而这些代理服务器使用缓存技术缓存了海量的网站信息,再加上使用一些web加速的技术例如 CDN技术,这就让该浏览器访问网站的效率明显快于其余浏览器。

  反向代理和正向代理从技术角度上基本上是一致的,区别主要是代理的内容不同了,反向代理代理的是应用服务器。反向代理技术也基本上是互联网公司的一 个标配技术,可是反向代理可否正确使用,可否更进一步的发挥它的实用价值,我以为并非全部公司都能作好的,下面我来总结一下反向代理的使用目的吧,具体 以下:

  使用目的一:反向代理能够隐藏真实的应用服务器。该目的属于安全的范畴,反向代理隐藏真实的应用服务器,那么就可让别有用心的黑客很难掌握正确的应用服务器,从而增长黑客的攻击难度。

  使用目的二:反向代理能够实现负载均衡的功能,例如在java的web开发里有一种很简单的实现集群的手段,这个手段就是使用apache加上tomcat的组合,用户请求先到达前置的apache服务器,apache再使用负载均衡策略将请求分配给后台不一样的tomcat服务器上。

  使用目的三:反向代理能够起到动态调节应用服务器并发数的目的,通常用做反向代理的服务器都是静态资源服务器, 这样的服务器在并发处理能力上要远强于后台的web应用服务器,那么能够经过控制web应用服务器前置的反向代理服务器,这样就能够动态调节后台服务的负 载的大小,这个作法的好处可能不少朋友都不太了解,这里我列举个例子,一个网站最须要稳定性的部分是哪一个部分呢?不少朋友会说是数据库, 的确数据库是最重要的,由于数据库作分布式很难,很容易造成单点故障,要是数据库挂了基本一切都无法玩了,那么除了数据库以外还有别的吗?固然有,那就是 用于处理业务的应用服务器了,应用服务器若是作了集群,集群中其中一台服务器挂了其影响面会比数据库挂掉低多了,可是一个网站的作业务处理的应用服务器挂 掉,对公司的损失仍是很大的,而web应用服务器前面的用做反向代理的静态资源服务器挂掉问题就会小多了,至少不会产生公司业务没法正常完成的事情了,因 此当网站负载太高,让过载的请求被反向代理拦截或者阻止,这对应用服务器的稳定性提高有莫大的好处。固然反向代理调节应用服务器的负载水平的用途不只仅这 些,有兴趣的朋友能够在网络上找找相关的介绍。

  使用目的四:反向代理能够缓存静态数据,通常用做反向代理的服务器都是使用像apache或者是ngnix这样的静态资源服务器,所以咱们能够把web应用里的静态资源缓存在反向代理服务器上,从而达到提高请求处理的速度问题。反向代理的这个功能就和本系列的主题网站静态化处理切合了。

  分析完反向代理的使用目的后,咱们如今将反向代理应用到项目里,这里应用的一个前置限定就是将反向代理应用到网站静态化的处理之上,首先是第一个应用方式,以下图所示:

 

      第一种反向代理应用方式就是让反向代理和应用服务器一一对应,也就是每台应用服务的部署服务器上都对应部署一台反向代理服务器,这么作有怎样的好处呢?首 先咱们来说第一个好处,若是咱们将网页作了动静分离,那么反向代理服务器就能够负责对请求中的静态资源访问进行处理,同时反向代理还能够承担动静资源整合 的目的。这里要特别说明下,前文里我说道动静资源会由于咱们使用的动静策略而发生转化,那么有些动态内容在必定条件被转化为静态资源后,咱们能够将这些作 了转化的静态资源在服务器上缓存起来,这个时候上图展现的架构模型就会发生变化,以下图所示: 

      咱们看到反向代理服务器应用服务器之 间会造成一个cache层,反向代理访问cache层的效率会比直接访问应用服务器要高的多,这等因而给应用服务器作了一个加速操做,同时经过缓存咱们可 以减小应用服务器的运算压力,从而达到提高应用服务器性能的目的。之前有朋友问我这么作会不会增长应用服务器的压力,由于一台服务器上部署了两台能够处理 web请求的服务器,那么它们之间必定会有发生冲突的时候,不过我想产生冲突确定是咱们没有很好的处理两者关系所致,因此咱们要理清在同一台服务器上部署 反向代理和应用服务器后,它们之间的关系究竟是怎样的?

     其实反向代理和应用服务器从物理形态角度上它们是两个不一样的东西,可是两者在逻辑上实际上是一个总体,它们共同完成一个逻辑性的应用服务器的功能,只不过 两者由于应用场景不一样而造成了一种分工合做的关系,反向代理服务器主要完成对静态资源请求的处理,而应用服务器则是负责业务逻辑的处理,它们最终造成一个 强大的协力使得总体的逻辑性应用服务器的性能获得显著的提高。

     除此以外,这个反向代理还能够发挥动态调节应用服务器的并发数的目的,可是上面的技术方案却没有发挥反向代理的负载均衡以及安全性这两个方面的做用。为了让反向代理四个使用目的获得充分的发挥,那么咱们该如何来作了?

     方法很简单就是把反向代理的部署地点从应用服务器所在的物理服务器上迁移出来,放到一台独立的物理服务器上,可是这个作法会有性能上的损失,同时还会增长整个技术架构的复杂性。为何性能会损失呢?由于原来的反向代理服务器应用服务器部署在同一个物理服务器上,那么它们之间的通信都是之内存共享的方式进行的,这样的通信效率是很是高,如今换成了经过网络通信进行沟通,而网络通信是IO设备里效率最差,可靠性最差的,所以单独部署反向代理服务器或多或少都会形成必定性能的损失。

    为何说单独部署反向代理会增长整个网站技 术架构的复杂性了?咱们把反向代理服务器单独部署,那么单独部署时候咱们还会是使用一一对应的策略吗?先不谈这么作,从技术和业务角度的好处和坏处,但从 成本这个考虑就是会让不少公司望而却步,由于这个作法就会致使用于部署应用服务器的成本翻倍的增长,而增长的服务器用于反向代理,这样的作法怎么体会都不 是以为物有所值,再说用于反向代理的静态资源服务器自己处理请求的并发能力是普通应用服务器的数百倍,一一对应自己也没有彻底发挥反向代理服务器的潜力,所以最好的解决方法就是把反向代理服务器作成一个反向代理服务器集群,作成集群问题又来,集群里每台反向代理缓存的数据是否是要保持一个同步了?这就比如处理应用服务器的 session同步问题,若是真的这么作会不会致使反向代理服务器上缓存大量使用率不高的数据从而致使缓存的利用率不好,同时同步操做自己也会影响到反向 代理集群的性能,因此要设计一个好的反向代理集群是一件十分复杂的事情,其实合理的反向代理集群的作法就是在集群里在进行分组,每一个分组应该是和后端的 SOA服务相匹配,这个时候反向代理集群的效率才能获得最大的发挥,同时资源利用率也会更加的合理。其实使用反向代理集群方式,也会给生产部署形成麻烦, 若是网站进 行了静态化处理,那么反向代理须要承担对静态资源的处理操做,这个时候反向代理和对应的应用服务器结合起来才能造成一个完整的应用服务器,可是如今咱们将 一个完整的逻辑应用服务器分开部署了,那么当咱们发布新应用的时候就得面临更加复杂的状况,这就增长了部署和运维的风险和难度。

     我如此批评单独部署反向代理的问题,可是我并非说这种作法彻底不可取,而是想告诉你们这种作法实际上是一种高级的作法,可是也是一个复杂的作法,要作好这个集群是很麻烦的一件事情的,我以为只有当咱们的网站业务量和请求量很大的时候,同时原有方案出现了瓶颈时候能够认真考虑反向代理集群方案的实现,不过将反向代理造成集群会给网站的安全性带来莫大的好处,反向代理能够隐藏后台的应用服务器,这种隐藏就是客户端只须要访问代理服务器即 可,应用服务器对外都是以反向代理来展现的,可是若是反向代理和应用服务器一一对应,那么恶意黑客找准了某台反向代理服务器后,对这个反向代理服务器进行 反复的攻击,那么这个攻击也就等于攻击与之对应的应用服务器,这就致使反向代理隐藏真实应用服务器的做用就没有获得有效的发挥,而集群这块就能够很好的处 理这个问题,不过咱们若是以为使用集群代价过高,咱们也有变通的方法,那就是在全部逻辑应用服务器前面再放置一个反向代理服务器,这个反向代理服务器再也不承担缓存的功能,而只是用来作负载均衡和安全处理,这样一一对应的策略安全性也能够获得保证,不过若是公司技术能力好能够考虑使用LVS这种软件化的负载均衡技术方案,假如公司还颇有钱还能够考虑使用更加高级的硬件负载均衡设备例如F5设备。

     若是咱们网站除了使用网站静态化技术还使用了先后端分离技术,固然这个先后端分离技术应该是使用nodejs的先后端分离技术,那么nodejs应该放 置在生产部署的什么位置上了?上篇文章里我曾列举了一个nodejs的应用实践场景,在这个实践场景里我曾经提到若是在原有的网站生产架构下引入 nodejs会增长一个请求处理环节,而nodejs使用主要是为了知足先后端分离而非增长网站性能,所以增长的环节可能会让请求处理的性能降低,所以我 最后提出一种变通手法,就是nodejs项目发布时候编译源代码,而后将编译出的javascript 和html文件干脆推移到浏览器端处理,这样就变相造成了前端MVC框架,这个作法老是有点不三不四的意味,假如咱们真的想把nodejs引入到应用生产 的网络架构里,咱们不但愿无故的增长请求处理环节,那么最好是让nodejs服务器替换某个部分。按照这个思路思考,那么我以为nodejs在生产的引入 最好是和反向代理相关,最简单的方式就是让nodejs和反向代理一一对应,这样就能够很好的下降引入nodejs带来的问题,固然复杂点的就是反向代理 集群对应的应用服务器应该是nodejs的应用服务器,而不是用来作业务处理的业务级别的应用服务器。

    无论怎么说,我认为在网站静态化方案里咱们必定要考虑反向代理的运用,若是静态化技术方案里没有反向代理的身影,那么这个网站静态化处理可能很难达到咱们预期的效果。

 

网站静态化处理—web前端优化—上(11)

网站静态化处理这个系列立刻就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化。在开始谈论本主题以前,我想问你们一个问题,网站静态化处理技术究竟是应该归属于web服务端的技术范畴仍是应该归属于web前端的技术范畴,要回答清楚这个问题咱们要明确下网站应用的本质究竟是什么?网 站的本质其实就是BS,这里的BS我没有带上架构二字,而就是指Browser和Server即浏览器和服务器,而网站静态化技术的做用目标就是让客户端 即浏览器的用户体验更好,可是若是咱们想让网站在浏览器上运行的更快,在更快的基础上能设计更多更好的用户体验功能,那么咱们须要作的工做其实就不只仅是 着眼于浏览器自己,而是要把和浏览器相关的一切做用因子结合在一块儿考虑,这就是网站静态化技术的本源所在,因此有些朋友认为网站静态化 技术实际上是一个服务端技术多于web前端的技术,所以认为网站静态化技术是不属于web前端的范畴,我认为这种理解是不正确的,我想产生这种误导的缘由是 不少人都是狭义的理解web前端技术,认为web前端就是以javascript、css以及html所表明的技术,超出这个范畴的技术就不该该属于 web前端范畴,我我的以为这种理解也无可厚非,可是这种理解可能会让那些有追求的前端工程师产生一个很差的后果,这个后果就是不灵活的划分本身须要掌握 的技术范畴,最终影响自身技术能力的突破,无论是web前端仍是web服务端都应该把作好优秀的网站为己任。BS自己就是一个总体,只有两者结合起来才能 产生网站,缺乏其中任何一方,那又何来的网站呢?BS中的S就犹如蝴蝶效益里蝴蝶的翅膀,虽然蝴蝶看起来只是在亚马逊雨林轻轻的挥动了一下,但是这个挥动 却能让相距千万里的太平洋上刮起可怕的飓风,所以本人对web前端有个新的认识,咱们不该该把前端只是局限于javascript、css和html这些 技术之上,而是应该把本身当作浏览器应用开发专家,一切用做于浏览器的技术和手段都是web前端工程师须要掌握的知识,就像时下的nodejs出现,逼得 前端工程师不得不去作服务端开发,不要以为这是被迫的,而要把它当作web前端的逆袭,认为这是理所固然的事情。

  好了,咱们如今回到web前端优化这个主题吧。Web前端优化技术的普及仍是要归功于互联网两大巨头雅虎和谷歌的贡献,他们经过多年的积累和总结,将 这些web前端优化的经验无偿的公布给全世界,从而推进了web前端的发展,这些技术都不是什么秘密,我在网上找到一篇讲解这些技巧的文章,文章就是《Web前端优化最佳实践及工具集锦》。

  web前端优化技术和网站静态化技术使用目的是一致的,就是让网站变得更快,用户体验更好,我我的认为网站静态化技术其实就是web前端优化的一部 分,只不过网站静态化技术是经过服务端的大规模技术改造来实现web前端技术优化,而服务端的这种改造的目的就是让整个网站的后台技术架构更加切合web 前端的要求,从而能更好的实现web前端优化。我这里之因此能如此评价网站静态化技术,其实说明网站静态化技术和web前端优化技术必定存在某种强烈的切 合点,我我的认为这个切合点就是它们背后使用的理论基点是一致的。那么它们之间这个切合的理论基点究竟是什么呢?

  优秀的网站应该是用户体验好的网站,当人们使用这个网站感受爽,好评不断,那么这个网站就是一个用户体验优秀的网站,可是用户体验好的网站就是网站布局精美,图片很炫,人性化设计到位这么简单吗?这些要素都是网站使用者的感觉,可是对于网站设计和开发人员而言,再好的网站必定要解决一个根本问题,那就是网站加载的速度要快,若是网站加载速度不快,你就算把网站设计的再漂亮,估计也会搞的无人问津,说到这里,是否是有较真的朋友不信个人结论呢?我把前面引用文章里的一张图再给你们瞧瞧,以下图所示:

  其实当咱们开发网站若是只考虑如何把网站作的漂亮而忽视网站的性能,咱们就会发现漂亮的网站和网站的性能实际上是矛与盾的关系,例如精美的图片每每须要 高质量的图片格式,而高质量的图片格式就意味图片会变得很大,那么在图片经过网络加载时候就须要花费更多的时间,因此咱们在设计和开发优秀网站时候,漂亮和效率是须要咱们认真权衡的,认真思考的,最终要找到一个最好的方式实现两者的平衡,同时更加充分的发挥双方的潜在价值。而直观的用户体验好这其实更多的是一个设计问题,而解决用户体验好的根基:速度问题,这就是一个技术问题了。

  要解决网站的速度和效率问题,那么咱们就得思考网站的载体计算机到底哪些因素会影响网站的速度和效率。其实计算机的本质很简单,那就是计算和存储,计算主要是CPU来完成,而计算机用于存储的介质就多了,它们主要是内存、硬盘,若是是网站应用还有个很关键的存储介质须要考虑那就是网络了。那么计算机用于计算和存储的这些介质的效率是怎样的一个状况呢?这个问题我在之前一篇文章里有过阐述,这篇文章就是《关于如何提升Web服务端并发效率的异步编程技术

  这篇文章的其余内容太多了,我把关键部分在本文摘抄一遍,内容以下:

对于一个网络请求的处理,是由两个不一样类型的操做共同完成,这两个操做是CPU的计算操做和IO操做,若是咱们以处理效率角度来评判这两个操做,CPU操做效率是光速的,而IO操做就不尽然了,计算机里的IO操做就是对存储数据介质的操做,计算机里有以下几个介质能够存储数据,它们分别是:CPU的一级缓存、二级缓存、内存、硬盘和网络,一级缓存存储和读取数据的能力接近光速,它比二级缓存快个5倍到6倍,可是无论是一级缓存仍是二级缓存,它们存储数据量太少了,作不了什么大事情,下面就是内存了,以一级缓存的效率作参照,一级缓存比内存速度快100多倍,到了硬盘存储和读取数据效率就更慢了,一级缓存比硬盘要快1000多万倍,到了网络就慢的更不像话了,一级缓存比网络要快一亿多倍,可见一个请求处理的效率瓶颈都是由IO引发的。

  因而可知网站的速度和效率问题彷佛都是由存储即IO形成的。不过咱们不能由于感受发现问题根源在于存储,而就忽视对CPU的思考,因此我先讲讲CPU 和网站性能的关系吧。CPU是计算机用于作计算的设备,如今的电脑能看电影,能听歌,能够和朋友聊天,还能用于工做,这些使人称奇的功能其实到了CPU这 里也就是经过加减乘除这类基本的数学运算完成的,说到这个真是难以让人想象,读书时候学数学老是以为那么枯燥乏味,没想到如此强大的人类神器竟然就是经过 数学运算得来的,难怪有国外科学家说宇宙都是经过数学运算得来的,这仍是有道理的。不过网站背后的数学运算却有着本身的特色,虽然CPU计算能力很强,但 是在实际场景下不少业务的计算其实很消耗时间的,若是网站某些请求响应背后的运算是须要消耗太多的时间,那么这个时候CPU也就会成为网站性能的瓶颈所 在,网站应用有个重要的特色,这个特色有个专有名词描述那就是网站的实时性,根据网站实时性的特色,那么就要求咱们网站每一个请求所包含的计算都要简单和快 捷,简单快捷的计算也就让每一个请求背后所包含的业务性运算要更加简单,这也就是为何不少人会说互联网的网站和企业的web应用相比,互联网的业务逻辑比 较简单的道理,可是随着网站的规模扩大,业务模式愈来愈丰富,这个时候网站在某些业务环节不可避免的变得复杂,假如这些复杂的业务又须要实时的反应给用 户,那么CPU不能快速完成业务计算就是网站的效率问题的根源了,例如我在存储系列里说到的海量数据的计算操做,就是这样的场景之一,那么这个时候咱们该 如何来作了?

  碰到这个问题,咱们首先要明确一个问题,计算出现了瓶颈,那么最直接的手段就是增长计算机的计算能力,好比使用运算更快的CPU,可是更快的CPU面 对快速增加的业务而言,增长的效率是很是有限的,因此在CPU这块出现了多核技术,咱们能够把一个计算任务拆分红诺干个子运算,这些子运算在不一样CPU上 计算,最终把结果汇总起来,可是这个手段和用更快的CPU手段同样,面对快速增加的业务很快就会达到性能瓶颈,最终咱们发现咱们的业务计算任务其实已经超 出了单机计算机的能力,如是乎分布式技 术出现了,咱们这回再也不是在CPU上作文章了,而是使用多台计算机联合计算,可是分布式计算系统是须要网络进行互联的,而网络是计算和存储里最大的短板, 再加以如今互联网的所使用的计算资源规模达到了超乎想象的程度,咱们发现想经过扩展计算机的计算能力来解决网站快速响应的问题基本是一件没法完成的任务, 那么这个时候咱们又该怎么办呢?

  这个时候咱们就要转化思路了,由于当网站的计算瓶颈问题已经到了这个地步了,咱们再去更加深刻挖掘计算机的计算能力这对最终的结果影响已经意义不大 了,所以咱们只能从计算的相关方哪里寻找问题的解决方案。那什么是相关方呢?仔细分析计算相关方的确太多了,可是有一个最根本的相关方就是用户的实际业务 需求了,用户可能认为本身的业务需求都是很明确的,例如电商里的用户想查询本身的交易数据,可是这个业务问题转移到网站的开发人员和业务人员,面对这么多 用户的交易查询那就是一个超级复杂的计算问题,如是网站的业务和开发人员就会根据本身系统自己的特色和问题,进一步思考用户业务计算问题的本质,谈论业务 计算本质这个问题若是展开细化是很是复杂的,由于现实的业务场景实在是太多太复杂了,可是放到网站实时计算这个角度,其实有一个很简单的解决思路,咱们回 顾下咱们前面讨论的计算瓶颈问题,其实这个问题的本质不是计算可否成功完成的问题,而是计算是否能及时完成的问题,如 果用户的请求计算的确是无法很快完成,那么咱们就不要让用户以为这个计算是能很快的完成,这个作法也有一个专有名词那就是异步计算,可是若是咱们把难以快 速完成的计算都这么来处理,虽然让用户感受网站已经很坦诚的告诉本身能力有限啊,可是苛刻的用户可不必定会买这个帐,所以当有同类型网站使用新的技术手段 解决了快速实时计算问题后,假如咱们的网站仍是驻步不前,那么后果就会很严重了,那么这个时候咱们又该如何突破了?

  那么咱们就得进一步思考计算自己到底哪里出现了影响速度的问题,计算自己包含三个方面,首先是用于计算的计算资源,再就是作运算的工具即CPU,最后是计算的最终结果, 若是业务计算慢的缘由是由于数据量太大了,CPU很难快速完成,那么这个时候咱们有一些手段能够解决这个问题,咱们能够把海量数据作一个分类,例如存储系 列里说的历史交易数据和当日交易数据的分类,当日数据由于数据量有限在必定条件下能够快速计算出来,面对历史数据,若是咱们的计算结果最终是很简单的并且 在必定时间范围里是不会变化的,那么咱们可不能够这么考虑,让这些结果提早计算出来,而后将结果存储在效率更高的存储设备里例如内存,当用户请求操做这个 业务计算时候咱们只须要直接读取缓存里的计算结果就好了,这样就避免了计算,同时计算结果存储在效率高效的缓存里,用户得到响应的速度也会快多了,这个其实就是网站静态化技术里ESI技术背后的深意了。

  固然当咱们要解决网站性能问题,不太可能单独从计算或者存储一个维度来思考,通常都是把双方放在一块儿思考,按照我前面提到计算和存储介质的效率问题, 咱们发现存储实际上是最容易影响网站效率的痛点,实际状况也是如此,当网站发生计算瓶颈问题以前,更多的效率问题仍是由存储所致使的,并且复杂计算过程也是 须要存储参入才能正常完成,例如计算过程里的中间结果当超出CPU缓存大 小后咱们就不得不将中间结果放到内存里,当内存也不够的时候咱们就得放到硬盘里,因此解决计算效率问题也受到存储性能很大的影响。假如咱们仍是按照木桶理 论来理解这个问题,咱们发现无论是单纯的存储问题仍是计算和存储混合的问题,最终的短板都是其中效率最差的哪一方,而计算和存储里效率最差的一方就是网络 了,不过有些马虎的朋友可能说如今宽带好快了,我在网上下载一部几个G的电影也就几十秒,甚至有时比我硬盘拷贝还快,像你说网络是最大的短板其实不许确 的,这位朋友的想法的确有他的道理,可是不是每一个人使用的网络都是你那么快呢,并且如今移动互联网 已经普了及,移动互联网速度比普通宽带就差多了,并且你在移动设备上使用网络流量越大,成本也就越高,若是你认为我说的这些问题都不算啥,网络还和地域的 距离有关,你宽带很快,你想访问大洋彼岸美国的网站(这个网站在中国没有任何缓存处理),访问速度确定仍是快不起来,并且互联网的连通路径自己也很复杂, 例如你感受本身访问的是一个上海本土的网站,可是这个网站说不定好多重要服务器是放置在北京,这么复杂的网络环境,这么多不可控的因素还会影响网络的传输 效率,网络谈何能说本身性能比硬盘强呢?

  由此咱们就能够发现谷歌和雅虎总结的web前端优化技巧以及我这里谈的网站静态化技术大部分都是围绕如何解决网络传输效率来进行了,由于它是整个木桶 最大的短板,咱们只有首先解决了这个短板,那么再去解决其余因素的效率问题,才能发挥其做用。这里的这个解释也能够解答前不久一个网友问我,为何我讲网 站优化不多讲解如何编写高效的代码,而都是从一些和代码无关的角度来阐述的了,其实你想经过代码优化提高网站性能,你首先要解决好对网站效率影响更大更关 键的要素例如网络通信问题,不然你代码优化的再好,对最终效果影响都是有限的。

 

网站静态化处理—web前端优化—中(12)

Web前端不少优化原则都是从如何提高网络通信效率的角度提出的,可是这些原则使用的时候仍是有不少陷阱在里面,若是咱们不能深刻理解这些优化原则 背后所隐藏的技术原理,颇有可能掉进这些陷阱里,最终没有达到最佳的预期效果,今天我在这里分析下浏览器和服务端通信的一些细节问题,但愿经过分析这些细 节问题,能给你们一个启迪,能更好的理解这些优化原则背后的隐秘,最终能更好的运用这些原则。

  网站的通信技术是构建在http协议上,http协议底层通信手段使用的是tcp/ip协议,可是tcp通信协议在创建链接和断开链接这两个动做上是 很是消耗通信性能的,这主要是由于tcp/ip协议在链接创建时候的三次握手机制和断开链接时候的四次挥手机制所致,咱们来看看下面的图形:

 

  图中中间被红色标记的方块就是tcp/ip协议在创建链接时候须要发送三次报文才能确认链接是否创建成功,中间四个蓝色的方框就是说明tcp/ip协 议在断开链接时候要发四次报文才能肯定链接最终被断开,而一个具体的http请求和响应也就发送两次报文,这也就说明若是浏览器每次和服务端的交互都要新 建和关闭一个tcp/ip链接,那么浏览器和服务器之间就要往返9次报文通信,而真正用来处理用户请求的报文确只有其中的两次,换句话说这样的一个请求大 概会有80%左右的性能都不是用来处理业务需求,等因而损失了80%左右的性能,固然这个比率是9次报文交互的数据大小一致状况下得出的,若是用户业务请 求和响应的数据量比较大,那么创建链接和断开链接的性能损失占比会下降,不过就算占比下降了那也是在请求处理自己的时间变的更慢的基础上的下降,要是浏览 器和服务器之间的距离特别大,那么多出来的7次报文交换的效率问题就更加严重了,无论怎样,tcp/ip的三次握手机制和四次挥手机制只要发生都会对网络 请求效率产生重大影响。

  为了解决这个报文交互次数过多的问题,http协议自己也发生了改变,那就是http开始采用了长链接,使用长链接后网站只须要开启一个长链接,在用 户关闭浏览器关闭以前浏览器里的网页都会复用这个长链接。不过http协议的1.0版本默认是不启用长链接的,因此在使用http协议1.0版本时候我就 得手动的打开长链接,这个方法就是在http头里设置Connection: Keep-Alive,而http1.1版本里长链接是默认打开的,因此不须要咱们手动的设置,并且时下的浏览器几乎都支持http1.1协议,所以大多 时候状况下咱们是没有必要手动去打开长链接的。

  虽然http协议采用长链接后能够减小网站通信时候三次握手和四次挥手的次数,可是长链接创建起来后须要浏览器和服务器长时间维护,这自己会消耗浏览 器和服务器的性能,特别是服务器端长时间维护长链接自己还会损坏服务器处理并发的能力,因此早期浏览器会限制http1.1开启链接的数量,例如ie7这 个古董浏览器,它准许http1.1最多开启2个长链接,而http1.0由于默认使用短链接它默承认以开启4个,下面有张图能够说明,以下所示:

 

  提高浏览器加载效率的手段除了提高每一个链接的传输效率外,其实还有一种方式,这个方式就是使用多个链接进行并行加载,这个等于几我的联合起来一块儿完成 一个任务,那么效率确定就比一我的高,而页面加载时候很符合使用并发加载的场景,例如咱们让页面里的图片并行加载确定会比一个个加载图片的效率要高多了。 回到浏览器支持的链接数的问题,因为早期浏览器在http1.0和http1.1链接数的差别,某些网站例如维基百科这样的网站,它的静态资源特别多,为 了充分发挥并发的优点,它将存放这些静态资源的服务器采用http1.0协议,这样就能并行加载更多的静态资源,由于这个并行加载的整体效率提高相比 tcp/ip握手和挥手的损失要高的多,不过如今这个手法已经起不到什么做用了,由于新版的浏览器已经把两种版本的http协议支持的链接数调整一致了, 由于长链接能够复用链路,所以使用长链接的效率会比非长链接更好。

  上面链接数也是有一个限制的,这个限制就是必须是在同一个域名下,若是一个页面某些静态资源放在不一样域名下面,那么这个作法就能够增长页面里的并发数 量,例如咱们把一些不是常常变化的静态资源例如图片、外部的css文件以及javascript文件单独放置在一个静态资源服务器上,静态资源服务器对外 的url地址和页面自己的url地址不在同一个域名下,那么页面自己的并发加载链接数就会增长一倍,不过这也就意味着浏览器端要维护的长链接数会变得更 多,雅虎工程师曾经总结过一个页面里合理的域名数量,那就是两个,这个结论的提出已通过去了好多年了,如今的浏览器和服务器的性能已经今非昔比了,这个跨 域数量应该能够增长点,不过我我的认为一个页面的里包含的域名数量仍是不要太多,其实若是咱们web前端优化手段使用得当,两个不一样域名就足够用了,多了 价值不大,除非你网站状况是在特殊,例如你看看如今浏览器自己支持的链接数量已经很高了,大部分都是6,ie9甚至还达到了10,翻个倍就有12和20个 链接数,咱们在翻个倍就是24和40个,这个数字看起来就很恐怖了,一个计算机支持这么多并发,假如你在浏览器还打开个网站也是这么干的,那么浏览器的并 发数多的实在太吓人了,我估计到时计算机自己就跑不动了,因此10多个链接数很够用了,你合理发挥下这些链接数网站的性能就能有很大提高,再说了一个网站 并发链接数太多那自己就说明了你在减小http个数这个手段没有运用好。

  回到web前端优化的手段,咱们若是把这些手段再仔细分析下就会发现不少手段使用都是在同步请求这个场景下进行了,固然这些手段在合适状况下也能做用 于异步加载场景,可是异步加载场景发生并发加载以前须要一个单线程的异步加载,这个单线程的异步加载就和分布式系统里的单点故障有点像了,它颇有多是整 个流程的软肋所在,因此合理使用同步请求还能让异步操做性能更加优秀作好准备。上面我讲到浏览器在同一个域名下最多能够开启多少个链接数,可是从事web 前端开发的人都能感受到,咱们作页面开发时候实际上是无法控制这个链接数的,那么问题来了,这么多链接究竟是在什么条件下被开启的呢?这个问题很是有意思 的,咱们来看下面的瀑布图:

 

  从上面的瀑布图咱们发现,并行下载的是图片,这个推而广之要是咱们看见某些网站的网页作过并发优化处理的设计,咱们就会发现并发的资源都是纯静态的资 源,那么这个并发链接数跟咱们页面的设计存在一个怎样的关系呢?首先咱们总结一下页面里的静态资源,在页面里静态资源有html,若是html里面有内联 的css代码和javascript代码,那么这些代码也会归属于html,除了html外还有外部的css文件、外部的javascript文件和页面 里使用到的图片,那么这些要素怎样会促发页面的并行加载了,换个说法这些要素又是如何促使浏览器同时打开更多链接呢?

  首先咱们要明确一个问题,浏览器之因此能够打开更多链接数,让这么多链接并行执行是有个前提的,这个前提就是这些资源是否是被并行加载的,例如像外部 css文件,图片这样的资源,这些资源下载完毕后立刻就能够使用,由于它们下载完毕后没有逻辑性问题要处理所以下载完毕后就能够直接拿来使用,所以它们并 行加载不会影响到页面的展现问题,这个状况若是碰到javascript就有点麻烦了,外部javascript代码是包含逻辑在里面,并且有些逻辑颇有 可能会影响页面的展现,因此javascript下载完毕后,浏览器就得立刻执行,因此咱们就会看到这样的瀑布图,以下图所示:

 

  上面的空白区就是浏览器在执行javascript代码所要花费的时间。浏览器开启多少个链接是浏览器自发的行为,这个自发行为主要出于提高浏览器并 发下载效率的角度出发的。因为如今浏览器的链接基本都是采起的是http1.1协议,也就是使用的长链接,那么链接创建后这个链接就会长期维护,若是这个 长链接是单独的静态资源服务器上的长链接,这个问题倒没什么,若是这个长链接放在主域名下面,问题就来了,主域名在页面初始化加载时候会用来下载 html,若是咱们为提升并发下载效率,让这个主域名下还放置其余的静态资源,那么可能会致使浏览器和主域名的服务器下维护更多的长链接,而页面后续操做 基本是使用ajax来操做的,而ajax每每只会复用其中一个长链接,那么其余多余的长链接等于要空转了,这个空转还须要消耗浏览器和服务器的系统资源, 因此咱们发现主域名下的请求资源类型必定要认真加以控制,能迁移到单独的静态资源服务器上的必定要进行迁移,尽可能让主域名下处理的请求都是包含业务逻辑的 请求,这样就能够有效提高系统资源的使用率。这个问题进一步思考下去,咱们就会发现若是服务端的业务应用服务器以前放置一个反向代理,反向代理都是使用静 态资源服务器,而静态资源服务器对并发的承载能力是远超业务应用服务器,若是主域名下咱们不当心放置了太多静态资源,要是后台使用了反向代理,那么反向代 理也能够减轻这种长链接所形成的计算资源损失。

  上面这些场景都是在浏览器同步请求下进行了,那么换到异步请求这个并行加载静态资源的手段还有效吗?回答这个问题前,咱们首先要想一想异步加载会致使新 的静态资源被加载吗?这个固然可能,特别是在前端MVC的场景下,咱们会把模板技术放到浏览器端完成,这个时候有些html模板一开始可能会包含在 javascript代码里,做为一个变量存储下来,而这个模板里颇有可能包含好多新的图片被使用,当ajax从服务端获取数据后,解析了这个模板,而后 咱们把构造好的模板加入到页面的DOM结构里,浏览器从新渲染页面时候看到不少新图片须要加载,就有可能会开启多个链接进行并行加载来提高资源加载效率, 若是碰到经过ajax技术动态加载外部CSS文件,那么这个并行加载状况就会更加突出了,由于css文件里颇有可能包含大量的图片资源,若是咱们把不变的 静态资源都放置在了单独的静态资源服务器,那么这个并行加载就不会在主域名下打开更多长链接,因而可知,将静态资源使用单独的域名的静态资源服务器处理的 好处很是之多。

  如今http2.0协议还在起草之中,http2.0若是落地将会给web前端优化技术产生重大影响,http2.0打算在一个页面里只使用一个 tcp/Ip链接,不过http2.0会在这个链接上进行链路复用,也就是让一个链接上也能作到并行操做,让链接的利用率更高,若是http2.0落地 后,web前端里那些用于减小http链接数的手段都会失去市场了,由于协议自己就能处理好并发的问题了,到时像外部css文件,外部 javascript文件,css sprite技术说不定就要成为历史了。

 

网站静态化处理—web前端优化—下【终篇】(13)

本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了 一个事业部,不过该企业把这个事业部里的人事成本,系统运维成本特别是硬件采购的成本都由总公司来承担,固然互联网业务上的市场营销成本这块仍是由该事业 部本身承担,但是网站一年运维下来,该公司发现该事业部里最大的成本竟然不是市场营销的开销,而是短信业务和宽带使用上的开销,是否是有点让人感到意外 呢?下面我来分析下这个场景吧。

  短信这块是和通信运营商有关,很难从根本上解决,固然该企业能够考虑使用像微信这样的工具来分摊下短信的成本,可是宽带流量消耗这个问题却很难有第二 选择了,可能有人会感到诧异,一家作互联网的企业,用户都是使用本身掏钱的宽带来上网的,为啥企业会有宽带流量的成本呢?其实互联网公司的后台服务都是会 放置在IDC即数据中内心的,除非你的企业是真正的高富帅,或者你自己的核心业务就是互联网业务,这样的企业才有可能会自建数据中心,绝大部分企业都会租 用第三方的数据中心,并且有些企业为了容灾还会在不一样地域创建不一样的数据中心,不一样数据中心之间是经过专线来通信的,而专线的成本是很高的,咱们想让本身 开发的网站让更多人用,能够经过改造服务端并发处理能力来达到这个目的,可是这里还有一个制约因素,那就是服务端使用的带宽,通常而言,企业选择多大带宽 是能够估算出来,最终采用一个合理的带宽,可是,若是这家公司是电商类型网站,就颇有可能碰到像双十一啊,或者自身作大促销的状况,这个时候服务端的负载 压力就会成倍增长,远远超出平时的网络流量,如是企业会提早扩充带宽,而扩充的带宽流量是昂贵的,这样就会无形增长网站运营成本。若是咱们不去思考成本问 题,当今社会讲求环保,例如淘宝就说它们网站没完成一次交易使用的电量能够煮熟两个鸡蛋,它们网站一天下来消耗的电量至关于中国一个三线城市一天消耗的电 量,那么若是咱们能节约每次请求消耗的宽带流量其实也就是在节约能源,因此无论是从成本角度仍是从环保角度提升宽带的利用率都是有很大的现实意义的。

  Web前端优化里有一个技巧就是压缩http请求的数据量,这个技巧不少人都是简单认为http请求的数据越小,那么http处理速度就更快些,不过 我认为这结论实际上是一个相对的结论,如今的网速是愈来愈快,不少人家里接入的宽带已经使用上了光纤,50兆,百兆的宽带已经飞进了寻常百姓家了,那么这时 候其实网络传输100kb数据和传输300kb数据的效率差别基本能够忽略不计了,固然并不是每一个人网络访问速度都这么快,例如咱们使用手机的2G网络上 网,那么100kb和300kb的传输效率仍是会有很大差别的,因此压缩http请求大小这个手段在客户端这块是一种解决短板的技巧,这个短板就是照顾那 些上网速度太慢的人了,而非对人人平等的技术手段,可是这个问题换到服务端就不一样了,减小http报文的数据大小能够提高企业对宽带的利用率,是一种节约 网站运营成本的一个重要手段,所以压缩http传输数据的大小是一个颇有价值的技术手段。

  用来压缩http请求数据大小的手段不少,例如使用Gzip压缩http请求,压缩图片等等,不过我这里要特别说明一个手段那就是减小cookie存 储数据的大小,这是一个经常被忽视的压缩http请求大小的技术手段。不过cookie技术对不少初学者经常会感到差别,cookie是客户端的数据,为 什么服务端和客户端都能操做它,难道服务端也会存储一份cookie的备份吗?之因此初学者会对cookie使用有疑问,这主要是初学者不太清楚 cookie信息除了保存在浏览器端,它还会包含在http报文头里的,每一个http请求响应都会带着cookie信息进行传递,因此cookie既能够 被客户端操做也能被服务端操做,若是咱们忽视cookie这个特色,再加上咱们滥用cookie,最后cookie被撑满了,这也就意味每次请求响应的数 据量会增长,而这些信息可能大部分都不会被使用,纯粹多余。而网站在开发和维护时候很容易不自觉的让cookie变得愈来愈多,愈来愈大,若是咱们一开始 就明确cookie这个特色,提早设计cookie使用规范,那么就能够必定程度上规避cookie不合理使用致使的http数据量变大的问题。若是网站 使用了单独的静态资源服务器,而且把静态资源放置在单独的域名下面,这个时候咱们还要避免给静态资源域名下使用cookie技术,由于静态资源基本都不会 有状态信息,使用cookie只会无谓的增长请求的数据大小。

  网络是存储设备里效率最差的,若是页面加载时候还有些请求是一个坏请求,例如页面访问的某些静态资源忽然丢了,浏览器这个时候会有一个容错的作法,这 个作法具体是:浏览器不能肯定有问题的请求究竟是由于网速慢了仍是找不到,因此浏览器会屡次请求这个url,直到浏览器认为这个url的确是有问题没法访 问了,浏览器才不去继续请求了,若是碰到的资源正好是外部javascript文件,那就颇有可能阻塞整个页面的加载,因此剔除页面里的坏请求也是要常常 留心的事情。

  咱们若是再进一步分析下web前端优化的一些手段,就会发现不少优化手段其实都是基于静态资源来处理的,静态资源的特色就是在必定时间范围内不会发生 变化的,并且当用户请求静态资源时候,服务端不须要任何计算操做即消耗CPU资源就能把结果返回给客户端,静态资源这种不参与计算的特色就可让静态资源 和业务应用服务器解耦,所以咱们能够把静态资源单独抽取出来放置在CDN或者是请求效率处理更佳的静态资源服务器上。和静态资源相对的动态资源就很难作到 这点,咱们仔细回味下网站后台整个应用架构,就会发现全部网站都会使用存储系统即基本都会用数据库,并且应用服务器和数据库又是一种紧耦合的关系,由于我 们想消除存储系统的状态问题基本是不可能完成的任务,这就让应用服务器无法作成CDN的形式,所以动态资源处理想使用CDN这种减小距离对网络通信影响的 手段基本是很麻烦的。我以为网站静态化处理实际上是根据web前端优化技术产生的技术,它让网站静态化资源和动态资源分离作的更好,因此我说网站静态化技术 是充分发挥web前端优化手段的重要保证,这也就是我为何会把web前端优化的内容也要放在网站静态化处理系列里的缘由了。

  静态资源由于在必定时间里不会发生变化,容易被缓存,并且浏览器自己也有缓存机制,那么若是咱们把静态资源缓存在浏览器端,用户请求网站就不须要再去 请求网络资源,这个效率不就更高了吗?现实状况的确是如此,可是咱们想让浏览器端充分发挥这个缓存做用其实并不是那么简单,由于咱们会碰到以下的问题,具体 以下:

  问题一:网站对浏览器的控制是一种被动控制,用户才是控制浏览器的主动方,用户的不少行为都会致使网站对浏览器的缓存设计策略失效,若是缓存失效,那么用户再去访问网站时候就得从新请求资源,因此为了弥补浏览器缓存的不可靠性,CDN技术以及静态资源服务器的使用就派上用场了。

  问题二:浏览器缓存网页部分资源可让网页加载的更快,可是要作到这一点以前,咱们首先要明确什么时候采用,同时采 用何种方式让客户端缓存这些能够被缓存的资源?那么咱们在知道某个用户要访问网站了,咱们提早把须要缓存的资源发送个用户,让用户先缓存下这些资源,这个 作法确定是开国际玩笑了,通常咱们都是在用户第一次访问网站时候将能够缓存的资源缓存起来,这个时候问题又来了,那就是用户第一次访问网站时候由于须要缓 存的资源都没有被缓存,因此所有的资源都要经过网络请求下载,这个时候就会致使用户第一次访问网站页面的效率不好,有人可能认为网站又不是设计为访问一次 的产品,只要资源被缓存了网页就会更快的,要是用户以为第一次访问慢了,就先忍忍吧,之后会快的,这个想法又是再开国际玩笑了。就算用户忍受了第一次访问 慢的情形,可是若是用户使用这个网站的时间间隔是很长的,例如某些专业性的网站,它的用户可能会很长一段时间后再访问该网站,而过了这段时间后,浏览器缓 存的资源颇有可能失效了,这个时候用户再去访问又等因而第一次访问了,那么咱们这个缓存设计方案基本就是无效了。

  问题二所反映的问题也就代表咱们在如何合理使用浏览器缓存这块上是须要考虑用户的使用场景的,须要加入一些业务性的策略了,只有这样浏览器缓存方案才能充分发挥其优点。下面我就来谈论下浏览器端缓存策略设计的问题了。

  首先咱们来看一个场景,用户第一次访问网站,访问的是网站的首页,咱们按照web前端优化原则设计了网站首页,特别是使用了一个优化原则就是把css 合并成一个外部css文件,把javascript代码也合并成一个外部文件,首页都引入了这两个外部文件,这种状况首页访问至少会产生三个http请 求,但是网站首页其实没有那么复杂,也就是说首页使用的css代码和javascript代码其实并不太多,若是咱们把这些代码就放置到页面内部,那么首 页加载就只有一个请求,虽然这会致使这个请求的数据量变大,不过按照我前面说到压缩http请求数据大小,其实在提高网络传输速度上这个角度是值得商榷 的,可是多个http请求就会致使浏览器打开更多链接,而每一个链接的创建和销毁倒是十分消耗计算资源的,那么若是咱们能把三个请求合并成一个请求完成就一 定会让请求处理的更快,但是这个作法就会致使css和javascript文件无法被缓存,那么之后想复用它们就麻烦了。碰到这样的问题咱们又该如何来抉 择了?最理想的结果就是两者兼顾,可是要兼顾两者,那么页面就必定要处理这三个http请求了,咱们到底能不能作到两者兼顾了?答案是确定的,咱们能够作 到的。咱们仔细的分析下这个场景,就会发现,快速加载页面和缓存静态资源在页面首次访问这个背景下实际上是两个不一样的业务操做,用户第一次访问首页用户只会 关心页面是否快速被加载,至于加载静态资源的行为以及缓存静态资源的行为,用户是不用关心,所以咱们就能够拆分这两个操做,首先是让页面快速被加载,等页 面加载完毕后,咱们在经过异步手段来加载外部的静态资源,这样就能够作到两者兼顾了,至于如何异步加载静态资源,我在之前的文章里讲述过,这篇文章就是《探真无阻塞加载javascript脚本技术,咱们会发现不少意想不到的秘密》,不了解这个技术的朋友能够看看本篇文章。

  不过要让上面的方案发挥做用是有一个大的前置条件的,那就是咱们要判断出用户究竟是不是第一次访问,并且由于外部的css文件和外部的 javascript文件都被咱们合并成了一个文件,这也就是说首页里内嵌的css代码和javascript代码和外部文件是有一个冗余的,若是用户第 二次访问时候不须要这些操做了,那么让首页保持这个冗余是否是就没有这个必要了?特别是javascript代码,重复的javascript代码老是让 人以为不放心。这两个问题的核心仍是在于如何判断用户是否第一次访问,判断用户的行为那就是属于判断用户状态的问题了,用户的状态标记在服务端使用的是 session技术,浏览器端使用的是cookie技术,而session技术是一个临时会话存储技术,所以使用session是无法判断用户之前是否访 问过该网站,因此这里只能使用cookie技术(若是浏览器支持html5,客户端保存用户状态的信息手段就更加多了,不必定非要使用cookie了), 也就是当用户第一次访问网站时候,咱们将一些能够标记用户是否访问过网站的状态信息存储在cookie里,那么用户再次访问这个网站时候,http请求就 会把cookie信息传送给服务端,服务端经过cookie信息断定用户是否第一次访问,这个时候服务端能够剔除页面里内嵌的css代码和 javascript代码,同时能够阻止浏览器再异步加载外部css文件和外部javascript文件行为,这样用户再次访问网站的行为也不会被用户第 一次访问行为干扰了。

  上面场景里还有一个优化手段的使用是值得商榷的,那就是咱们把网站全部的css代码和javascript代码合并到一个文件里。这里我首先来说讲把 全部javascript代码合并成一个文件的问题,一个网站会包含不少不一样页面,不一样的页面由于业务场景的不一样,就会致使每一个页面都有专属的处理业务逻 辑的javascript代码,若是咱们简单的认为把javascript代码放置到外部文件就会让页面加载的更快,那么当咱们合并外部文件时候这些和页 面紧耦合的业务代码也会合并到一个文件里,最后就会致使最终的外部javascript文件变得特别大,对于浏览器而言,javascript代码过多也 会影响到页面的加载效率和javascript的执行效率,并且这个超大的外部javascript文件对于某一个功能页面而言有太多冗余的代码,因此我 们简单把所有外部javascript文件合并成一个外部javascript文件这个作法其实并非太好,所以到底哪些javascript外部文件应 该被合并这是有所选择的。并且把某些业务相关的javascript代码就写在页面,和页面一块儿被下载可能比咱们单独使用外部文件的javascript 效率更高,由于单独的外部javascript文件会增长页面http请求的个数,那么咱们在开发时候那些javascript代码须要内嵌入页面,那些 javascript代码要把放在单独外部文件里这也是咱们要注意的策略问题。

  咱们毫无原则的把外部css文件和javascript文件合并成少许的外部文件还会影响到网站的运维和浏览器的缓存策略,特别是缓存策略的失效机 制,例如网站某个页面作了css代码或者javascript代码的修改,而这些代码上生产时候要被合并到一个外部的css文件和javascript文 件里,而这些外部文件又被不少网页引用,那么咱们就不得不让不少无关的网页也须要刷新浏览器缓存,若是这个修改是做用于公共代码这个问题还好理解,要是这 个代码是用于营销活动这个特定场景下,那么这样的刷新缓存操做就会显得很是没有必要,若是有天营销活动结束了,咱们是否是还要再刷新下缓存,剔除多余的代 码呢?因此如何合并外部的css代码和javascript代码咱们仍是要应该根据业务场景进行合理的分组的。

  Web前端的工做是十分繁重的,网站是和终端用户打交道,这些终端用户都是网站的需求方,而web前端是处理终端用户需求的排头兵,用户那么多,需求 那么多,因此网站的前端页面会常常的被修改,修改的页面就要从新发布生产,这个时候咱们就要刷新浏览器的缓存了,那如何来刷新页面的缓存了,方法其实很简 单就是改变页面url的参数,通常网站的静态资源的url后面咱们会专门加上一个版本号参数,例如:

www.cnblogs.com/sharpxiajun/a.css?v=1234556

  咱们只要改变12345这个参数的值就能让浏览器从新从服务端获取静态资源,这个时候问题来了,若是外部css文件或javascript文件被不少 页面引用,那么咱们就不得不去手动的更改页面里引用这些外部文件的版本号,这个操做不免会有遗漏,就算遗漏问题好解决,若是咱们的页面是使用服务端模板开 发的,那么就可能致使生产发布时候重启生产服务器,为了静态资源发布重启服务器的确让人感受有点得不偿失。那么咱们又如何来解决这个问题呢?

  咱们分析下这个问题的本质就是页面引用外部css文件和javascript文件的行为其实包含一个动态性,那么咱们要解决这个问题就是要拆分出这个 动态性,也就是把要变化的版本号这个动态性拆分出来进行单独处理,通常咱们就会经过模板语言来从新编写link和script标签的代码,例如在jsp技 术里咱们能够自定义一个标签,将版本号做为参数传入标签里,当项目发布时候,模板引擎会根据版本参数不一样从新编译出link和script标签,可是这个 作法仍是有问题的,例如jsp页面技术,要想更改版本号就得重启服务,因此这个时候咱们把版本号的计算功能作到独立的缓存里,当文件改变后咱们经过更改配 置刷新缓存,这样就能够不用重启服务器就能刷新静态资源的版本号了。若是咱们网站使用了网站静态化处理,那么咱们能够把这个操做迁移到反向代理这边来作, 把该操做做为动静整合的一部分,若是咱们使用了ESI技术,那么无非就是刷新下ESI对应的缓存便可。这个动态刷新静态资源版本号的操做在互联网里已经很 流行了,可是如今大部分技术都是关注在如何检测静态文件是否发生变化上,例如使用md5技术计算文件的md5值啊,或者是修改下文件的名字啊,可是这些手 段使用时候都没考虑到是否重启服务器的问题,最终致使设计方案使用起来比较麻烦,我以为如何检测文件是否变化很重要,若是方案能实如今检测变化的基础上作 到不用重启服务器就能刷新缓存,这样才能让该方案更加完整和实用。

  OK了,终于把网站静态系列写完了,后面我将开启一个新的系列那就是分布式和SOA,原本我想把分布式和SOA分红两个系列,最近以为这两个系列合并 在一块儿比较好,不过写新系列前可能须要一段时间准备,最近一直写博客都没抽出时间好好看书,应该要花点时间看书好好学习下了。

相关文章
相关标签/搜索