一:网络的结构
- 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由 1、0 转化为电流强弱来进行传输,到达目的地后转化为1、0,也就是我们常说的模数转换与数模转换)。这一层的数据叫做比特。
- 数据链路层:主要将从物理层接收的数据进行 MAC 地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
- 网络层:主要将从下层接收到的数据进行 IP 地址的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
- 传输层:定义了一些传输数据的协议和端口号(WWW 端口 80 等), 主要是将从下层接收的数据进行分段进行传输,到达目的地址后在进行重组。常常把这一层数据叫做段。
- TCP:传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据
- UDP:用户数据报协议,与 TCP 特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如 QQ 聊天数据就是通过这种方式传输的
- 会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或或者接受会话请求(设备之间需要互相认识,可以是 IP 也可以是 MAC 或者是主机名)
- 表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等))
- 应用层 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的
TCP和UDP
首部不同:UDP 首部 8 个字节,TCP 首部最低 20 个字节。
协议不同:
TCP 对应的协议:
- FTP:定义了文件传输协议,使用 21 端口。常说某计算机开了 FTP 服务便是启动了文件传输服务。下载文件,上传主页,都要用到 FTP 服务。
- Telnet:它是一种用于远程登陆的端口,用户可以自己的身份远程连接到计算机上,通过这种端口可以提供一种基于 DOS 模式下的通信服务。如以前的 BS 是-纯字符界面的,支持 BS 的服务器将 23 端口打开,对外提供服务。
- SMTP:定义了简单邮件传送协议,现在很多邮件服务器都用的是这个协议,用于发送邮件。如常见的免费邮件服务中用的就是这个邮件服务端口,所以在电子邮件设置-中常看到有这么 SMTP端口设置这个栏,服务器开放的是 25 号端口。
- POP3:它是和 SMTP 对应,POP3 用于接收邮件。通常情况下,POP3 协议所用的是 10 端口。也是说,只要你有相应的使用 POP3 协议的程序(例如 Foxmail 或 Outlok),就可以不以 Web 方式登陆进邮箱界面,直接用邮件程序就可以收到邮件(如是 163 邮箱就没有必要先进入网易网站,再进入自己的邮箱来收信)。
- HTP 协议:是从 Web 服务器传输超文本到本地浏览器的传送协议。
UDP 对应的协议:
- DNS:用于域名解析服务,将域名地址转换为 IP 地址。DNS 用的是 53 号端口。
- SNMP:简单网络管理协议,使用 16 号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
- TFP(Trival File Transfer Protcal),简单文件传输协议,该协议在熟知端口 69 上使用 UDP服务。
二:TCP/IP 原理
TCP/IP协议族 由四个层次组成:网络接口层、网络层、传输层、应用层
- 网络访问层(Network Access Layer):主机必须使用某种协议与网络相连。
- 网络层(Internet Layer):整个体系结构的关键部分,其功能是使主机可以把分组发往任何网络,并使分组独立地传向目标。这些分组可能经由不同的网络,到达的顺序和发送的顺序也可能不同。高层如果需要顺序收发,那么就必须自行处理对分组的排序。互联网层使用因特网协议(IP,Internet Protocol)。
- 传输层(Tramsport Layer-TCP/UDP):使源端和目的端机器上的对等实体可以进行会话。在这一层定义了两个端到端的协议:传输控制协议(TCP,Transmission Control Protocol)和用户数据报协议(UDP,User Datagram Protocol)。TCP 是面向连接的协议,它提供可靠的报文传输和对上层应用的连接服务。为此,除了基本的数据传输外,它还有可靠性保证、流量控制、多路复用、优先权和安全性控制等功能。UDP 是面向无连接的不可靠传输的协议,主要用于不需要 TCP 的排序和流量控制等功能的应用程序。
- 应用层(Application Layer):包含所有的高层协议,包括:虚拟终端协议(TELNET,
TELecommunications NETwork)、文件传输协议(FTP,File Transfer Protocol)、电子邮件传输协议(SMTP,Simple Mail Transfer Protocol)、域名服务(DNS,Domain Name Service)、网上新闻传输协议(NNTP,Net News Transfer Protocol)和超文本传送协议(HTTP,HyperText Transfer Protocol)等。
三:TCP
1. 数据包说明
- 源端口号( 16 位):它(连同源主机 IP 地址)标识源主机的一个应用进程。
- 目的端口号( 16 位):它(连同目的主机 IP 地址)标识目的主机的一个应用进程。这两个值加上 IP 报头中的源主机 IP 地址和目的主机 IP 地址唯一确定一个 TCP 连接。
- 顺序号 seq( 32 位):用来标识从 TCP 源端向 TCP 目的端发送的数据字节流,它表示在这个报文段中的第一个数据字节的顺序号。
如果将字节流看作在两个应用程序间的单向流动,则TCP 用顺序号对每个字节进行计数。序号是 32bit 的无符号数,序号到达 232-1 后又从 0 开始。
当建立一个新的连接时, SYN 标志变 1 ,顺序号字段包含由这个主机选择的该连接的初始顺序号 ISN ( Initial Sequence Number )。 - 确认号 ack( 32 位):包含发送确认的一端所期望收到的下一个顺序号。因此,确认序号应当是上次已成功收到数据字节顺序号加 1 。只有 ACK 标志为 1 时确认序号字段才有效。
TCP 为应用层提供全双工服务,这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必须保持每个方向上的传输数据顺序号。 - TCP 报头长度( 4 位):给出报头中 32bit 字的数目,它实际上指明数据从哪里开始。需要这个值是因为任选字段的长度是可变的。这个字段占 4bit ,因此 TCP 最多有 60 字节的首部。然而,没有任选字段,正常的长度是 20 字节。
- 保留位( 6 位):保留给将来使用,目前必须置为 0 。
- 控制位( control flags , 6 位):在 TCP 报头中有 6 个标志比特,它们中的多个可同时被设置为 1 。依次为:
- URG :为 1 表示紧急指针有效,为 0 则忽略紧急指针值。
- ACK :为 1 表示确认号有效,为 0 表示报文不包含确认信息,忽略确认号字段
- PSH :为 1 表示是带有 PUSH 标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
- RST :用于复位由于主机崩溃或其他原因而出现错误的连接。它还可以用于拒绝非法的报文段和拒绝连接请求。一般情况下,如果收到一个 RST 为 1 的报文,那么一定发生了某些问题。
- SYN :同步序号,为 1 表示连接请求,用于建立连接和使顺序号同步
- FIN :用于释放连接,为 1 表示发送方没有数据发送,即关闭本方数据流
- 窗口大小( 16 位):数据字节数,表示从确认号开始,本报文的源方可以接收的字节数,即源方接收窗口大小。窗口大小是一个 16bit 字段,因而窗口大小最大为 65535 字节。
- 校验和( 16 位):此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证。
- 紧急指针( 16 位):只有当 URG 标志置 1 时紧急指针才有效。TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
- 选项:最常见的可选字段是最长报文大小,又称为 MSS(Maximum Segment Size) 每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN 标志的那个段)中指明这个选项,它指明本端所能接收的最大长度的报文段。选项长度不一定是 32 位字的整数倍,所以要加填充位,使得报头长度成为整字数。
- 数据: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
2. 三次握手
可以看成是某男生追某女生的过程。
- 男生向女生告白,说我喜欢你,然后男生等待女生的回应
- 女生收到男生的告白,而且该女生也喜欢次男生,她就可以给男生回应,说:我也喜欢你。
- 男生收到该女生的回应,确认女生也喜欢他,开心的发送消息说:那我们正式交往吧!女生收到并确认男生的信息后,开心的说:好啊我们现在开始交往!
- 第一次握手:主机 A 发送位 SYN=1,随机产生 seq number=1234567 的数据包到服务器,主机 B由 SYN=1 知道,A 要求建立联机;
- 第二次握手:主机 B 收到请求后要确认联机信息,向 A 发 送 ack number=( 主 机 A 的seq+1),SYN=1,ACK=1,随机产生 seq=7654321 的包
- 第三次握手:主机 A 收到后检查 ack number 是否正确,即第一次发送的 seq number+1,以及位码ACK是否为 1,若正确,主机 A 会再发送 ack number=(主机 B 的 seq+1),ack=1,主机 B 收到后确认seq 值与 ACK=1 则连接建立成功。
3. 四次挥手
这个过程相当于男女双方分手的过程。
- 女方有了外遇,向男方提出分手,等待男方的回应
- 男方听到这个消息,伤心的对女方说:好吧!祝你幸福。女方确认后开心的跟高富帅跑了。
- 过段时间,男方得知真相发现自己被绿了。于是很不爽的跟女方说:应该我跟你说分手的,你这个绿茶婊!
- 女方听到并确认是男方的信息,碰巧刚被高富帅甩了,赌气的骂了句:滚吧你!男方头也不回的走了。女方以为男方会来挽回她,等了一下后,发现男方真的狠下心了,于是也无奈的走了
TCP 建立连接要进行三次握手,而断开连接要进行四次。这是由于 TCP 的半关闭造成的。因为 TCP 连接是全双工的(即数据可在两个方向上同时传递),所以进行关闭时每个方向上都要单独进行关闭。这个单方向的关闭就叫半关闭。当一方完成它的数据发送任务,就发送一个 FIN 来向另一方通告将要终止这个方向的连接。
- 关闭客户端到服务器的连接:
- 首先客户端 A 发送一个 FIN,用来关闭客户到服务器的数据传送,然后等待服务器的确认。其中终止标志位 FIN=1,序列号 seq=u
- 服务器收到这个 FIN,它发回一个 ACK,确认号 ack 为u+1,序列号seq=v;此时TCP服务器进程通知高层应用进程,释放客户端到服务器的连接(半关闭),CLOSE_WAIT 是要等待自己(服务器)把传输的东西发送完
- 客户端验证ack是否为u+1,并且ACK=1,是则验证成功,释放连接
- 关闭服务器到客户端的连接
- 服务器也是发送一个 FIN 给客户端,FIN=1,序列号seq=w,ACK=1,ack=u+1
- 客户段收到 FIN 后检查 ack number 是否正确,即第一次发送的 seq number+1,以及位码ACK是否为 1,若正确,发回一个 ACK 报文确认,ack=w+1,序列化 seq =u+1;等待一段时间后关闭(TIME_WAIT阶段要等待2个MSL时间才关闭, 因为网络原因可能要重发可能丢失的 ACK 报文,保证可靠地实现 TCP 全双工连接的终止;并且允许老的重复分节在网络中消逝 )
- 主机 B 收到后确认seq 值与 ACK=1 则关闭连接
4. tcp 粘包问题
Nagle算法
nagle算法的核心思想是允许网络中最多只能有一个小分组被发送,而待发送的其它小分组会被缓存起来重新分组成一个”较大的”小分组,直到合适的时机再发送
- 收到前一个数据包报文段的ACK确认
- 当前字符属于紧急数据
- 缓存的字符数据到达数据包报文段的最大长度
在一些场景下可以提高网络利用率,降低包处理的主机资源消耗并且工作做得很好,当传输数据存在大量交互数据时,nagle算法可以有效减少网络中的报文段个数,从而减小网络拥塞的出现
但是对于那些需要实时预览的通讯程序而言,客户端可能需要不断发送更新数据并得到服务器的响应,这种情况下nagle算法会造成客户端明显的延迟
延迟ACK确认
如果tcp对每个数据包都发送一个ack确认,那么只是一个单独的数据包为了发送一个ack代价比较高,所以tcp会延迟一段时间,如果这段时间内有数据发送到对端,则捎带发送ack,如果在延迟ack定时器触发时候,发现ack尚未发送,则立即单独发送
可以避免糊涂窗口综合症,在发送数据的时候将ack捎带发送,不必单独发送ack;如果延迟时间内有多个数据段到达,那么允许协议栈发送一个ack确认多个报文段;
当Nagle遇上延迟ACK时,如果另一端发生ACK延迟确认,同时本端又需要等待另一端发送确认后才会发送一个数据包,因此会造成延迟
改进Nagle算法
直接忽略大包的确认,只要检查到最近的一个小包是否被确认,则可以继续发送,否则延迟等待
这样保证了控制小包的数量(同时只有一个未确认的小包)。同时又放宽了条件,尽量减少ack延迟对nagle算法造成的损害。缩短了延迟,提高了带宽利用率
static inline int tcp_minshall_check(const struct tcp_sock *tp)
{
return after(tp->snd_sml,tp->snd_una) &&
!after(tp->snd_sml, tp->snd_nxt);
}
粘包问题:
5. TCP的可靠性
- 数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢
弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据; - 数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据缓存起来,进行重新排序后才交给应用层
- 数据包分片:TCP会按照MTU合理分片
- 丢弃重复数据:对于重复数据,能够丢弃重复数据;
- 应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确
认不是立即发送,通常将推迟几分之一秒; - 超时重发:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
- 流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一
端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区
溢出,这就是流量控制。- 可变大小的滑动窗口
- 拥塞控制:当网络拥塞时,减少数据的发送。发送方让自己的发送窗口等于拥塞窗口
- 慢启动
- 拥塞避免
- 快重传和快恢复
- 滑动窗口:安全性
关于流量控制和拥塞控制,可以参考我之前的博客:《计算机网络》学习笔记(4)——运输层
6. TCP的状态
- CLOSED:起始点,在超时或者连接关闭时候进入此状态。
- LISTEN:server 端在等待连接过来时候的状态,server端为此要调用 socket的bind,listen 函数,就能进入此状态。此称为应用程序被动打开(等待客户端来连接)。
- SYN_SENT:客户端发起连接,发送 SYN 给服务器端。如果服务器端不能连接,则直接进入CLOSED 状态。
- SYN_RCVD:跟 3 对应,服务器端接受客户端的 SYN 请求,服务器端由 LISTEN 状态进入SYN_RCVD 状态。同时服务器端要回应一个 ACK,同时发送一个 SYN 给客户端;另外一种情况,客户端在发起 SYN 的同时接收到服务器端得 SYN 请求,客户端就会由 SYN_SENT到SYN_RCVD 状态。
- ESTABLISHED:服务器端和客户端在完成 3 次握手进入状态,说明已经可以开始传输数据了
以上是建立连接时服务器端和客户端产生的状态转移说明。
下面,我们来看连接关闭时候的状态转移说明,关闭需要进行 4 次双方的交互,还包括要处理一些善后工作(TIME_WAIT 状态),注意,这里主动关闭的一方或被动关闭的一方不是指特指服务器端或者客户端,是相对于谁先发起关闭请求来说的:
- FIN_WAIT_1:主动关闭的一方,由状态 5 进入此状态,具体的动作是发送FIN给对方
- FIN_WAIT_2:主动关闭的一方,接收到对方的 FIN ACK,进入此状态。由此不能再
接收对方的数据。但是能够向对方发送数据。 - CLOSE_WAIT:接收到 FIN 以后,被动关闭的一方进入此状态。具体动作时接收到FIN,同时发送 ACK。
- LAST_ACK:被动关闭的一方,发起关闭请求,由状态 8 进入此状态。具体动作时
发送 FIN给对方,同时在接收到 ACK 时进入 CLOSED 状态。 - CLOSING:两边同时发起关闭请求时,会由 FIN_WAIT_1 进入此状态。具体动作是,接收到 FIN 请求,同时响应一个 ACK。
- TIME_WAIT:最纠结的状态来了。从状态图上可以看出,有 3 个状态可以转化成
它,我们一来分析:- 由 FIN_WAIT_2 进入此状态:在双方不同时发起 FIN 的情况下,主动关闭的一方在完成自身发起的关闭请求后,接收到被动关闭一方的 FIN 后进入的状态。
- 由 CLOSING 状态进入:双方同时发起关闭,都做了发起 FIN 的请求,同时接收到了FIN 并做了ACK 的情况下,由 CLOSING 状态进入。
- 由 FIN_WAIT_1 状态进入:同时接受到 FIN(对方发起),ACK(本身发起的 FIN 回应),与b 的区别在于本身发起的 FIN 回应的 ACK 先于对方的 FIN 请求到达,而 b 是 FIN 先到达。这种情况概率最小。
四:HTTP
HTTP 是一个无状态的协议。无状态是指客户机(Web 浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息
HTTP 遵循请求(Request)/应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有 HTTP 连接都被构造成一套请求和应答。
1. 请求报文、请求方法、响应报文、响应状态码
可以参考我之前的博客:十分钟了解Http(1)——HTTP的报文到底是什么?
2. 传输流程
-
地址解析:如用客户端浏览器请求这个页面:http://localhost.com:8080/index.html 从中分解出协议名、主机名、端口、对象路径等部分,需要域名系统 DNS 解析域名 localhost.com,得到主机的 IP 地址。对于我们的这个地址,解析得到的结果如下:
- 协议名:http
- 主机名:localhost.com
- 端口:8080
- 对象路径:/index.html
-
封装 HTTP 请求数据包:把以上部分结合本机自己的信息,封装成一个 HTTP 请求数据包
-
封装成 TCP 包并建立连接:封装成 TCP 包,建立 TCP 连接(TCP 的三次握手)
-
客户机发送请求命令:建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息(包括请求修饰符、客户机信息和可能的内容)
-
服务器响应:服务器接到请求后,定位请求资源。服务器将资源复本写到 TCP 套接字,由客户端读取给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息(包括服务器信息、实体信息和可能的内容)
-
服务器关闭 TCP 连接:一般情况下,一旦 Web 服务器向浏览器发送了请求数据,它就要关闭 TCP 连接。然后如果浏览器或者服务器在其头信息加入Connection:keep-alive,TCP 连接在发送后服务器将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
-
客户端浏览器解析 HTML 内容:客户端浏览器读取响应数据 HTML,根据 HTML 的语法对其进行格式化,并在浏览器窗口中显示
3. HTTP 状态
4:Http的长连接和短连接
短连接:在 HTTP/1.0 中默认使用短连接。也就是说,客户端和服务器每进行一次 HTTP
操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 HTTP 会话。
长连接:而从 HTP/1. 起,默认使用长连接,用以保持连接特性。使用长连接的 HTTP
协议,会在响应头加入这行代码:
conection:keep-alive
实现长连接需要客户端和服务端都支持长连接
区别
- 长连接:多用于操作频繁,点对点的通讯,而且连接数不能太多情况。每个 TCP 连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,二次处理时直接发送数据包就 OK 了,不用建立 TCP 连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成 socket 错误,而且频繁的 socket创建也是对资源的浪费。
- 短连接:像 WEB 网站的 http 服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像 WEB 网站这么频繁的成千上万个客户端的连接用短连接会更省一些资源。所以并发量大,但每个用户无需频繁操作情况下需用短连接
5:无状态的Http
HTTP协议本身是无状态的,浏览器发起的每个HTTP请求,对于服务端而言都是彼此独立的。维持HTTP状态的机制就是会话机制。
会话机制一般有两种实现方案,一种是基于Session实现,一种是基于Cookie实现。这两种方案的本质区别是前者是将用户状态信息保存在服务端,后者是将用户状态信息保存在客户端。
(1)session
解决http协议无状态问题的服务端解决方案,它能让客户端和服务端一系列交互动作变成一个完整的事务,能使网站变成一个真正意义上的软件
- 服务端session:浏览器第一次访问服务器会在服务器端生成一个session,有一个session_id和它对应(一个由24个字符组成的随机字符串),tomcat生成的session_id叫做jsession_id
- 客户端session:服务器会给浏览器分发一个 session_id作为标识,默认是以cookie的形式存储在客户端,所以当用户禁用了cookie的话,服务器端就得不到session_id
(可以使用url的方式来存储客户端Session。也就是将session_id直接写在了url中:或者作为URL路径的附加信息,或者作为查询字符串附加在URL后面。也可以通过表单隐藏字段传递)
产生方式:服务端调用HttpServletRequest的getSession(true)的时候创建,tomcat的ManagerBase类提供创建sessionid的方法:随机数+时间+jvmid
存储方式:tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,Redis
销毁方式:session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session
- 程序调用HttpSession.invalidate()
- 距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间
- 服务器进程被停止
(2)cookie
cookie 是 Web 服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个 Web
服务器存储 cookie。以后浏览器在给特定的 Web 服务器发请求的时候,同时会发送所有为该服务器存储的 cookie
- 内存中Cookie(不设置过期时间):关闭浏览器后进程消失,进程中的Cookie自然就消失了,那么session _id也跟着消失了
- 硬盘中Cookie(设置了过期时间):session_id将长期保存在硬盘上的Cookie中,直到失效为止
(3)区别
- session的运行依赖session_id,session_id存储在cookie中。如果禁用了cookie,那么session也会失效(但是可以通过其他方式实现)
- session能够存储任意Java对象,cookie只能存储字符串
- session可以存储在文件、内存中。
- cookie不安全,会被他人分析本地的cookie并进行cookie欺骗;session比较安全,一般用于用户验证
- session性能不太好,会在一段时间内保存在服务器上,当访问增加时开销大;cookie速度快,保存在客户端上
- cookie保存的数据不能超过4K,一个站点最多保存20个cookie
6. Http各个版本
http1.1与 http1.0 的区别
- http1.0 需要 keep-alive 参数来告知服务器要建立一个长连接,而 http1.1 默认支持长连接
- http 1.1 支持只发送 header 信息(不带任何 body 信息),如果服务器认为客户端有权限请求服务器,则返回 100,否则返回 401。客户端如果接受到 100,才开始把请求 body 发送到服务器。这样当服务器返回 401 的时候,客户端就可以不用发送请求 body 了,节约了带宽。
- http1.0 没有 host 域,http1.1 才支持这个参数。
- http1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,http1.1 则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
http1.0 与 http2.0 的区别
- 新的二进制格式(Binary Format):http1.x 的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认 0和 1 的组合。基于这种考虑 http2.0 的协议解析决定采用二进制格式,实现方便且健壮。
- 多路复用(MultiPlexing):即连接共享,建立起一个连接请求后,可以在这个链接上一直发送,不要等待上一次发送完并且受到回复后才能发送下一个(http1.0 是这样),可以同时发送多个请求,互相并不干扰。
- header 压缩: http1.x 的 header 带有大量信息,而且每次都要重复发送,http2.0 利用 HPACK 对消息头进行压缩传输,客服端和服务器维护一个动态链表(当一个头部没有出现的时候,就插入,已经出现了就用表中的索引值进行替代),将既避免了重复 header 的传输,又减小了需要传输的大小。
- 服务端推送(server push):就是客户端请求 html 的时候,服务器顺带把此 html 需要的 css,js也一起发送给客服端,而不像 http1.0 中需要请求一次 html,然后再请求一次 cs,然后再请求一次 js。
7. 转发和重定向
转发过程:
- 客户浏览器发送 http 请求
- web 服务器接受此请求
- 调用内部的一个方法在容器内部完成请求处理和转发动作,将目标资源发送给客户;在这里,转发的路径必须是同一个 web 容器下的 url,其不能转向到其他的 web 路径上去,中间传递的是自己的容器内的 request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
重定向过程:
- 客户浏览器发送 http 请求
- web 服务器接受后发送 302 状态码响应及对应新的location 给客户浏览器
- 客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求url 是新的 location 地址
- 服务器根据此请求寻找资源并发送给客户。在这里 location 可以重定向到任意 URL,重定向行为是浏览器做了至少两次的访问请求的。
8. HTTPS
HTTPS(Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP 通道,简单讲是 HTTP 的安全版。即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL。其所用的端口号是 443。
HTTPS和HTTP
- http 无需证书,而 https 需要证书。https 协议需要到 ca 申请证书,一般免费证书较少,因而需要一定费用。
- http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl加密传输协议。
- http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 43。
- http 的连接很简单,是无状态的;https 协议是由 ssl+http 协议构建的,可进行加密传输、身份认证的网络协议
- 在 OSI 网络模型中,http 工作于应用层,而 https 工作在传输层
过程
建立连接获取证书
SSL 客户端通过 TCP 和服务器建立连接之后(443 端口),并且在一般的 tcp 连接协商(握手)过程中请求证书。即客户端发送 https 请求,传送客户端 SSL 协议版本号、支持的加密算法、随机数等,服务器端会回应一个数据包,把自己支持的加密算法、随机数和证书等回传给客户端。(证书里面包含了服务器信息:域名。申请证书的公司,公共秘钥)。
证书验证
Client 在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。
数据加密和传输
如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。
客户端向服务器发出信息,指明后面的数据使用该对称密钥进行加密,同时通知服务
器 SSL 握手结束。服务器接收到信息,使用对称密钥通信,通知握手接收。
SSL 工作原理
RSA 握手协议
第一步,Client 给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
第二步,Server 确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。
第三步,Client 确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给 Server。
第四步,Server 使用自己的私钥,获取 Client 发来的随机数
第五步,Client 和 Server 根据约定的加密方法,使用前面的三个随机数,生成” 对话密钥”(sesion key),用来加密接下来的整个对话过程。
记录协议
记录协议在客户机和服务器握手成功后使用,即客户机和服务器鉴别对方和确定安全信息交换使用的算法后,进入SSL记录协议,记录协议对数据传输提供保密性和完整性
警报协议
客户机和服务器发现错误时,向对方发送一个警报消息。如果是致命错误,则算法立即关闭SSL连接,双方还会先删除相关的会话号,秘密和密钥。
每个警报消息共2个字节,第1个字节表示错误类型,如果是警报,则值为1,如果是致命错误,则值为2;第2个字节制定实际错误类型。
五:DNS和CDN
DNS的解析过程
- 输入网址
- 根据域名,查询DNS,获取IP地址
- 浏览器自身的DNS缓存
- 操作系统的DNS缓存
- 本地的HOST文件
- 发起一个DNS的系统调用
- 宽度运营服务器查看本地缓存
- 运营服务器发起迭代DNS解析请求
- 浏览器获得域名对应的IP地址后,发起三次握手
- TCP/IP建立连接
- 客户端浏览器发起一个 htp 会话
- 在客户端的传输层,把 HTP 会话请求分成报文段,添加源和目的端口
- 客户端的网络层通过查找路由表确定如何到达服务器,期间可能经过多个路由器
- 包通过链路层发送到路由器,通过邻居协议查找给定的 ip 地址和 MAC 地址,然后发送 ARP 请求查找目的地址,如果得到回应后就可以使用 ARP 的请求应答交换的 ip 数据包,发送 Ip 数据包到达服务器的地址。
- 服务器接收请求,根据路径参数,经过后端的处理后生成视图返回给浏览器
- 浏览器解析和渲染HTML页面
CDN(Content Delivery Network)
内容分发网络,目的就是通过现有的 Internet 中增加一新的网络架构,将网站内容发布到离用户最近的网络“边缘”,提高用户访问网站的速度,所以更像是增加了一层 CACHE(缓存)层,一般包含分发服务系统、负载均衡系统和管理系统
功能:当用户访问加入 CDN 服务的网站时,域名解析请求将最终交给全局负载均衡 DNS 进行处理。全局负载均衡 DNS 通过一组预先定义好的策略,将当时最接近用户的节点地址提供给用户,使用户能够得到快速的服务。
分发服务系统
其基本的工作单元就是各个 Cache 服务器。负责直接响应用户请求,将内容快速分发到用户;同时还负责内容更新,保证和源站内容的同步。
根据内容类型和服务种类的不同,分发服务系统分为多个子服务系统,如:网页加速服务、流媒体加速服务、应用加速服务等。每个子服务系统都是一个分布式的服务集群,由功能类似、地域接近的分布部署的 Cache 集群组成。
在承担内容同步、更新和响应用户请求之外,分发服务系统还需要向上层的管理调度系统反馈各个Cache 设备的健康状况、响应情况、内容缓存状况等,以便管理调度系统能够根据设定的策略决定由哪个 Cache 设备来响应用户的请求。
负载均衡系统:
负载均衡系统是整个 CDN 系统的中枢。负责每个节点中各个 Cache 的负载均衡,保证节点的工作效率;同时,负载均衡设备还负责收集节点与周围环境的信息,保持与全局负载DNS 的通信,实现整个系统的负载均衡。确定提供给用户的最终访问地址。使用分级实现。
最基本的两极调度体系包括全局负载均衡(GSLB)和本地负载均衡(SLB)。
- GSLB 根据用户地址和用户请求的内容,主要根据就近性原则,确定向用户服务的节点。一般通过 DNS解析或者应用层重定向(Http 3XX 重定向)的方式实现。
- SLB 主要负责节点内部的负载均衡。当用户请求从 GSLB 调度到 SLB 时,SLB 会根据节点内各个Cache 设备的工作状况和内容分布情况等对用户请求重定向。SLB 的实现有四层调度(LVS)、七层调度(Nginx)和链路负载调度等。
四层负载均衡(目标地址和端口交换)
主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
以常见的 TCP 为例,负载均衡设备在接收到第一个来自客户端的 SYN 请求时,即通过上述方式选择一个最佳的服务器,并对报文中目标 IP 地址进行修改(改为后端服务器 IP),直接转发给该服务器。
TCP 的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。
实现四层负载均衡的软件有:
- F5:硬件负载均衡器,功能很好,但是成本很高。
- lvs:重量级的四层负载软件。
- nginx:轻量级的四层负载软件,带缓存功能,正则表达式较灵活。
- haproxy:模拟四层转发,较灵活。
七层负载均衡(内容交换)
所谓七层负载均衡,也称为“内容交换”,也就是主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
七层应用负载的好处,是使得整个网络更智能化。例如访问一个网站的用户流量,可以通过七层的方式,将对图片类的请求转发到特定的图片服务器并可以使用缓存技术;将对文字类的请求可以转发到特定的文字服务器并可以使用压缩技术。
实现七层负载均衡的软件有:
- haproxy:天生负载均衡技能,全面支持七层代理,会话保持,标记,路径转移;
- nginx:只在 http 协议和 mail 协议上功能比较好,性能与 haproxy 差不多;
- apache:功能较差
- Mysql proxy:功能尚可。
负载均衡算法/策略
- 轮循均衡(Round Robin):每一次来自网络的请求轮流分配给内部中的服务器,从 1 至 N 然后重新开始。此种均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况。
- 权重轮循均衡(Weighted Round Robin):根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器 A 的权值被设计成 1,B 的权值是 3,C 的权值是 6,则服务器 A、B、C 将分别接受到 10%、30%、60%的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。
- 随机均衡(Random):把来自网络的请求随机分配给内部中的多个服务器。
- 权重随机均衡(Weighted Random):此种均衡算法类似于权重轮循算法,不过在处理请求分担时是个随机选择的过程
- 响应速度均衡(Response Time 探测时间):负载均衡设备对内部各服务器发出一个探测请求(例如 Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。此种均衡算法能较好的反映服务器的当前运行状态,但这最快响应时间仅仅指的是负载均衡设备与服务器间的最快响应时间,而不是客户端与服务器间的最快响应时间。
- 最少连接数均衡(Least Connection):对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。此种均衡算法适合长时处理的请求服务,如 FTP。
- 处理能力均衡(CPU、内存):此种均衡算法将把服务请求分配给内部中处理负荷(根据服务器 CPU 型号、CPU 数量、内存大小及当前连接数等换算而成)最轻的服务器,由于考虑到了内部服务器的处理能力及当前网络运行状况,所以此种均衡算法相对来说更加精确,尤其适合运用到第七层(应用层)负载均衡的情况下。
- DNS 响应均衡(Flash DNS):在此均衡算法下,分处在不同地理位置的负载均衡设备收到同一个客户端的域名解析请求,并在同一时间内把此域名解析成各自相对应服务器的 IP 地址并返回给客户端,则客户端将以最先收到的域名解析 IP 地址来继续请求服务,而忽略其它的 IP 地址响应。在种均衡策略适合应用在全局负载均衡的情况下,对本地负载均衡是没有意义的。
- 哈希算法:一致性哈希一致性 Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
- IP 地址散列(保证客户端服务器对应关系稳定):通过管理发送方 IP 和目的地 IP 地址的散列,将来自同一发送方的分组(或发送至同一目的地的分组)统一转发到相同服务器的算法。当客户端有一系列业务需要处理而必须和一个服务器反复通信时,该算法能够以流(会话)为单位,保证来自相同客户端的通信能够一直在同一服务器中进行处理。
- URL 散列:通过管理客户端请求 URL 信息的散列,将发送至相同 URL 的请求转发至同一服务器的算法。
Nginx 反向代理负载均衡
反向代理服务器在接收访问用户请求后,会代理用户重新发起请求代理下的节点服务器,最后把数据返回给客户端用户。在节点服务器看来,访问的节点服务器的客户端用户就是反向代理服务器,而非真实的网站访问用户。
upstream_module 和健康检测
ngx_http_upstream_module 是负载均衡模块,可以实现网站的负载均衡功能即节点的健康检查,upstream 模块允许 Nginx 定义一组或多组节点服务器组,使用时可通过proxy_pass 代理方式把网站的请求发送到事先定义好的对应 Upstream 组的名字上
proxy_pass 请求转发
proxy_pass 指令属于 ngx_http_proxy_module 模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过 location 功能匹配指定的 URI,然后把接收到服务匹配 URI 的请求通过 proyx_pass 抛给定义好的 upstream 节点池。
LVS
普通的负载均衡软件,实现对请求数据包的转发、传递,从负载均衡下的节点服务器来看,接收到的请求还是来自访问负载均衡器的客户端的真实用户。
IPVS 模块
LVS 的 IP 负载均衡技术是通过 IPVS 模块来实现的,IPVS 是 LVS 集群系统的核心软件,它的主要作用是:安装在 Director Server 上,同时在 Director Server 上虚拟出一个 IP 地址,用户必须通过这个虚拟的 IP 地址访问服务器。这个虚拟 IP 一般称为 LVS 的 VIP,即 Virtual IP。
访问的请求首先经过 VIP 到达负载调度器,然后由负载调度器从 Real Server 列表中选取一个服务节点响应用户的请求。 在用户的请求到达负载调度器后,调度器将请求发送到提供服务的 Real Server 节点, Real Server 节点返回数据给用户
当收到用户请求某集群服务时,经过 PREROUTING 链,经检查本机路由表,送往 INPUT 链;在进入 netfilter 的 INPUT 链时,ipvs 强行将请求报文通过ipvsadm 定义的集群服务策略的路径改为 FORWORD 链,将报文转发至后端真实提供服务的主机
NAT 模式
特点:
- NAT 技术将请求的报文和响应的报文都需要通过 LB 进行地址改写,因此网站访问量比较大的时候 LB 负载均衡调度器有比较大的瓶颈,一般要求最多之能 10-20 台节点
- 只需要在 LB 上配置一个公网 IP 地址就可以了。
- 每台内部的 realserver 服务器的网关地址必须是调度器 LB 的内网地址。
- NAT 模式支持对 IP 地址和端口进行转换。即用户请求的端口和真实服务器的端口可以不一致。
优点:集群中的物理服务器可以使用任何支持 TCP/IP 操作系统,只有负载均衡器需要一个合法的 IP 地址。
缺点:扩展性有限。当服务器节点(普通 PC 服务器)增长过多时,负载均衡器将成为整个系统的瓶颈,因为所有的请求包和应答包的流向都经过负载均衡器。当服务器节点过多时,大量的数据包都交汇在负载均衡器那,速度就会变慢
TUN 模式(IP 封装、跨网段)
特点:
- TUNNEL 模式必须在所有的 realserver 机器上面绑定 VIP 的 IP 地址
- TUNNEL 模式的 vip ------>realserver 的包通信通过 TUNNEL 模式,不管是内网和外网都能通信,所以不需要 lvs vip 跟 realserver 在同一个网段内。
- TUNNEL 模式 realserver 会把 packet 直接发给 client
- TUNNEL 模式走的隧道模式,所以运维起来比较难,所以一般不用。
优点:负载均衡器只负责将请求包分发给后端节点服务器,而 RS 将应答包直接发给用户。所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,就能处理很巨大的请求量,这种方式,一台负载均衡器能够为很多 RS 进行分发。而且跑在公网上就能进行不同地域的分发。
缺点:隧道模式的 RS 节点需要合法 IP,这种方式需要所有服务器支持”IPTunneling”(IP Encapsulation)协议,服务器可能只局限在部分 Linux 系统上。
DR 模式(局域网改写 mac 地址)
优点:和 TUN(隧道模式)一样,负载均衡器也只是分发请求,应答包通过单独的路由方法返回给客户端。与 VS-TUN 相比,VS-DR 这种实现方式不需要隧道结构,因此可以使用大多数操作系统做为物理服务器。DR 模式的效率很高,但是配置稍微复杂一点,因此对于访问量不是特别大的公司可以用haproxy/nginx取代
缺点:所有 RS 节点和调度器 LB 只能在一个局域网里面
FULLNAT 模式
特点:
- FULL NAT 模式不需要 LBIP 和 realserver ip 在同一个网段;
- FULL NAT 因为要更新 sorce ip 所以性能正常比 nat 模式下降 10%
管理系统:
分为运营管理和网络管理子系统。
- 网络管理系统实现对 CDN 系统的设备管理、拓扑管理、链路监控和故障管理,为管理员提供对全网资源的可视化的集中管理,通常用 web 方式实现。
- 运营管理是对 CDN 系统的业务管理,负责处理业务层面的与外界系统交互所必须的一些收集、整理、交付工作。包括用户管理、产品管理、计费管理、统计分析等。
六:网络攻击
SYN Flod 攻击
攻击者给服务器发了一个 SYN 后就下线了,于是服务器需要默认等 63s 才会断开连接,这样,攻击者就可以把服务器的 syn 连接的队列耗尽,让正常的连接请求不能处理。
Linux 通过tcp_syncokies 的参数来应对这个事:一旦 SYN 队列满了后,TCP 会通过源地址端口、目标地址端口和时间戳打造出一个特别的 Sequence Number 发回去(又叫cookie),如果是攻击者则不会有响应,如果是正常连接,则会把这个 SYN Cookie 发回来,然后服务端可以通过 cookie 建连接(即使你不在 SYN 队列中)。
请注意,千万别用 tcp_syncokies来处理正常的大负载的连接的情况。因为,syncokies 是妥协版的 TCP 协议,并不严谨。
对于正常的请求,你应该调整三个 TCP 参数
- tcp_synack_retries可以用他来减少重试次数
- tcp_max_syn_backlog,可以增大 SYN 连接数
- tcp_abort_on_overflow 处理不过来干脆就直接拒绝连接了。
DOS 攻击
DOS 攻击是 Distrbuted Denial of Service 的缩写,即不法黑客组织通过控制服务器等资源,发动对包括国家骨干网络、重要网络设施、政企或个人网站在内的互联网上任一目标的攻击,致使目标服务器断网,最终停止提供服务。
预防:
- 高防服务器: 主要是指能独立硬防御 50Gbps 以上的服务器,能够帮助网站拒绝服务攻击,定期扫描网络主节点等
- DOS 清洗:对用户请求数据进行实时监控,及时发现 DOS 攻击等异常流量,在不影响正常业务开展的情况下清洗掉这些异常流量。
- CDN加速 :在现实中,CDN 服务将网站访问流量分配到了各个节点中,这样一方面隐藏网站的真实 IP,另一方面即使遭遇 DoS 攻击,也可以将流量分散到各个节点中,防止源站崩溃。
DOOS攻击
向服务器发送链接请求。客户端向服务端发送链接请求数据包,服务器向客户端回复链接请求数据包并等待客户端发送TCP/IP链接的第三步数据包,如果客户端不向服务端发送最后一个数据包,则服务器必须等待30s到2min中才能将链接关闭。如果有大量的请求,则服务器需要耗费大量的资源等待请求的第三个数据包
预防:
DNS 欺骗
DNS 欺骗就是攻击者冒充域名服务器 的一种欺骗行为
预防:
- 使用入侵检测系统
- 使用 DNSSEC
重放攻击
重放攻击又称重播攻击、回放攻击,是指攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程,破坏认证的正确性。
预防:
- 加随机数
- 加时间戳
SQL 注入
所谓 SQL 注入,就是通过把 SQL 命令插入到 Web 表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。
预防:
- 加密处理:将用户登录名称、密码等数据加密保存。加密用户输入的数据,然
后再将它与数据库中保存的数据比较,这相当于对用户输入的数据进行了“消毒”处理,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入 SQL 命令。 - 确保数据库安全:只给访问数据库的 web 应用功能所需的最低的权限,撤销不必要的公共许可
- 输入验证: 检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行。之所以要执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性。