diff --git a/README.md b/README.md
index 466be2d5..93637019 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@
> [Leetcode 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Leetcode%20题解.md)
-对题目做了一个分类,并对每种题型的解题思路做了总结。已经整理了 300+ 的题目,基本涵盖所有经典题目。
+对题目做了一个分类,并对每种题型的解题思路做了总结。
## 面向对象 :couple:
@@ -59,7 +59,7 @@
整理自《数据库系统概论 第四版》
-> [SQL 语法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/SQL%20语法.md)
+> [SQL](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/SQL.md)
整理自《SQL 必知必会》
@@ -67,6 +67,10 @@
整理自《高性能 MySQL》,整理了一些重点内容。
+> [Redis](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Redis.md)
+
+整理自《Redis 设计与实现》和《Redis 实战》
+
## Java :coffee:
> [JVM](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/JVM.md)
@@ -89,7 +93,31 @@ File, InputStream OutputStream, Reader Writer, Serializable, Socket, NIO
整理了一些常见考点。
-## 编码实践 :hammer:
+## 分布式 :sweat_drops:
+
+> [分布式基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/分布式基础.md)
+
+整理自《大规模分布式存储系统》
+
+> [一致性协议](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/一致性协议.md)
+
+两阶段提交、Paxos、Raft、拜占庭将军问题。
+
+> [分布式问题分析](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/分布式问题分析.md)
+
+分布式事务、复杂均衡算法与实现、分布式锁、分布式 Session、分库分表的分布式困境与应对之策。
+
+## 工具 :hammer:
+
+> [Git](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Git.md)
+
+整理一些 Git 的使用和概念。
+
+> [正则表达式](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/正则表达式.md)
+
+整理自《正则表达式必知必会》
+
+## 编码实践 :speak_no_evil:
> [重构](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/重构.md)
@@ -103,11 +131,11 @@ File, InputStream OutputStream, Reader Writer, Serializable, Socket, NIO
Google 开源项目的代码风格规范。
-
+一些 PDF 书籍
## 后记 :memo:
diff --git a/notes/Git.md b/notes/Git.md
new file mode 100644
index 00000000..3418d95e
--- /dev/null
+++ b/notes/Git.md
@@ -0,0 +1,156 @@
+
+* [学习资料](#学习资料)
+* [集中式与分布式](#集中式与分布式)
+* [Git 的中心服务器](#git-的中心服务器)
+* [Git 工作流](#git-工作流)
+* [分支实现](#分支实现)
+* [冲突](#冲突)
+* [Fast forward](#fast-forward)
+* [分支管理策略](#分支管理策略)
+* [储藏(Stashing)](#储藏stashing)
+* [SSH 传输设置](#ssh-传输设置)
+* [.gitignore 文件](#gitignore-文件)
+* [Git 命令一览](#git-命令一览)
+
+
+
+# 学习资料
+
+- [Git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html)
+- [图解 Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html)
+- [廖雪峰 : Git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)
+- [Learn Git Branching](https://learngitbranching.js.org/)
+
+# 集中式与分布式
+
+Git 属于分布式版本控制系统,而 SVN 属于集中式。
+
+集中式版本控制只有中心服务器拥有一份代码,而分布式版本控制每个人的电脑上就有一份完整的代码。
+
+集中式版本控制有安全性问题,当中心服务器挂了所有人都没办法工作了。
+
+集中式版本控制需要连网才能工作,如果网速过慢,那么提交一个文件的会慢的无法让人忍受。而分布式版本控制不需要连网就能工作。
+
+分布式版本控制新建分支、合并分支操作速度非常快,而集中式版本控制新建一个分支相当于复制一份完整代码。
+
+# Git 的中心服务器
+
+Git 的中心服务器用来交换每个用户的修改。没有中心服务器也能工作,但是中心服务器能够 24 小时保持开机状态,这样就能更方便的交换修改。Github 就是一种 Git 中心服务器。
+
+# Git 工作流
+
+
+
+新建一个仓库之后,当前目录就成为了工作区,工作区下有一个隐藏目录 .git,它属于 Git 的版本库。
+
+Git 版本库有一个称为 stage 的暂存区,还有自动创建的 master 分支以及指向分支的 HEAD 指针。
+
+
+
+- git add files 把文件的修改添加到暂存区
+- git commit 把暂存区的修改提交到当前分支,提交之后暂存区就被清空了
+- git reset -- files 使用当前分支上的修改覆盖暂缓区,用来撤销最后一次 git add files
+- git checkout -- files 使用暂存区的修改覆盖工作目录,用来撤销本地修改
+
+
+
+可以跳过暂存区域直接从分支中取出修改或者直接提交修改到分支中
+
+- git commit -a 直接把所有文件的修改添加到暂缓区然后执行提交
+- git checkout HEAD -- files 取出最后一次修改,可以用来进行回滚操作
+
+# 分支实现
+
+Git 把每次提交都连成一条时间线。分支使用指针来实现,例如 master 分支指针指向时间线的最后一个节点,也就是最后一次提交。HEAD 指针指向的是当前分支。
+
+
+
+新建分支是新建一个指针指向时间线的最后一个节点,并让 HEAD 指针指向新分支表示新分支成为当前分支。
+
+
+
+每次提交只会让当前分支向前移动,而其它分支不会移动。
+
+
+
+合并分支也只需要改变指针即可。
+
+
+
+# 冲突
+
+当两个分支都对同一个文件进行了修改,在分支合并时就会产生冲突。
+
+
+
+Git 会使用 <<<<<<< ,======= ,>>>>>>> 标记出不同分支的内容,只需要把不同分支中冲突部分修改成一样就能解决冲突。
+
+```
+<<<<<<< HEAD
+Creating a new branch is quick & simple.
+=======
+Creating a new branch is quick AND simple.
+>>>>>>> feature1
+```
+
+# Fast forward
+
+"快进式合并"(fast-farward merge),会直接将 master 分支指向合并的分支,这种模式下进行分支合并会丢失分支信息,也就不能在分支历史上看出分支信息。
+
+可以在合并时加上 --no-ff 参数来禁用 Fast forward 模式,并且加上 -m 参数让合并时产生一个新的 commit。
+
+```
+$ git merge --no-ff -m "merge with no-ff" dev
+```
+
+
+
+# 分支管理策略
+
+master 分支应该是非常稳定的,只用来发布新版本;
+
+日常开发在开发分支 dev 上进行。
+
+
+
+# 储藏(Stashing)
+
+在一个分支上操作之后,如果还没有将修改提交到分支上,此时进行切换分支,那么另一个分支上也能看到新的修改。这是因为所有分支都共用一个工作区的缘故。
+
+可以使用 git stash 将当前分支的修改储藏起来,此时当前工作区的所有修改都会被存到栈上,也就是说当前工作区是干净的,没有任何未提交的修改。此时就可以安全的切换到其它分支上了。
+
+```
+$ git stash
+Saved working directory and index state \ "WIP on master: 049d078 added the index file"
+HEAD is now at 049d078 added the index file (To restore them type "git stash apply")
+```
+
+该功能可以用于 bug 分支的实现。如果当前正在 dev 分支上进行开发,但是此时 master 上有个 bug 需要修复,但是 dev 分支上的开发还未完成,不想立即提交。在新建 bug 分支并切换到 bug 分支之前就需要使用 git stash 将 dev 分支的未提交修改储藏起来。
+
+# SSH 传输设置
+
+Git 仓库和 Github 中心仓库之间是通过 SSH 加密。
+
+如果工作区下没有 .ssh 目录,或者该目录下没有 id_rsa 和 id_rsa.pub 这两个文件,可以通过以下命令来创建 SSH Key:
+
+```
+$ ssh-keygen -t rsa -C "youremail@example.com"
+```
+
+然后把公钥 id_rsa.pub 的内容复制到 Github "Account settings" 的 SSH Keys 中。
+
+# .gitignore 文件
+
+忽略以下文件:
+
+1. 操作系统自动生成的文件,比如缩略图;
+2. 编译生成的中间文件,比如 Java 编译产生的 .class 文件;
+3. 自己的敏感信息,比如存放口令的配置文件。
+
+不需要全部自己编写,可以到 [https://github.com/github/gitignore](https://github.com/github/gitignore) 中进行查询。
+
+# Git 命令一览
+
+
+
+比较详细的地址:http://www.cheat-sheets.org/saved-copy/git-cheat-sheet.pdf
diff --git a/notes/HTTP.md b/notes/HTTP.md
index 1aa5f46c..5014946b 100644
--- a/notes/HTTP.md
+++ b/notes/HTTP.md
@@ -1,28 +1,29 @@
-* [基础概念](#基础概念)
+* [一 、基础概念](#一-基础概念)
* [Web 基础](#web-基础)
* [URL](#url)
* [请求和响应报文](#请求和响应报文)
-* [HTTP 方法](#http-方法)
+* [二、HTTP 方法](#二http-方法)
* [GET:获取资源](#get获取资源)
* [POST:传输实体主体](#post传输实体主体)
* [HEAD:获取报文首部](#head获取报文首部)
* [PUT:上传文件](#put上传文件)
+ * [PATCH:对资源进行部分修改](#patch对资源进行部分修改)
* [DELETE:删除文件](#delete删除文件)
* [OPTIONS:查询支持的方法](#options查询支持的方法)
- * [TRACE:追踪路径](#trace追踪路径)
* [CONNECT:要求用隧道协议连接代理](#connect要求用隧道协议连接代理)
-* [HTTP 状态码](#http-状态码)
+ * [TRACE:追踪路径](#trace追踪路径)
+* [三、HTTP 状态码](#三http-状态码)
* [2XX 成功](#2xx-成功)
* [3XX 重定向](#3xx-重定向)
* [4XX 客户端错误](#4xx-客户端错误)
* [5XX 服务器错误](#5xx-服务器错误)
-* [HTTP 首部](#http-首部)
+* [四、HTTP 首部](#四http-首部)
* [通用首部字段](#通用首部字段)
* [请求首部字段](#请求首部字段)
* [响应首部字段](#响应首部字段)
* [实体首部字段](#实体首部字段)
-* [具体应用](#具体应用)
+* [五、具体应用](#五具体应用)
* [Cookie](#cookie)
* [缓存](#缓存)
* [持久连接](#持久连接)
@@ -33,15 +34,18 @@
* [内容协商](#内容协商)
* [虚拟主机](#虚拟主机)
* [通信数据转发](#通信数据转发)
-* [HTTPs](#https)
+* [六、HTTPs](#六https)
* [加密](#加密)
* [认证](#认证)
* [完整性](#完整性)
-* [HTTP/1.0 与 HTTP/1.1 的区别](#http10-与-http11-的区别)
+* [七、各版本比较](#七各版本比较)
+ * [HTTP/1.0 与 HTTP/1.1 的区别](#http10-与-http11-的区别)
+ * [HTTP/1.1 与 HTTP/2.0 的区别](#http11-与-http20-的区别)
+* [参考资料](#参考资料)
-# 基础概念
+# 一 、基础概念
## Web 基础
@@ -61,36 +65,37 @@ URI 包含 URL 和 URN,目前 WEB 只有 URL 比较流行,所以见到的基
## 请求和响应报文
-**请求报文**
+### 1. 请求报文
-**响应报文**
+### 2. 响应报文
-# HTTP 方法
+# 二、HTTP 方法
-客户端发送的请求报文第一行为请求行,包含了方法字段。
+客户端发送的 **请求报文** 第一行为请求行,包含了方法字段。
## GET:获取资源
## POST:传输实体主体
-POST 主要目的不是获取资源,而是传输实体主体数据。
+POST 主要目的不是获取资源,而是传输存储在内容实体中的数据。
-GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL 中,而 POST 的参数存储在实体主体部分。
+GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL 中,而 POST 的参数存储在内容实体。
```
GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1
```
+
```
POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2
```
-GET 的传参方式相比于 POST 安全性较差,因为 GET 传的参数在 URL 是可见的,可能会泄露私密信息。并且 GET 只支持 ASCII 字符,如果参数为中文则可能会出现乱码,而 POST 支持标准字符集。
+GET 的传参方式相比于 POST 安全性较差,因为 GET 传的参数在 URL 中是可见的,可能会泄露私密信息。并且 GET 只支持 ASCII 字符,如果参数为中文则可能会出现乱码,而 POST 支持标准字符集。
## HEAD:获取报文首部
@@ -100,37 +105,68 @@ GET 的传参方式相比于 POST 安全性较差,因为 GET 传的参数在 U
## PUT:上传文件
-由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般 WEB 网站不使用该方法。
+由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般不使用该方法。
+
+```html
+PUT /new.html HTTP/1.1
+Host: example.com
+Content-type: text/html
+Content-length: 16
+
+New File
+```
+
+## PATCH:对资源进行部分修改
+
+PUT 也可以用于修改资源,但是只能完全替代原始资源,PATCH 允许部分修改。
+
+```html
+PATCH /file.txt HTTP/1.1
+Host: www.example.com
+Content-Type: application/example
+If-Match: "e0023aa4e"
+Content-Length: 100
+
+[description of changes]
+```
## DELETE:删除文件
与 PUT 功能相反,并且同样不带验证机制。
+```html
+DELETE /file.html HTTP/1.1
+```
+
## OPTIONS:查询支持的方法
查询指定的 URL 能够支持的方法。
会返回 Allow: GET, POST, HEAD, OPTIONS 这样的内容。
+## CONNECT:要求用隧道协议连接代理
+
+要求在于代理服务器通信时建立隧道,使用 SSL(Secure Sokets Layer,安全套接字)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
+
+```html
+CONNECT www.example.com:443 HTTP/1.1
+```
+
+
+
## TRACE:追踪路径
服务器会将通信路径返回给客户端。
发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输。
-TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪),因此更不会去使用它。
+通常不会使用 TRACE,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪),因此更不会去使用它。
-## CONNECT:要求用隧道协议连接代理
+# 三、HTTP 状态码
-主要使用 SSL(Secure Sokets Layer,安全套接字)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
-
-
-
-# HTTP 状态码
-
-服务器返回的响应报文中第一行为状态行,包含了状态码以及原因短语,来告知客户端请求的结果。
+服务器返回的 **响应报文** 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果。
| 状态码 | 类别 | 原因短语 |
| --- | --- | --- |
@@ -146,7 +182,7 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
- **204 No Content** :请求已经成功处理,但是返回的响应报文不包含实体的主体部分。一般在只需要从客户端往服务器发送信息,而不需要返回数据时使用。
-- **206 Partial Content**
+- **206 Partial Content** :表示客户端进行了范围请求。响应报文包含由 Content-Range 指定范围的实体内容。
## 3XX 重定向
@@ -154,7 +190,7 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
- **302 Found** :临时性重定向
-- **303 See Other**
+- **303 See Other** :和 302 有着相同的功能,但是 303 明确要求客户端应该采用 GET 方法获取资源。
- 注:虽然 HTTP 协议规定 301、302 状态下重定向时不允许把 POST 方法改成 GET 方法,但是大多数浏览器都会 在 301、302 和 303 状态下的重定向把 POST 方法改成 GET 方法。
@@ -164,9 +200,9 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
## 4XX 客户端错误
-- **400 Bad Request** :请求报文中存在语法错误
+- **400 Bad Request** :请求报文中存在语法错误。
-- **401 Unauthorized** :该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。如果之前已进行过一次请求,则表示用户认证失败。
+- **401 Unauthorized** :该状态码表示发送的请求需要有认证信息(BASIC 认证、DIGEST 认证)。如果之前已进行过一次请求,则表示用户认证失败。
@@ -176,11 +212,11 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
## 5XX 服务器错误
-- **500 Internal Server Error** :服务器正在执行请求时发生错误
+- **500 Internal Server Error** :服务器正在执行请求时发生错误。
-- **503 Service Unavilable** :该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
+- **503 Service Unavilable** :服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
-# HTTP 首部
+# 四、HTTP 首部
有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。
@@ -191,7 +227,7 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
| 首部字段名 | 说明 |
| -- | -- |
| Cache-Control | 控制缓存的行为 |
-| Connection | 逐跳首部、 连接的管理 |
+| Connection | 控制不再转发给代理的首部字段;管理持久连接|
| Date | 创建报文的日期时间 |
| Pragma | 报文指令 |
| Trailer | 报文末端的首部一览 |
@@ -245,7 +281,7 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
| Allow | 资源可支持的 HTTP 方法 |
| Content-Encoding | 实体主体适用的编码方式 |
| Content-Language | 实体主体的自然语言 |
-| Content-Length | 实体主体的大小(单位: 字节) |
+| Content-Length | 实体主体的大小(单位:字节) |
| Content-Location | 替代对应资源的 URI |
| Content-MD5 | 实体主体的报文摘要 |
| Content-Range | 实体主体的位置范围 |
@@ -253,56 +289,107 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
| Expires | 实体主体过期的日期时间 |
| Last-Modified | 资源的最后修改日期时间 |
-# 具体应用
+# 五、具体应用
## Cookie
HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。
-服务器发送的响应报文包含 Set-Cookie 字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。下次再发送请求时,从浏览器中读出 Cookie 值,在请求报文中包含 Cookie 字段,这样服务器就知道客户端的状态信息了。Cookie 状态信息保存在客户端浏览器中,而不是服务器上。
+Cookie 是服务器发送给客户端的数据,该数据会被保存在浏览器中,并且在下一次发送请求时包含该数据。通过 Cookie 可以让服务器知道两个请求是否来自于同一个客户端,从而实现保持登录状态等功能。
-
+### 1. 创建过程
-Set-Cookie 字段有以下属性:
+服务器发送的响应报文包含 Set-Cookie 字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。
+
+```html
+HTTP/1.0 200 OK
+Content-type: text/html
+Set-Cookie: yummy_cookie=choco
+Set-Cookie: tasty_cookie=strawberry
+
+[page content]
+```
+
+客户端之后发送请求时,会从浏览器中读出 Cookie 值,在请求报文中包含 Cookie 字段。
+
+```html
+GET /sample_page.html HTTP/1.1
+Host: www.example.org
+Cookie: yummy_cookie=choco; tasty_cookie=strawberry
+```
+
+### 2. Set-Cookie
| 属性 | 说明 |
| -- | -- |
| NAME=VALUE | 赋予 Cookie 的名称和其值(必需项) |
| expires=DATE | Cookie 的有效期(若不明确指定则默认为浏览器关闭前为止) |
| path=PATH | 将服务器上的文件目录作为 Cookie 的适用对象(若不指定则默认为文档所在的文件目录) |
-| domain= 域名 | 作为 Cookie 适用对象的域名(若不指定则默认为创建 Cookie 的服务器的域名) |
+| domain=域名 | 作为 Cookie 适用对象的域名(若不指定则默认为创建 Cookie 的服务器的域名) |
| Secure | 仅在 HTTPS 安全通信时才会发送 Cookie |
| HttpOnly | 加以限制,使 Cookie 不能被 JavaScript 脚本访问 |
-**Session 和 Cookie 区别**
+### 3. Session 和 Cookie 区别
Session 是服务器用来跟踪用户的一种手段,每个 Session 都有一个唯一标识:Session ID。当服务器创建了一个 Session 时,给客户端发送的响应报文就包含了 Set-Cookie 字段,其中有一个名为 sid 的键值对,这个键值对就是 Session ID。客户端收到后就把 Cookie 保存在浏览器中,并且之后发送的请求报文都包含 Session ID。HTTP 就是通过 Session 和 Cookie 这两种方式一起合作来实现跟踪用户状态的,Session 用于服务器端,Cookie 用于客户端。
-**浏览器禁用 Cookie 的情况**
+### 4. 浏览器禁用 Cookie 的情况
会使用 URL 重写技术,在 URL 后面加上 sid=xxx 。
-**使用 Cookie 实现用户名和密码的自动填写**
+### 5. 使用 Cookie 实现用户名和密码的自动填写
-网站脚本会自动从 Cookie 中读取用户名和密码,从而实现自动填写。
+网站脚本会自动从保存在浏览器中的 Cookie 读取用户名和密码,从而实现自动填写。
## 缓存
-有两种缓存方法:让代理服务器进行缓存和让客户端浏览器进行缓存。
+### 1. 优点
-Cache-Control 用于控制缓存的行为。Cache-Control: no-cache 有两种含义,如果是客户端向缓存服务器发送的请求报文中含有该指令,表示客户端不想要缓存的资源;如果是源服务器向缓存服务器发送的响应报文中含有该指令,表示缓存服务器不能对资源进行缓存。
+1. 降低服务器的负担;
+2. 提高响应速度(缓存资源比服务器上的资源离客户端更近)。
-Expires 字段可以用于告知缓存服务器该资源什么时候会过期。当首部字段 Cache-Control 有指定 max-age 指令时,比起首部字段 Expires,会优先处理 max-age 指令。
+### 2. 实现方法
+
+1. 让代理服务器进行缓存;
+2. 让客户端浏览器进行缓存。
+
+### 3. Cache-Control 字段
+
+HTTP 通过 Cache-Control 首部字段来控制缓存。
+
+```html
+Cache-Control: private, max-age=0, no-cache
+```
+
+### 4. no-cache 指令
+
+该指令出现在请求报文的 Cache-Control 字段中,表示缓存服务器需要先向原服务器验证缓存资源是否过期;
+
+该指令出现在响应报文的 Cache-Control 字段中,表示缓存服务器在进行缓存之前需要先验证缓存资源的有效性。
+
+### 5. no-store 指令
+
+该指令表示缓存服务器不能对请求或响应的任何一部分进行缓存。
+
+no-cache 不表示不缓存,而是缓存之前需要先进行验证,no-store 才是不进行缓存。
+
+### 6. max-age 指令
+
+该指令出现在请求报文的 Cache-Control 字段中,如果缓存资源的缓存时间小于该指令指定的时间,那么就能接受该缓存。
+
+该指令出现在响应报文的 Cache-Control 字段中,表示缓存资源在缓存服务器中保存的时间。
+
+Expires 字段也可以用于告知缓存服务器该资源什么时候会过期。在 HTTP/1.1 中,会优先处理 Cache-Control : max-age 指令;而在 HTTP/1.0 中,Cache-Control : max-age 指令会被忽略掉。
## 持久连接
-当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问 HTML 页面资源,还会请求图片资源,如果每进行一次 HTTP 通信就要断开一次 TCP 连接,连接建立和断开的开销会很大。 **持久连接** 只需要进行一次 TCP 连接就能进行多次 HTTP 通信。HTTP/1.1 开始,所有的连接默认都是持久连接。
+当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问 HTML 页面资源,还会请求图片资源,如果每进行一次 HTTP 通信就要断开一次 TCP 连接,连接建立和断开的开销会很大。持久连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信。
-持久连接需要使用 Connection 首部字段进行管理。HTTP/1.1 开始 HTTP 默认是持久化连接的,如果要断开 TCP 连接,需要由客户端或者服务器端提出断开,使用 Connection: close;而在 HTTP/1.1 之前默认是非持久化连接的,如果要维持持续连接,需要使用 Keep-Alive。
+持久连接需要使用 Connection 首部字段进行管理。HTTP/1.1 开始 HTTP 默认是持久化连接的,如果要断开 TCP 连接,需要由客户端或者服务器端提出断开,使用 Connection : close;而在 HTTP/1.1 之前默认是非持久化连接的,如果要维持持续连接,需要使用 Connection : Keep-Alive。
-管线化方式可以同时发送多个请求和响应,而不需要发送一个请求然后等待响应之后再发下一个请求。
+**管线化方式** 可以同时发送多个请求和响应,而不需要发送一个请求然后等待响应之后再发下一个请求。
@@ -316,11 +403,24 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
## 多部分对象集合
-一份报文主体内可含有多种类型的实体同时发送,每个部分之间用 boundary 字段定义的分隔符进行分隔;每个部分都可以有首部字段。
+一份报文主体内可含有多种类型的实体同时发送,每个部分之间用 boundary 字段定义的分隔符进行分隔,每个部分都可以有首部字段。
例如,上传多个表单时可以使用如下方式:
-
+```html
+Content-Type: multipart/form-data; boundary=AaB03x
+
+--AaB03x
+Content-Disposition: form-data; name="submit-name"
+
+Larry
+--AaB03x
+Content-Disposition: form-data; name="files"; filename="file1.txt"
+Content-Type: text/plain
+
+... contents of file1.txt ...
+--AaB03x--
+```
## 范围请求
@@ -328,6 +428,20 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
在请求报文首部中添加 Range 字段,然后指定请求的范围,例如 Range:bytes=5001-10000。请求成功的话服务器发送 206 Partial Content 状态。
+```html
+GET /z4d4kWk.jpg HTTP/1.1
+Host: i.imgur.com
+Range: bytes=0-1023
+```
+
+```html
+HTTP/1.1 206 Partial Content
+Content-Range: bytes 0-1023/146515
+Content-Length: 1024
+...
+(binary content)
+```
+
## 内容协商
通过内容协商返回最合适的内容,例如根据浏览器的默认语言选择返回中文界面还是英文界面。
@@ -340,7 +454,7 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
## 通信数据转发
-**代理**
+### 1. 代理
代理服务器接受客户端的请求,并且转发给其它服务器。
@@ -350,19 +464,19 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
-**网关**
+### 2. 网关
与代理服务器不同的是,网关服务器会将 HTTP 转化为其它协议进行通信,从而请求其它非 HTTP 服务器的服务。
-**隧道**
+### 3. 隧道
使用 SSL 等加密手段,为客户端和服务器之间建立一条安全的通信线路。
-# HTTPs
+# 六、HTTPs
HTTP 有以下安全性问题:
@@ -384,21 +498,23 @@ HTTPs 采用 **混合的加密机制** ,使用公开密钥加密用于传输
## 认证
-通过使用 **证书** 来对通信方进行认证。证书中有公开密钥数据,如果可以验证公开密钥的确属于通信方的,那么就可以确定通信方是可靠的。
+通过使用 **证书** 来对通信方进行认证。
-数字证书认证机构(CA,Certificate Authority)可以对其颁发的公开密钥证书对其进行验证。
+数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。服务器的运营人员向 CA 提出公开密钥的申请,CA 在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公开密钥证书后绑定在一起。
-进行 HTTPs 通信时,服务器会把证书发送给客户端,客户端取得其中的公开密钥之后,就可以开始通信。
+进行 HTTPs 通信时,服务器会把证书发送给客户端,客户端取得其中的公开密钥之后,先进行验证,如果验证通过,就可以开始通信。
+
+除了上诉提到的服务器端证书之外,还有客户端证书,客户端证书的目的就是让服务器对客户端进行验证。客户端证书需要用户自行安装,只有在业务需要非常高的安全性时才使用客户端证书,例如网上银行。
使用 OpenSSL 这套开源程序,每个人都可以构建一套属于自己的认证机构,从而自己给自己颁发服务器证书。浏览器在访问该服务器时,会显示“无法确认连接安全性”或“该网站的安全证书存在问题”等警告消息。
-客户端证书需要用户自行安装,只有在业务需要非常高的安全性时才使用客户端证书,例如网上银行。
-
## 完整性
SSL 提供摘要功能来验证完整性。
-# HTTP/1.0 与 HTTP/1.1 的区别
+# 七、各版本比较
+
+## HTTP/1.0 与 HTTP/1.1 的区别
HTTP/1.1 新增了以下内容:
@@ -407,3 +523,26 @@ HTTP/1.1 新增了以下内容:
- 提供了虚拟主机的功能;
- 多了一些缓存处理字段;
- 多了一些状态码;
+
+## HTTP/1.1 与 HTTP/2.0 的区别
+
+### 1. 多路复用
+
+HTTP/2.0 使用多路复用技术,使用同一个 TCP 连接来处理多个请求。
+
+### 2. 首部压缩
+
+HTTP/1.1 的首部带有大量信息,而且每次都要重复发送。HTTP/2.0 要求通讯双方各自缓存一份首部字段表,从而避免了重复传输。
+
+### 3. 服务端推送
+
+在客户端请求一个资源时,会把相关的资源一起发送给客户端,客户端就不需要再次发起请求了。例如客户端请求 index.html 页面,服务端就把 index.js 一起发给客户端。
+
+### 4. 二进制格式
+
+HTTP/1.1 的解析是基于文本的,而 HTTP/2.0 采用二进制格式。
+
+# 参考资料
+
+- [图解 HTTP](https://pan.baidu.com/s/1M0AHXqG9sP9Bxne6u0JK8A)
+- [MDN : HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
diff --git a/notes/JVM.md b/notes/JVM.md
index 0605479c..5054c6e6 100644
--- a/notes/JVM.md
+++ b/notes/JVM.md
@@ -1,79 +1,65 @@
-* [内存模型](#内存模型)
- * [1. 程序计数器](#1-程序计数器)
- * [2. Java 虚拟机栈](#2-java-虚拟机栈)
- * [3. 本地方法栈](#3-本地方法栈)
- * [4. Java 堆](#4-java-堆)
- * [5. 方法区](#5-方法区)
- * [6. 运行时常量池](#6-运行时常量池)
- * [7. 直接内存](#7-直接内存)
-* [垃圾收集](#垃圾收集)
- * [1. 判断一个对象是否可回收](#1-判断一个对象是否可回收)
- * [1.1 引用计数](#11-引用计数)
- * [1.2 可达性](#12-可达性)
- * [1.3 引用类型](#13-引用类型)
- * [1.3.1 强引用](#131-强引用)
- * [1.3.2 软引用](#132-软引用)
- * [1.3.3 弱引用](#133-弱引用)
- * [1.3.4 虚引用](#134-虚引用)
- * [1.3 方法区的回收](#13-方法区的回收)
- * [1.4 finalize()](#14-finalize)
- * [2. 垃圾收集算法](#2-垃圾收集算法)
- * [2.1 标记-清除算法](#21-标记-清除算法)
- * [2.2 复制算法](#22-复制算法)
- * [2.3 标记-整理算法](#23-标记-整理算法)
- * [2.4 分代收集算法](#24-分代收集算法)
- * [3. 垃圾收集器](#3-垃圾收集器)
- * [3.1 Serial 收集器](#31-serial-收集器)
- * [3.2 ParNew 收集器](#32-parnew-收集器)
- * [3.3 Parallel Scavenge 收集器](#33-parallel-scavenge-收集器)
- * [3.4 Serial Old 收集器](#34-serial-old-收集器)
- * [3.5 Parallel Old 收集器](#35-parallel-old-收集器)
- * [3.6 CMS 收集器](#36-cms-收集器)
- * [3.7 G1 收集器](#37-g1-收集器)
- * [3.8 七种垃圾收集器的比较](#38-七种垃圾收集器的比较)
- * [4. 内存分配与回收策略](#4-内存分配与回收策略)
- * [4.1 优先在 Eden 分配](#41-优先在-eden-分配)
- * [4.2 大对象直接进入老年代](#42-大对象直接进入老年代)
- * [4.3 长期存活的对象进入老年代](#43-长期存活的对象进入老年代)
- * [4.4 动态对象年龄判定](#44-动态对象年龄判定)
- * [4.5 空间分配担保](#45-空间分配担保)
- * [5. Full GC 的触发条件](#5-full-gc-的触发条件)
- * [5.1 调用 System.gc()](#51-调用-systemgc)
- * [5.2 老年代空间不足](#52-老年代空间不足)
- * [5.3 空间分配担保失败](#53-空间分配担保失败)
- * [5.4 JDK 1.7 及以前的永久代空间不足](#54-jdk-17-及以前的永久代空间不足)
- * [5.5 Concurrent Mode Failure](#55-concurrent-mode-failure)
-* [类加载机制](#类加载机制)
- * [1 类的生命周期](#1-类的生命周期)
- * [2. 类初始化时机](#2-类初始化时机)
- * [3. 类加载过程](#3-类加载过程)
- * [3.1 加载](#31-加载)
- * [3.2 验证](#32-验证)
- * [3.3 准备](#33-准备)
- * [3.4 解析](#34-解析)
- * [3.5 初始化](#35-初始化)
- * [4. 类加载器](#4-类加载器)
- * [4.1 类与类加载器](#41-类与类加载器)
- * [4.2 类加载器分类](#42-类加载器分类)
- * [4.3 双亲委派模型](#43-双亲委派模型)
-* [JVM 参数](#jvm-参数)
+* [一、内存模型](#一内存模型)
+ * [程序计数器](#程序计数器)
+ * [Java 虚拟机栈](#java-虚拟机栈)
+ * [本地方法栈](#本地方法栈)
+ * [Java 堆](#java-堆)
+ * [方法区](#方法区)
+ * [运行时常量池](#运行时常量池)
+ * [直接内存](#直接内存)
+* [二、垃圾收集](#二垃圾收集)
+ * [判断一个对象是否可回收](#判断一个对象是否可回收)
+ * [1. 引用计数](#1-引用计数)
+ * [2. 可达性](#2-可达性)
+ * [3. 引用类型](#3-引用类型)
+ * [4. 方法区的回收](#4-方法区的回收)
+ * [5. finalize()](#5-finalize)
+ * [垃圾收集算法](#垃圾收集算法)
+ * [1. 标记-清除算法](#1-标记-清除算法)
+ * [2. 复制算法](#2-复制算法)
+ * [3. 标记-整理算法](#3-标记-整理算法)
+ * [4. 分代收集算法](#4-分代收集算法)
+ * [垃圾收集器](#垃圾收集器)
+ * [1. Serial 收集器](#1-serial-收集器)
+ * [2. ParNew 收集器](#2-parnew-收集器)
+ * [3. Parallel Scavenge 收集器](#3-parallel-scavenge-收集器)
+ * [4. Serial Old 收集器](#4-serial-old-收集器)
+ * [5. Parallel Old 收集器](#5-parallel-old-收集器)
+ * [6. CMS 收集器](#6-cms-收集器)
+ * [7. G1 收集器](#7-g1-收集器)
+ * [8. 七种垃圾收集器的比较](#8-七种垃圾收集器的比较)
+ * [内存分配与回收策略](#内存分配与回收策略)
+ * [Full GC 的触发条件](#full-gc-的触发条件)
+* [三、类加载机制](#三类加载机制)
+ * [类的生命周期](#类的生命周期)
+ * [类初始化时机](#类初始化时机)
+ * [类加载过程](#类加载过程)
+ * [1. 加载](#1-加载)
+ * [2. 验证](#2-验证)
+ * [3. 准备](#3-准备)
+ * [4. 解析](#4-解析)
+ * [5. 初始化](#5-初始化)
+ * [类加载器](#类加载器)
+ * [1. 类与类加载器](#1-类与类加载器)
+ * [2. 类加载器分类](#2-类加载器分类)
+ * [3. 双亲委派模型](#3-双亲委派模型)
+* [四、JVM 参数](#四jvm-参数)
* [GC 优化配置](#gc-优化配置)
* [GC 类型设置](#gc-类型设置)
-# 内存模型
+# 一、内存模型
注:白色区域为线程私有的,蓝色区域为线程共享的。
-## 1. 程序计数器
+## 程序计数器
记录正在执行的虚拟机字节码指令的地址(如果正在执行的是 Native 方法则为空)。
-## 2. Java 虚拟机栈
+## Java 虚拟机栈
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
@@ -82,11 +68,11 @@
1. 当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常;
2. 栈进行动态扩展时如果无法申请到足够内存,会抛出 OutOfMemoryError 异常。
-## 3. 本地方法栈
+## 本地方法栈
与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法服务。
-## 4. Java 堆
+## Java 堆
所有对象实例都在这里分配内存。
@@ -94,7 +80,7 @@
不需要连续内存,可以通过 -Xmx 和 -Xms 来控制动态扩展内存大小,如果动态扩展失败会抛出 OutOfMemoryError 异常。
-## 5. 方法区
+## 方法区
用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
@@ -102,7 +88,7 @@
对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现,HotSpot 虚拟机把它当成永久代来进行垃圾回收。
-## 6. 运行时常量池
+## 运行时常量池
运行时常量池是方法区的一部分。
@@ -110,17 +96,17 @@
在运行期间也可以用过 String 类的 intern() 方法将新的常量放入该区域。
-## 7. 直接内存
+## 直接内存
在 JDK 1.4 中新加入了 NIO 类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
-# 垃圾收集
+# 二、垃圾收集
程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收。垃圾回收主要是针对 Java 堆和方法区进行。
-## 1. 判断一个对象是否可回收
+## 判断一个对象是否可回收
-### 1.1 引用计数
+### 1. 引用计数
给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。
@@ -131,7 +117,7 @@ objA.instance = objB;
objB.instance = objA;
```
-### 1.2 可达性
+### 2. 可达性
通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是都是可用的,不可达的对象可被回收。
@@ -142,13 +128,13 @@ GC Roots 一般包含以下内容:
3. 方法区中的常量引用的对象
4. 本地方法栈中引用的对象
-### 1.3 引用类型
+### 3. 引用类型
无论是通过引用计算算法判断对象的引用数量,还是通过可达性分析算法判断对象的引用链是否可达,判定对象是否存活都与“引用”有关。
Java 对引用的概念进行了扩充,引入四种强度不同的引用类型。
-#### 1.3.1 强引用
+#### 3.1 强引用
只要强引用存在,垃圾回收器永远不会回收调掉被引用的对象。
@@ -158,7 +144,7 @@ Java 对引用的概念进行了扩充,引入四种强度不同的引用类型
Object obj = new Object();
```
-#### 1.3.2 软引用
+#### 3.2 软引用
用来描述一些还有用但是并非必需的对象。
@@ -170,10 +156,10 @@ Object obj = new Object();
```java
Object obj = new Object();
-WeakReference