增加 pipelining 缺陷描述 修正 QuickSort 中的小问题

增加 pipelining  缺陷描述 修正 QuickSort 中的小问题
This commit is contained in:
imhuster 2019-07-03 11:50:41 +08:00
parent a2220c04de
commit 0dd19569d5
2 changed files with 14 additions and 30 deletions

View File

@ -63,17 +63,14 @@
URI 包含 URL URN
<div align="center"> <img src="pics/8441b2c4-dca7-4d6b-8efb-f22efccaf331.png" width="500px"> </div><br>
## 请求和响应报文
### 1. 请求报文
<div align="center"> <img src="pics/HTTP_RequestMessageExample.png" width=""/> </div><br>
### 2. 响应报文
<div align="center"> <img src="pics/HTTP_ResponseMessageExample.png" width=""/> </div><br>
# HTTP 方法
客户端发送的 **请求报文** 第一行为请求行包含了方法字段
@ -160,7 +157,6 @@ CONNECT www.example.com:443 HTTP/1.1
```
<div align="center"> <img src="pics/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg" width=""/> </div><br>
## TRACE
> 追踪路径
@ -303,7 +299,6 @@ CONNECT www.example.com:443 HTTP/1.1
## 连接管理
<div align="center"> <img src="pics/HTTP1_x_Connections.png" width="800"/> </div><br>
### 1. 短连接与长连接
当浏览器访问一个包含多张图片的 HTML 页面时除了请求访问的 HTML 页面资源还会请求图片资源如果每进行一次 HTTP 通信就要新建一个 TCP 连接那么开销会很大
@ -319,6 +314,18 @@ CONNECT www.example.com:443 HTTP/1.1
流水线是在同一条长连接上连续发出请求而不用等待响应返回这样可以减少延迟
但是流水线依然存在不少缺陷
- pipelining 只能适用于 HTTP/1.1且只有幂等的请求GETHEADPUT DELETE 等方法才能使用 pipelining 非幂等请求比如 POST 不能使用因为请求之间可能会存在先后依赖关系[Clients SHOULD NOT pipeline requests using non-idempotent methods or non-idempotent sequences of methods](https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2)
- head of line blocking 问题HTTP/1.1 协议规定服务器必须按请求收到的顺序依次发送响应[A server MUST send its responses to those requests in the same order that the requests were received.](https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2)因此如果前面的请求堵塞了后面的请求即使处理完了也需要等待前面的请求处理完发送后才能发送给客户端
- 绝大部分的 HTTP 代理服务器不支持 pipelining
- 使用 pipelining 不一定会带来的性能上的提升
正是因为有这么多的问题各大浏览器厂商要么是根本就不支持 pipelining要么就是默认关掉了 pipelining 机制而且启用的条件十分苛刻
## Cookie
HTTP 协议是无状态的主要是为了让 HTTP 协议尽可能简单使得它能够处理大量事务HTTP/1.1 引入 Cookie 来保存状态信息
@ -632,11 +639,9 @@ HTTP/1.1 使用虚拟主机技术,使得一台服务器拥有多个域名,
- 用户察觉得到正向代理的存在
<div align="center"> <img src="pics/a314bb79-5b18-4e63-a976-3448bffa6f1b.png" width=""/> </div><br>
- 而反向代理一般位于内部网络中用户察觉不到
<div align="center"> <img src="pics/2d09a847-b854-439c-9198-b29c65810944.png" width=""/> </div><br>
### 2. 网关
与代理服务器不同的是网关服务器会将 HTTP 转化为其它协议进行通信从而请求其它非 HTTP 服务器的服务
@ -658,7 +663,6 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
通过使用 SSLHTTPS 具有了加密防窃听认证防伪装和完整性保护防篡改
<div align="center"> <img src="pics/ssl-offloading.jpg" width="700"/> </div><br>
## 加密
### 1. 对称密钥加密
@ -669,7 +673,6 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
- 缺点无法安全地将密钥传输给通信方
<div align="center"> <img src="pics/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png" width="600"/> </div><br>
### 2.非对称密钥加密
非对称密钥加密又称公开密钥加密Public-Key Encryption加密和解密使用不同的密钥
@ -682,13 +685,11 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSLSecure Sockets Layer
- 缺点运算速度慢
<div align="center"> <img src="pics/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png" width="600"/> </div><br>
### 3. HTTPS 采用的加密方式
HTTPS 采用混合的加密机制使用非对称密钥加密用于传输对称密钥来保证传输过程的安全性之后使用对称密钥加密进行通信来保证通信过程的效率下图中的 Session Key 就是对称密钥
<div align="center"> <img src="pics/How-HTTPS-Works.png" width="600"/> </div><br>
## 认证
通过使用 **证书** 来对通信方进行认证
@ -700,7 +701,6 @@ HTTPS 采用混合的加密机制,使用非对称密钥加密用于传输对
进行 HTTPS 通信时服务器会把证书发送给客户端客户端取得其中的公开密钥之后先使用数字签名进行验证如果验证通过就可以开始通信了
<div align="center"> <img src="pics/2017-06-11-ca.png" width=""/> </div><br>
## 完整性保护
SSL 提供报文摘要功能来进行完整性保护
@ -729,7 +729,6 @@ HTTP/1.x 实现简单是以牺牲性能为代价的:
HTTP/2.0 将报文分成 HEADERS 帧和 DATA 它们都是二进制格式的
<div align="center"> <img src="pics/86e6a91d-a285-447a-9345-c5484b8d0c47.png" width="400"/> </div><br>
在通信过程中只会有一个 TCP 连接存在它承载了任意数量的双向数据流Stream
- 一个数据流Stream都有一个唯一标识符和可选的优先级信息用于承载双向信息
@ -737,13 +736,11 @@ HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式
- Frame是最小的通信单位来自不同数据流的帧可以交错发送然后再根据每个帧头的数据流标识符重新组装
<div align="center"> <img src="pics/af198da1-2480-4043-b07f-a3b91a88b815.png" width="600"/> </div><br>
## 服务端推送
HTTP/2.0 在客户端请求一个资源时会把相关的资源一起发送给客户端客户端就不需要再次发起请求了例如客户端请求 page.html 页面服务端就把 script.js style.css 等与之相关的资源一起发给客户端
<div align="center"> <img src="pics/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png" width="800"/> </div><br>
## 首部压缩
HTTP/1.1 的首部带有大量信息而且每次都要重复发送
@ -753,7 +750,6 @@ HTTP/2.0 要求客户端和服务器同时维护和更新一个包含之前见
不仅如此HTTP/2.0 也使用 Huffman 编码对首部字段进行压缩
<div align="center"> <img src="pics/_u4E0B_u8F7D.png" width="600"/> </div><br>
# HTTP/1.1 新特性
详细内容请见上文

View File

@ -59,7 +59,6 @@ public abstract class Sort<T extends Comparable<T>> {
选择排序需要 \~N<sup>2</sup>/2 次比较和 \~N 次交换它的运行时间与输入无关这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作
<div align="center"> <img src="pics/bc6be2d0-ed5e-4def-89e5-3ada9afa811a.gif" width="230px"> </div><br>
```java
public class Selection<T extends Comparable<T>> extends Sort<T> {
@ -86,7 +85,6 @@ public class Selection<T extends Comparable<T>> extends Sort<T> {
在一轮循环中如果没有发生交换那么说明数组已经是有序的此时可以直接退出
<div align="center"> <img src="pics/0f8d178b-52d8-491b-9dfd-41e05a952578.gif" width="200px"> </div><br>
```java
public class Bubble<T extends Comparable<T>> extends Sort<T> {
@ -120,7 +118,6 @@ public class Bubble<T extends Comparable<T>> extends Sort<T> {
- 最好的情况下需要 N-1 次比较和 0 次交换最好的情况就是数组已经有序了
<div align="center"> <img src="pics/35253fa4-f60a-4e3b-aaec-8fc835aabdac.gif" width="200px"> </div><br>
```java
public class Insertion<T extends Comparable<T>> extends Sort<T> {
@ -143,7 +140,6 @@ public class Insertion<T extends Comparable<T>> extends Sort<T> {
希尔排序使用插入排序对间隔 h 的序列进行排序通过不断减小 h最后令 h=1就可以使得整个数组是有序的
<div align="center"> <img src="pics/7818c574-97a8-48db-8e62-8bfb030b02ba.png" width="450px"> </div><br>
```java
public class Shell<T extends Comparable<T>> extends Sort<T> {
@ -177,7 +173,6 @@ public class Shell<T extends Comparable<T>> extends Sort<T> {
归并排序的思想是将数组分成两部分分别进行排序然后归并起来
<div align="center"> <img src="pics/ec840967-d127-4da3-b6bb-186996c56746.png" width="300px"> </div><br>
## 1. 归并方法
归并方法将数组中两个已经排序的部分归并成一个
@ -273,7 +268,6 @@ public class Down2UpMergeSort<T extends Comparable<T>> extends MergeSort<T> {
- 快速排序通过一个切分元素将数组分为两个子数组左子数组小于等于切分元素右子数组大于等于切分元素将这两个子数组排序也就将整个数组排序了
<div align="center"> <img src="pics/6234eb3d-ccf2-4987-a724-235aef6957b1.png" width="280px"> </div><br>
```java
public class QuickSort<T extends Comparable<T>> extends Sort<T> {
@ -283,7 +277,7 @@ public class QuickSort<T extends Comparable<T>> extends Sort<T> {
sort(nums, 0, nums.length - 1);
}
private void sort(T[] nums, int l, int h) {
protected void sort(T[] nums, int l, int h) {
if (h <= l)
return;
int j = partition(nums, l, h);
@ -292,7 +286,7 @@ public class QuickSort<T extends Comparable<T>> extends Sort<T> {
}
private void shuffle(T[] nums) {
List<Comparable> list = Arrays.asList(nums);
List<Comparable<T>> list = Arrays.asList(nums);
Collections.shuffle(list);
list.toArray(nums);
}
@ -304,7 +298,6 @@ public class QuickSort<T extends Comparable<T>> extends Sort<T> {
a[l] 作为切分元素然后从数组的左端向右扫描直到找到第一个大于等于它的元素再从数组的右端向左扫描找到第一个小于它的元素交换这两个元素不断进行这个过程就可以保证左指针 i 的左侧元素都不大于切分元素右指针 j 的右侧元素都不小于切分元素当两个指针相遇时将切分元素 a[l] a[j] 交换位置
<div align="center"> <img src="pics/c4859290-e27d-4f12-becf-e2a5c1f3a275.gif" width="320px"> </div><br>
```java
private int partition(T[] nums, int l, int h) {
int i = l, j = h + 1;
@ -408,7 +401,6 @@ public T select(T[] nums, int k) {
堆可以用数组来表示这是因为堆是完全二叉树而完全二叉树很容易就存储在数组中位置 k 的节点的父节点位置为 k/2而它的两个子节点的位置分别为 2k 2k+1这里不使用数组索引为 0 的位置是为了更清晰地描述节点的位置关系
<div align="center"> <img src="pics/f48883c8-9d8a-494e-99a4-317d8ddb8552.png" width="170px"> </div><br>
```java
public class Heap<T extends Comparable<T>> {
@ -444,7 +436,6 @@ public class Heap<T extends Comparable<T>> {
在堆中当一个节点比父节点大那么需要交换这个两个节点交换后还可能比它新的父节点大因此需要不断地进行比较和交换操作把这种操作称为上浮
<div align="center"> <img src="pics/99d5e84e-fc2a-49a3-8259-8de274617756.gif" width="270px"> </div><br>
```java
private void swim(int k) {
while (k > 1 && less(k / 2, k)) {
@ -457,7 +448,6 @@ private void swim(int k) {
类似地当一个节点比子节点来得小也需要不断地向下进行比较和交换操作把这种操作称为下沉一个节点如果有两个子节点应当与两个子节点中最大那个节点进行交换
<div align="center"> <img src="pics/4bf5e3fb-a285-4138-b3b6-780956eb1df1.gif" width="270px"> </div><br>
```java
private void sink(int k) {
while (2 * k <= N) {
@ -506,13 +496,11 @@ public T delMax() {
无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作一个更高效的方法是从右至左进行下沉操作如果一个节点的两个节点都已经是堆有序那么进行下沉操作可以使得这个节点为根节点的堆有序叶子节点不需要进行下沉操作可以忽略叶子节点的元素因此只需要遍历一半的元素即可
<div align="center"> <img src="pics/c2ca8dd2-8d00-4a3e-bece-db7849ac9cfd.gif" width="210px"> </div><br>
#### 5.2 交换堆顶元素与最后一个元素
交换之后需要进行下沉操作维持堆的有序状态
<div align="center"> <img src="pics/d156bcda-ac8d-4324-95e0-0c8df41567c9.gif" width="250px"> </div><br>
```java
public class HeapSort<T extends Comparable<T>> extends Sort<T> {
/**