第一章 深入WEB请求过程
1.1 B/S网络架构概述
不管网络架构如何变化,始终有一些固定的原则需要遵守.
1. 互联网上所有资源都要用一个独一无二的URL.
2. 必须基于HTTP与服务端交互.
3. 数据必须在浏览器中运行.
1.2 如何发起一个请求
发起一个HTTP请求和建立一个Socket连接区别不大.
1.根据地址栏输入的URL的域名DNS解析出IP地址.
2.根据这个IP地址和默认的80端口与远程服务器建立Socket连接.
3.浏览器根据URL组装一个get类型的HTTP请求,通过outputStream.write发送到目标服务器,服务器等待inputStream.read返回数据,断开连接.
1.3 HTTP解析
B/S网络架构的核心是HTTP.
常见的HTTP请求头
请求头 | 说明 |
---|---|
Accept-Charset | 用于指定客户端接受的字符集 |
Accept-Encoding | 用于指定可接受的内容编码,如 Accept-Encoding:gzip.deflate |
Accept-Language | 用于指定一种自然语言,如 Accept-Language:zh-cn |
Host | 用于指定被请求资源的Internet主机和端口号,如 Host:wwww.taobao.com |
User-Agent | 客户端将它的操作系统,浏览器,和其他属性告诉服务器 |
Connection | 当前连接是否继续保持,如 Connextion:Kepp-Alive |
常见的HTTP响应头
请求头 | 说明 |
---|---|
Server | 使用的服务器名称,如 Server:Apache/1.3.6(Unix) |
Content-Type | 用来指明发送给接收者的实体正文的媒体类型,如 Content-Type:text/html;charset=GBK |
Content-Encoding | 与请求报头的Accept-Encoding对应,告诉浏览器服务端采用的是什么压缩编码 |
Content-Language | 描述了资源所用的自然语言,与Accept-Language对应 |
Content-Length | 指明实体正文的长度,用以字节方式存储的十进制数字来表示 |
Keep-Alive | 保持连接时间,如 Keep-Alive:timeout=5,max=120 |
常见的HTTP状态码
请求头 | 说明 |
---|---|
200 | 客户端请求成功 |
302 | 临时跳转,跳转的地址通过Location指定 |
400 | 客户端请求有语法错误,不能被服务器识别 |
403 | 客户端收到请求,但是拒绝提供服务 |
404 | 请求的资源不存在 |
500 | 服务器发送不可预期的错误 |
1.3.2 浏览器缓存机制
使用Ctrl + F5可以清除缓存的刷新页面,原理是通过在HTTP的请求头中增加一些请求头,这些请求头会告诉服务端要获取最新的数据而不是缓存.
Cache-Control/Pragma
这个HTTP Head字段用于指定所有缓存机制在整个请求/响应链中必须服从的指令,不仅仅可以控制浏览器,还可以控制和HTTP相关的缓存或代理服务器.
Cache-Control字段的可选值
可选值 | 说明 |
---|---|
Public | 所有内容都被缓存,在响应头中设置 |
Private | 内容只缓存到私有缓存中,在响应头中设置 |
no-cache | 所有内容都不会被缓存,在请求头和响应头中设置 |
no-store | 所有内容都不会被缓存到缓存或Internet临时文件中,在响应头中设置 |
must-revalidation/proxy-revalidation | 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证,在请求头中设置 |
max-age=xxx | 缓存的内容将在xxx秒后失效,这个选项只在HTTP1.1中可用,和Last-Modified一起使用时优先级较高,在响应头中设置 |
- Cache-Control请求字段被各个浏览器支持较好,且优先级较高,和其他请求字段(如Expires)同时出现时,它会覆盖其他字段.
- Pragma字段的作用类似,最常用:Pragma:no-cache.
- Expires常用格式Sat,25 Feb 2012 12:22:17 GMT,超过这个时间值,缓存的内容将失效.
- Last-Modified字段表示一个服务器上的资源的最后修改时间.
- Etag的作用是让服务端给每个页面分配一个唯一的编号,然后通过这个编号来区分这个页面是否是最新的.
1.4 DNS域名解析
- 互联网都是通过URL来发布和请求资源的,而URL中的域名需要解析成IP地址才能与远程主机建立连接.
1.4.1 DNS域名解析过程
1.当用户在浏览器输入域名并按下回车后,浏览器会检查缓存中有没有改域名对应的街写过的的IP地址,若缓存中有,则解析过程结束.(浏览器缓存域名是有限制的,不仅大小有限制,域名被缓存的时间通过TTL属性来设置.通常情况下为几分钟到几小时)
2.若浏览器缓存中没有,浏览器会在操作系统中(hosts文件)查找是否有这个域名对应的DNS解析结果.
3.如果1,2步无法解析,操作系统会将这个域名发送给LDNS.也就是本区域的域名服务器.(电信等)这个专门的域名解析服务器性能都比较好,大约80%的域名解析都到这里就已经完成了,所以LDNS主要承担了域名的解析工作.
4.若LDNS没有解析成功,就直接到Root Server域名服务器请求解析.
5.根域名服务器返回本地域名服务器一个查询域的主域名服务器(gTLD Server)地址.gTLD是国际顶级域名服务器,如.com,.cn,.org等,全球只有13台左右.
6.本地域名服务器(Local DNS Server)再向上一步返回的gTLD服务器发送请求.
7.接受请求的gTLD服务器查找并返回此域名对应的Name Server域名服务器的地址,这个Name Server通常就是你注册的域名服务器.
8.Name Server域名服务器会查询存储的域名和IP的映射关系表,在正常情况下都根据域名得到目标IP记录,连同一个TTL值返回给DNS Server域名服务器.
9.返回该域名对应的IP和TTL值,Local DNS Server会缓存这个域名和IP的对应关系,缓存的时间由TTL值控制.
10.把缓存的结果返回给用户,用户根据TTL值缓存在本地系统中,域名解析过程结束.
1.4.3 清除缓存的域名
一般指清除本机缓存.
1.Windows执行ipconfig/flushdns命令刷新缓存.
2.Linux下通过/etc/init.d/nscd restart来清除缓存.
3.重启
4.Java应用中JVM也会缓存DNS的解析结果,在InetAdress类中完成.
清除缓存时,修改%JAVA_HOME%\lib\security\java.security配置文件.
另外,使用InetAddress类解析域名时,必须是单例模式.不然,每次创建InetAdress实例,都需要进行一次完整的域名解析,过于耗时.
1.4.4 几种域名解析方式
域名解析记录主要分为A记录,MX记录,CNAME记录,NS记录和TXT记录.
A记录
A代表Adress,用于指定域名对应的IP地址,如将wwww.baidu.com指定到115.238.23.XXX.
A记录可以将多个域名解析到同一个IP地址,但不能讲一个域名解析到多个IP地址.
MX记录
MX表示的是Mail Exchange.可以将某个域名下的邮件服务器指向自己的Mail Server,
如如果你设置A记录是指向123.12.123.123,而MX记录你设置是指向222.22.222.222,那么你的DNS服务器接收到别人的邮件路由请求时就将会将它的请求解释到222.22.222.222上去!而别人访问你的网页的时候仍然是访问123.12.123.123.
CNAME记录
全称是Canonical Name(别名解析).它可以将你注册的不同域名统统转到一个主域名上去!
与A记录不同的是,CNAME别名记录设置的可以是一个域名的描述而不一定是IP地址.
NS记录
为某个域名指定DNS解析服务器,也就是该域名有指定的IP地址的DNS服务器去解析.
TXT记录
为某个主机名或域名设置说明,如可以为baidu.com设置TXT记录为"百度一下,你就知道".
URL转发
URL转发可以转发到某一个目录下,甚至某一个文件上.
而CNAME是不可以,这就是URL转发和CNAME的主要区别所在.
1.5 CDN工作机制
CDN = 镜像(Mirror) + 缓存(Cache) + 整体负载均衡(GSLB)
1.5.2 负载均衡
1. 链路负载均衡
通过DNS Service解析成不同的IP,然后用户根据这个IP去访问不同的目标服务器.
2. 集群负载均衡
2.1 硬件负载均衡
2.2 软件负载均衡
3. 操作系统负载均衡
第二章 深入分析Java I/O的工作机制
Java的I/O类库的基本架构
- 基于字节操作的I/O接口:InputStream和OutputStream
基于字符操作的I/O接口:Writer和Reader
基于磁盘操作的I/O接口:File
-
基于网络操作的I/O接口:Socket
前两组主要是传输数据的数据格式,后两组主要是传输数据的方式.
不管是磁盘还是网络传输.最小的存储单元都是字节.
2.1.1 基于字节的I/O操作接口
1.操作数据的方式可以组合使用
OutputStream out = new BufferedOutputStream(new ObjectOutputStream(new FileoutStream("fileName")));
2.必须指定流最终写到什么地方,要么写到磁盘,要么写到网络中.
2.1.2 基于字符的I/O操作接口
1.不管是Writer还是Reader类,它们都只定义了读取或写入的数据方式的方式,但是并没有规定数据要写到哪里.
2.字符-->字节 编码
字节-->字符 解码
2.2 磁盘I/O工作机制
1.操作系统为了加速I/O访问,在内核空间使用缓存机制.
2.2.1 几种访问文件的方式
1.标准访问文件的方式
read():操作系统先检查在内核的高速缓存中有木有需要的数据,若没有,则从磁盘中读取,然后缓存在操作系统的缓存中.
writer():将数据从用户地址复制到内核空间的缓存中.什么时候写到磁盘中由操作系统决定,除非显式地调用了sync同步命令.
2.直接I/O的方式
应用程序直接访问磁盘数据,而不经过操作系统内核数据缓存区,可以减少一次从内核缓存区到用户程序缓存的数据复制.
3.同步访问文件的方式
数据的读取和写入是同步操作的.
4.异步访问文件的方式
当访问数据的线程发出请求后,线程会接着去处理其他事情,而不是阻塞等待,当等待的数据返回后继续处理下面的操作.
5.内存映射的方式
操作系统将内存中的某一块区域与磁盘中的文件关联起来.目的是减少数据从内核空间缓存到用户空间的数据复制操作.
2.2.3 Java序列化技术
将一个对象转化成一串二进制表示的字节数组,通过保存或转移这些字节数据来达成持久化的目的.
2.3.3 Java Socket的工作机制
Socket描述计算机之间完成相互通信的一种抽象对象.
建立Socket连接必须由底层TCP/IP来建立连接.
建立TCP连接需要底层IP来寻址网络中的主机.
同时,通过TCP或UDP的地址也就是端口号来指定通信的应用程序.
2.3.5 数据传输
当连接建立成功,服务端和客户端都有一个Socket实例.每个Socket都有一个InputStream和OutputStream,并通过两个对象交换数据.同时,网络I/O都是以字节流传输的,在创建Socket时,操作系统会为InputStream和OutputStream分配一定大小的缓存区.此时,就有可能会发生阻塞.另外,在两边同时传送数据可能会产生死锁,可以通过NIO来避免这种情况.
BIO:阻塞IO
2.4 NIO的工作机制
三大概念
1:Selector:调度器
2.Channel:通信信道
3.Buffer:缓冲器
2.5 I/O调优
2.5.1 磁盘I/O优化
1.增加缓存,减少磁盘访问次数
2.优化磁盘管理系统
3.设计合理的磁盘存储数据块,比如索引
4.合理的RAID策略