本文介绍一次web请求到结果返回到浏览器的过程。

1 B/S网络架构概述

B/S技术兴起后逐渐取代了C/S技术,B/S的优点是:使用统一的浏览器提供服务,用户不用额外进行配置、网络连接等,可以屏蔽服务商提供的使用服务的差异***商也不用考虑服务器等,可以直接使用基于http协议的服务器,只需关注应用逻辑。

B/S应用程序采用短连接的交互模式:一次请求就完成了一次数据交互,连接就断开,这样可以使B/S同时服务更多的用户。目前B/S网络架构大多采用如下图所示的设计。下面将具体分析这个过程。
图片说明

2 Http解析

一个http连接实质上就是建立一个socket连接的过程,我们可以通过浏览器来输入一个URL发起http请求,也可以通过其它程序来处理http请求,甚至可以自己动手写一个简单的浏览器。在linux上可以通过curl命令发起http请求。要想理解Http,先要熟悉Http Header:Http请求头和响应头可以通过浏览器的插件查看(如:FireFox中有Firebug和HttpFox,Chrome中可以通过快捷键F12打开自带插件)
图片说明
常见的http状态码参考下表,可以观察到,数字越小越接近请求成功。

状态码 说明
200 请求成功
302 临时跳转,跳转的地址通过Location指定
400 客户端的请求有语法错误,不能够被服务端识别
403 服务器收到请求,但拒绝为其提供服务
404 请求的资源不存在
500 服务器发生不可预期的错误

Http请求头中有一些常用的配置项用于控制浏览器资源的缓存,值得特别关注,Cache-Control/Pragma用于指定整个请求/响应链中的必须服从的缓存指令,expires用于指定缓存的失效时间、Last-Modified/Etag用于表示服务器上资源的最后修改时间,便于判断服务器是否应该传输最新的数据。

3 DNS域名解析

DNS对域名的解析过程参考下图。解析过程大致描述如下:

1)查找浏览器缓存中是否缓存了域名对应的IP,有则返回。缓存的大小、时间都有限制(后面环节的缓存都如此),一般为几分钟到几个小时,如果缓存时间过短则用户每次访问网站都要重新解析域名,缓存时间过长则当域名解析到的IP有变化,客户端将无法解析到变化后的IP。

2)查找操作系统缓存是否缓存了域名对应的IP,有则返回。在windows中,可以通过C:\Windows\System32\drivers\etc\hosts文件来设置操作系统的域名解析,将任意域名解析到任意IP地址,在Linux这一配置文件是/etc/hosts。

图片说明

3)将解析请求发送到DNS服务器地址,windows下可以通过ipconfig来查询,Linux下可以通过cat /etc/resolv.conf来查询DNS Server。这个LDNS解析性能很好,大约80%的域名解析到这里就完成了。LDNS也会对解析的域名进行缓存。

4)-9)由Root Server的域名服务器请求解析,Root Server返回给本地服务器一个所查询域gTLD地址,这个地址是国际顶级域名地址,比如.com,.org,本地域名服务器向gtLD服务器发送域名请求,gTLD服务器回返回给本地服务器一个查找域名服务器对应的Name Server域名服务器。Name Server域名服务器就是你注册域名的服务供应商的域名服务器。最后由Name Sever查询并返回你查询的域名服务器对应的IP地址。
图片说明
在linux和windows下都可以用nslookup来查询域名的解析结果。

Linux下还可以用dig命令来查询DNS的解析过程,可以通过增加参数+trace详细跟踪这个域名的解析过程。

dig www.taobao.com +trace

在DNS对域名解析的过程中,主要会在两个地方进行解析结果的缓存:本机和Local DNS,Local DNS的域名缓存由TTL控制,很难人工介入,但是本机的缓存可以进行修改。在windows系统可以通过执行ipconfig/flushdns命令来刷新缓存,在linux中可以通过 /etc/init.d/nscd restart来清除缓存。当然,重启仍然是很多问题的第一选择。

在Java应用中JVM也会缓存DNS的解析结果,这个缓存是由InetAddress类动态完成的,它有两种缓存策略:一种是正确解析的结果缓存,一种是失败的解析结果缓存。着两个缓存时间由%JAVA_HOME%\lib\security\java.sercurity文件中两个配置项控制,它们分别是networkadress.cache.ttl(默认值为-1,永不失效)和networkaddress.cache.negtive.ttl(默认值为10,缓存10s)。我们可以通过修改sercurity文件的默认值,在java启动参数中增加-Dsun.net.inetaddr.ttl=xxx来修改,或者通过InetAddress类动态修改。如果需要用InetAdress来解析域名,必须为单例模式,否则将非常耗时。

域名解析得到的记录有以下几种:

A记录:A代表Adress,将域名指定到对应的IP地址。可以将多个域名指定到同一个ip地址,但是不可以将一个域名解析到多个ip地址。

MX记录:MX代表Mail Exchange,可以将某个域名下的邮件服务器指向其的Mail Server,DNS会将邮件发送到MX记录设置的域名。

CNAME记录:全称是Canonical Name(别名解析),即可以为域名设置一个或者多个别名,解析其别名。

NS记录:为某个域名指定DNS解析服务器,即这个域名由指定ip地址的DNS解析器去解析。

TXT记录:为某个主机名或者域名设置说明。

4 CDN工作机制

(1) CDN架构

CDN即内容分布网络,是一种先进的流量分配网络,可以显著提高信息流动效率,从而提高用户访问网站的速度。可以这么比喻:CDN=镜像(Mirror)+缓存(Cache)+整体负载均衡(GSLB)。目前CDN都以缓存网站中的静态数据为主,比如CSS、JS、图片和静态页面等数据。CDN通常要达到以下几个目标:Scablilty(应对大量新增的用户、数据、事务的扩展能力),Security(减少恶意攻击行为造成的商业网站的业务中断),Realiabilty、Responsiveness和Performance(能处理可能的故障,通过负载均衡来实现网络的容错机制)。CDN架构如图。

图片说明

这个过程可以简述如下:某个用户访问要访问某个静态文件,首先向Local DNS解析器发送请求,其域名经过解析后会返回给Local DNS一个Name Server地址,由这个域名注册的公司的解析服务器去解析,这个解析器一般会CNAME解析到另外一个域名,这个域名访问CDN网络,由其中的GTM来最终分配一个离用户最近的CDN结点给用户,用户就可以去这个CDN结点访问静态文件了。如果这个CDN结点没有请求的文件,就会去源站获取该文件再返回给该用户。

(2) 负载均衡

负载均衡是指将工作任务分摊到多个操作单元进行。负载均衡有三种类型:

链路负载均衡(比如上述过程中通过DNS解析成不同的ip地址,然后用户根据这个ip访问不同的目标服务器),链路负载均衡会直接去访问目标服务器,而不需要经过代理,速度快,但是一旦Server挂掉,就无法访问该域名。

图片说明

集群负载均衡分为软件负载均衡和硬件负载均衡。硬件负载均衡通过转发请求来实现负载均衡,但是转发设备价格昂贵,且不能动态扩容。
图片说明

软件负载均衡成本便宜,但一般需要多次经过代理服务器,会增加网络延时。

图片说明

最后一种是操作系统负载均衡,利用操作系统的软中断或者硬中断来实现负载均衡,比如可以设置多队列网卡等。

(3) CDN动态加速

CDN动态加速时当前比较流行一种优化技术,它是再DNS解析时通过链路探测来寻找一条最好的回源路径,从而加速用户访问的效率。

图片说明

5 总结

一个请求的全过程可以简述如下:当用户在浏览器输入一个URL时,由DNS对其进行域名解析,找到请求域名对应的服务器,向该服务器发送一个get请求来获取资源。在服务端,由CDN来选择合适的服务器响应请求,实现负载均衡来平衡用户的请求,选择合适的回源链路实现动态加速。