1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-20 22:17:09 +08:00

Merge pull request #1 from Snailclimb/main

更新
This commit is contained in:
Z 2022-03-03 15:43:39 +08:00 committed by GitHub
commit 9dfd0f4ce9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
135 changed files with 2793 additions and 2812 deletions

11
.gitignore vendored
View File

@ -1,4 +1,13 @@
/node_modules /node_modules
/package-lock.json /package-lock.json
/dist
.DS_Store .DS_Store
# VS Code Config file
.vscode/
# Vuepress Cache
.cache/
# Vuepress Temp
.temp/
# Vuepress Output
dist/
# Build files
packages/*/lib/

View File

@ -16,22 +16,22 @@ Read in other languages: [Mandarin](https://github.com/Snailclimb/JavaGuide/blob
> 6. **Interview Special Edition** : For those who are preparing for the interview, you can consider the interview special edition: [Java Interview Advanced Guide].(https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7) (Very high quality, built specifically for interviews, free for planet users) > 6. **Interview Special Edition** : For those who are preparing for the interview, you can consider the interview special edition: [Java Interview Advanced Guide].(https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7) (Very high quality, built specifically for interviews, free for planet users)
> 7. **Reprint Instructions**: All the following articles are my (Guide) original if not stated at the beginning of the text, reproduced at the beginning of the text to indicate the source, if found malicious plagiarism / transport, will use legal weapons to defend their rights. Let's maintain a good technical creation environment together! ⛽️ > 7. **Reprint Instructions**: All the following articles are my (Guide) original if not stated at the beginning of the text, reproduced at the beginning of the text to indicate the source, if found malicious plagiarism / transport, will use legal weapons to defend their rights. Let's maintain a good technical creation environment together! ⛽️
<p align="center"> <p style="text-align:center">
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank"> <a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
<img src="https://img-blog.csdnimg.cn/img_convert/1c00413c65d1995993bf2b0daf7b4f03.png#pic_center" width=""/> <img src="https://img-blog.csdnimg.cn/img_convert/1c00413c65d1995993bf2b0daf7b4f03.png#pic_center" width=""/>
</a> </a>
</p> </p>
<p align="center"> <p style="text-align:center">
<a href="https://javaguide.cn/"><img src="https://img.shields.io/badge/阅读-read-brightgreen.svg" alt="阅读"></a> <a href="https://javaguide.cn/"><img src="https://img.shields.io/badge/阅读-read-brightgreen.svg" alt="阅读"></a>
<img src="https://img.shields.io/github/stars/Snailclimb/JavaGuide" alt="stars"/> <img src="https://img.shields.io/github/stars/Snailclimb/JavaGuide" alt="stars"/>
<img src="https://img.shields.io/github/forks/Snailclimb/JavaGuide" alt="forks"/> <img src="https://img.shields.io/github/forks/Snailclimb/JavaGuide" alt="forks"/>
<img src="https://img.shields.io/github/issues/Snailclimb/JavaGuide" alt="issues"/> <img src="https://img.shields.io/github/issues/Snailclimb/JavaGuide" alt="issues"/>
</p> </p>
<h3 align="center">Recommended</h3> <h3 style="text-align:center">Recommended</h3>
<table> <table>
<tbody> <tbody>
<tr> <tr>
<td align="center" valign="middle"> <td style="text-align:center" valign="middle">
<a href="https://sourl.cn/e7ee87"> <a href="https://sourl.cn/e7ee87">
<img src="./media/sponsor/xingqiu.png" style="margin: 0 auto;width:850px" /></a> <img src="./media/sponsor/xingqiu.png" style="margin: 0 auto;width:850px" /></a>
</td> </td>
@ -163,7 +163,7 @@ In addition[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-alg
**Important knowledge points:** **Important knowledge points:**
1. <div align="center"> 1. <div style="text-align:center">
<p> <p>
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank"> <a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
<img src="https://img-blog.csdnimg.cn/img_convert/1c00413c65d1995993bf2b0daf7b4f03.png#pic_center" width="" /> <img src="https://img-blog.csdnimg.cn/img_convert/1c00413c65d1995993bf2b0daf7b4f03.png#pic_center" width="" />

124
README.md
View File

@ -1,43 +1,41 @@
## 👏 重大更新!!!重磅! > [JavaGuide 官方知识星球](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc)来啦!!!如果你需要专属面试小册/一对一交流/简历修改/专属求职指南/学习打卡,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) (一定要确定自己真的需要再加入,一定要看完详细介绍之后再加我)。
- JavaGuide 在线阅读版新版推荐👍https://javaguide.cn/ <div align="center">
- JavaGuide 在线阅读版(老版):https://snailclimb.gitee.io/javaguide/#/ <p>
- [《JavaGuide 面试突击版》PDF 版本下载](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100029614&idx=1&sn=62993c5cf10265cb7018db7f1ec67250&chksm=4ea1fb6579d67273499b7243641d4ef372decd08047bfbb6dfb5843ef81c7ccba209086cf345#rd)
<a href="https://t.1yb.co/GXLF"><img src="https://img-blog.csdnimg.cn/2f61f3e2d1f2427da977340919e41616.png" style="margin: 0 auto;width:850px" /></a>
> 1. **介绍**:关于 JavaGuide 的相关介绍请看:[关于 JavaGuide 的一些说明](https://www.yuque.com/snailclimb/dr6cvl/mr44yt) 。
> 2. **贡献指南** :欢迎参与 [JavaGuide的维护工作](https://github.com/Snailclimb/JavaGuide/issues/1235),这是一件非常有意义的事情。
> 3. **PDF版本** [《JavaGuide 面试突击版》PDF 版本](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100029614&idx=1&sn=62993c5cf10265cb7018db7f1ec67250&chksm=4ea1fb6579d67273499b7243641d4ef372decd08047bfbb6dfb5843ef81c7ccba209086cf345#rd) 。
> 4. **图解计算机基础** [图解计算机基础 PDF 下载](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100021725&idx=1&sn=2db9664ca25363139a81691043e9fd8f&chksm=4ea19a1679d61300d8990f7e43bfc7f476577a81b712cf0f9c6f6552a8b219bc081efddb5c54#rd) 。
> 5. **知识星球** : 简历指导/Java学习/面试指导/面试小册。欢迎加入[我的知识星球](https://sourl.cn/psyWaE) 。
> 6. **面试专版** :准备面试的小伙伴可以考虑面试专版:[《Java面试进阶指北 》](https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7) (质量很高,专为面试打造,星球用户免费)
> 7. **转载须知** 以下所有文章如非文首说明皆为我Guide哥的原创转载在文首注明出处如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!⛽️
<p align="center">
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
<img src="https://img-blog.csdnimg.cn/img_convert/1c00413c65d1995993bf2b0daf7b4f03.png#pic_center" width=""/>
</a>
</p>
<p align="center">
<a href="https://javaguide.cn/"><img src="https://img.shields.io/badge/阅读-read-brightgreen.svg" alt="阅读"></a>
<img src="https://img.shields.io/github/stars/Snailclimb/JavaGuide" alt="stars"/>
<img src="https://img.shields.io/github/forks/Snailclimb/JavaGuide" alt="forks"/>
<img src="https://img.shields.io/github/issues/Snailclimb/JavaGuide" alt="issues"/>
</p>
<h3 align="center">推荐</h3>
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc"> <a href="https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc">
<img src="./media/sponsor/xingqiu.png" style="margin: 0 auto;width:850px" /></a> <img src="./media/sponsor/xingqiu.png" style="margin: 0 auto; width: 850px;" />
</td> </a>
</tr> </p>
</tbody> <p>
</table> <a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
<img src="https://img-blog.csdnimg.cn/img_convert/1c00413c65d1995993bf2b0daf7b4f03.png#pic_center" width="" />
</a>
</p>
<p>
<a href="https://javaguide.cn/"><img src="https://img.shields.io/badge/阅读-read-brightgreen.svg" alt="阅读" /></a>
<img src="https://img.shields.io/github/stars/Snailclimb/JavaGuide" alt="stars" />
<img src="https://img.shields.io/github/forks/Snailclimb/JavaGuide" alt="forks" />
<img src="https://img.shields.io/github/issues/Snailclimb/JavaGuide" alt="issues" />
</p>
</div>
> 1. **面试专版** :准备面试的小伙伴可以考虑面试专版:[《Java 面试进阶指北 》](https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7) (质量很高,专为面试打造,配合 JavaGuide 食用)。
> 1. **知识星球** :专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入 [JavaGuide 知识星球](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc)(点击链接即可查看星球的详细介绍,一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我)。
> 2. **转载须知** 以下所有文章如非文首说明为转载皆为我Guide 哥)的原创,转载在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
推荐你通过在线阅读网站进行阅读,体验更好,速度更快!
- [JavaGuide 在线阅读网站(新版,推荐👍)](https://javaguide.cn/)
- [JavaGuide 在线阅读版(老版)](https://snailclimb.gitee.io/javaguide/#/)
你可能需要:
- [项目介绍](./docs/javaguide/intro)
- [贡献指南](./docs/javaguide/contribution-guideline)
- [常见问题](./docs/javaguide/faq)
- [项目代办](./docs/javaguide/todo)
## Java ## Java
### 基础 ### 基础
@ -83,7 +81,7 @@
1. **线程池** [Java 线程池详解](./docs/java/concurrent/java-thread-pool-summary.md)、[Java 线程池最佳实践](./docs/java/concurrent/java-thread-pool-best-practices.md) 1. **线程池** [Java 线程池详解](./docs/java/concurrent/java-thread-pool-summary.md)、[Java 线程池最佳实践](./docs/java/concurrent/java-thread-pool-best-practices.md)
2. [ThreadLocal 关键字解析](docs/java/concurrent/threadlocal.md) 2. [ThreadLocal 关键字解析](docs/java/concurrent/threadlocal.md)
3. [Java 并发容器总结](docs/java/concurrent/java-concurrent-collections.md) 3. [Java 并发容器总结](docs/java/concurrent/java-concurrent-collections.md)
4. [Atomic 原子类总结](docs/java/concurrent/atomic原子类总结.md) 4. [Atomic 原子类总结](docs/java/concurrent/atomic-classes.md)
5. [AQS 原理以及 AQS 同步组件总结](docs/java/concurrent/aqs原理以及aqs同步组件总结.md) 5. [AQS 原理以及 AQS 同步组件总结](docs/java/concurrent/aqs原理以及aqs同步组件总结.md)
6. [CompletableFuture入门](docs/java/concurrent/completablefuture-intro.md) 6. [CompletableFuture入门](docs/java/concurrent/completablefuture-intro.md)
@ -102,13 +100,12 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 新特性 ### 新特性
1. **Java 8** [Java 8 新特性总结(翻译)](docs/java/new-features/java8-tutorial-translate.md)、[Java8常用新特性总结](docs/java/new-features/java8-common-new-features.md) 1. **Java 8** [Java 8 新特性总结(翻译)](docs/java/new-features/java8-tutorial-translate.md)、[Java8常用新特性总结](./docs/java/new-features/java8-common-new-features.md)
2. **Java9~Java15** : [一文带你看遍 JDK9~15 的重要新特性!](./docs/java/new-features/java新特性总结.md) 2. [Java 9 新特性概览](./docs/java/new-features/java9.md)
3. [Java 10 新特性概览](./docs/java/new-features/java10.md)
### 小技巧 4. [Java 11 新特性概览](./docs/java/new-features/java11.md)
5. [Java 12~13 新特性概览](./docs/java/new-features/java12-13.md)
1. [JAD 反编译](docs/java/tips/jad.md) 6. [Java 14~15 新特性概览](./docs/java/new-features/java14-15.md)
2. [手把手教你定位常见 Java 性能问题](./docs/java/tips/locate-performance-problems/手把手教你定位常见Java性能问题.md)
## 计算机基础 ## 计算机基础
@ -116,23 +113,26 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 操作系统 ### 操作系统
1. [操作系统常见问题总结!](docs/cs-basics/operating-system/操作系统常见面试题&知识点总结.md) 1. [操作系统常见问题总结!](docs/cs-basics/operating-system/operating-system-basic-questions-01.md)
2. [后端程序员必备的 Linux 基础知识总结](docs/cs-basics/operating-system/linux-intro.md) 2. [后端程序员必备的 Linux 基础知识总结](docs/cs-basics/operating-system/linux-intro.md)
3. [Shell 编程入门](docs/cs-basics/operating-system/shell-intro.md) 3. [Shell 编程入门](docs/cs-basics/operating-system/shell-intro.md)
### 网络 ### 网络
1. [计算机网络常见面试题](docs/cs-basics/network/计算机网络常见面试题.md) 1. [OSI 和 TCP/IP 网络分层模型详解(基础)](./docs/cs-basics/network/osi&tcp-ip-model.md)
1. [HTTP vs HTTPS应用层](./docs/cs-basics/network/http&https.md)
1. [HTTP 1.0 vs HTTP 1.1(应用层)](./docs/cs-basics/network/http1.0&http1.1.md)
1. [计算机网络常见知识点&面试题(补充)](./docs/cs-basics/network/other-network-questions.md)
2. [谢希仁老师的《计算机网络》内容总结](docs/cs-basics/network/谢希仁老师的《计算机网络》内容总结.md) 2. [谢希仁老师的《计算机网络》内容总结](docs/cs-basics/network/谢希仁老师的《计算机网络》内容总结.md)
### 数据结构 ### 数据结构
**图解数据结构:** **图解数据结构:**
1. [线性数据结构 :数组、链表、栈、队列](docs/cs-basics/data-structure/线性数据结构.md) 1. [线性数据结构 :数组、链表、栈、队列](docs/cs-basics/data-structure/linear-data-structure.md)
2. [](docs/cs-basics/data-structure/.md) 2. [](docs/cs-basics/data-structure/graph.md)
3. [](docs/cs-basics/data-structure/.md) 3. [](docs/cs-basics/data-structure/heap.md)
4. [](docs/cs-basics/data-structure/树.md) :重点关注[红黑树](docs/cs-basics/data-structure/红黑树.md)、B-B+B*树、LSM树 4. [](docs/cs-basics/data-structure/tree.md) :重点关注[红黑树](docs/cs-basics/data-structure/red-black-tree.md)、B-B+B*树、LSM树
其他常用数据结构 其他常用数据结构
@ -147,9 +147,9 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
**常见算法问题总结** **常见算法问题总结**
- [几道常见的字符串算法题总结 ](docs/cs-basics/algorithms/几道常见的字符串算法题.md) - [几道常见的字符串算法题总结 ](docs/cs-basics/algorithms/string-algorithm-problems.md)
- [几道常见的链表算法题总结 ](docs/cs-basics/algorithms/几道常见的链表算法题.md) - [几道常见的链表算法题总结 ](docs/cs-basics/algorithms/linkedlist-algorithm-problems.md)
- [剑指 offer 部分编程题](docs/cs-basics/algorithms/剑指offer部分编程题.md) - [剑指 offer 部分编程题](docs/cs-basics/algorithms/the-sword-refers-to-offer.md)
另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。 另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
@ -159,8 +159,8 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
**总结:** **总结:**
1. [数据库基础知识总结](docs/database/数据库基础知识.md) 1. [数据库基础知识总结](docs/database/basis.md)
2. **[MySQL知识点总结](docs/database/mysql/mysql知识点&面试题总结.md)** (必看 :+1:) 2. **[MySQL知识点总结](docs/database/mysql/mysql-questions-01.md)** (必看 :+1:)
4. [一千行 MySQL 学习笔记](docs/database/mysql/a-thousand-lines-of-mysql-study-notes.md) 4. [一千行 MySQL 学习笔记](docs/database/mysql/a-thousand-lines-of-mysql-study-notes.md)
5. [MySQL 高性能优化规范建议](docs/database/mysql/mysql-high-performance-optimization-specification-recommendations.md) 5. [MySQL 高性能优化规范建议](docs/database/mysql/mysql-high-performance-optimization-specification-recommendations.md)
@ -171,7 +171,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
3. [MySQL三大日志(binlog、redo log和undo log)详解](docs/database/mysql/mysql-logs.md) 3. [MySQL三大日志(binlog、redo log和undo log)详解](docs/database/mysql/mysql-logs.md)
4. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/innodb-implementation-of-mvcc.md) 4. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/innodb-implementation-of-mvcc.md)
5. [一条 SQL 语句在 MySQL 中如何被执行的?](docs/database/mysql/how-sql-executed-in-mysql.md) 5. [一条 SQL 语句在 MySQL 中如何被执行的?](docs/database/mysql/how-sql-executed-in-mysql.md)
6. [字符集详解为什么不建议在MySQL中使用 utf8 ](docs/database/字符集.md) 6. [字符集详解为什么不建议在MySQL中使用 utf8 ](docs/database/character-set.md)
7. [关于数据库中如何存储时间的一点思考](docs/database/mysql/some-thoughts-on-database-storage-time.md) 7. [关于数据库中如何存储时间的一点思考](docs/database/mysql/some-thoughts-on-database-storage-time.md)
### Redis ### Redis
@ -223,7 +223,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
#### Spring Cloud #### Spring Cloud
[ 大白话入门 Spring Cloud](docs/system-design/framework/springcloud/springcloud-intro.md) [大白话入门 Spring Cloud](docs/system-design/framework/springcloud/springcloud-intro.md)
### 安全 ### 安全
@ -245,11 +245,11 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
系统需要对用户输入的文本进行敏感词过滤如色情、政治、暴力相关的词汇。 系统需要对用户输入的文本进行敏感词过滤如色情、政治、暴力相关的词汇。
相关阅读:[Java定时任务大揭秘》](./docs/system-design/security/sentive-words-filter.md) 相关阅读:[敏感词过滤》](./docs/system-design/security/sentive-words-filter.md)
### 定时任务 ### 定时任务
最近有朋友问到定时任务相关的问题。于是,我简单写了一篇文章总结一下定时任务的一些概念以及一些常见的定时任务技术选型:[《Java定时任务大揭秘》](./docs/system-design/定时任务.md) 最近有朋友问到定时任务相关的问题。于是,我简单写了一篇文章总结一下定时任务的一些概念以及一些常见的定时任务技术选型:[《Java定时任务大揭秘》](./docs/system-design/schedule-task.md)
## 分布式 ## 分布式
@ -316,7 +316,7 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读:
1. **RabbitMQ** : [RabbitMQ 入门](docs/high-performance/message-queue/rabbitmq-intro.md) 1. **RabbitMQ** : [RabbitMQ 入门](docs/high-performance/message-queue/rabbitmq-intro.md)
2. **RocketMQ** : [RocketMQ 入门](docs/high-performance/message-queue/rocketmq-intro)、[RocketMQ 的几个简单问题与答案](docs/high-performance/message-queue/rocketmq-questions.md) 2. **RocketMQ** : [RocketMQ 入门](docs/high-performance/message-queue/rocketmq-intro)、[RocketMQ 的几个简单问题与答案](docs/high-performance/message-queue/rocketmq-questions.md)
3. **Kafka** [Kafka 常见问题总结](docs/high-performance/message-queue/kafka知识点&面试题总结.md) 3. **Kafka** [Kafka 常见问题总结](docs/high-performance/message-queue/kafka-questions-01.md)
### 读写分离&分库分表 ### 读写分离&分库分表
@ -328,7 +328,7 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读:
常见的分库分表工具有:`sharding-jdbc`(当当)、`TSharding`(蘑菇街)、`MyCAT`(基于 Cobar`Cobar`(阿里巴巴)...。 推荐使用 `sharding-jdbc`。 因为,`sharding-jdbc` 是一款轻量级 `Java` 框架,以 `jar` 包形式提供服务,不要我们做额外的运维工作,并且兼容性也很好。 常见的分库分表工具有:`sharding-jdbc`(当当)、`TSharding`(蘑菇街)、`MyCAT`(基于 Cobar`Cobar`(阿里巴巴)...。 推荐使用 `sharding-jdbc`。 因为,`sharding-jdbc` 是一款轻量级 `Java` 框架,以 `jar` 包形式提供服务,不要我们做额外的运维工作,并且兼容性也很好。
相关阅读: [读写分离&分库分表常见问题总结](docs/high-performance/读写分离&分库分表.md) 相关阅读: [读写分离&分库分表常见问题总结](docs/high-performance/read-and-write-separation-and-library-subtable.md)
### 负载均衡 ### 负载均衡
@ -344,7 +344,7 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读:
高可用描述的是一个系统在大部分时间都是可用的,可以为我们提供服务的。高可用代表系统即使在发生硬件故障或者系统升级的时候,服务仍然是可用的 。 高可用描述的是一个系统在大部分时间都是可用的,可以为我们提供服务的。高可用代表系统即使在发生硬件故障或者系统升级的时候,服务仍然是可用的 。
相关阅读: **《[如何设计一个高可用系统?要考虑哪些地方?](docs/high-availability/高可用系统设计.md)》** 。 相关阅读: **《[如何设计一个高可用系统?要考虑哪些地方?](docs/high-availability/high-availability-system-design.md)》** 。
### 限流 ### 限流

View File

@ -1,427 +0,0 @@
const { config } = require("vuepress-theme-hope");
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = config({
port: "8080",
title: "JavaGuide",
description: "Java学习&&面试指南",
//指定 vuepress build 的输出目录
dest: "./dist",
// 是否开启默认预加载js
shouldPrefetch: (file, type) => false,
// webpack 配置 https://vuepress.vuejs.org/zh/config/#chainwebpack
// chainWebpack: config => {
// if (process.env.NODE_ENV === 'production') {
// const dateTime = new Date().getTime();
// // 清除js版本号
// config.output.filename('assets/js/jg-[name].js?v=' + dateTime).end();
// config.output.chunkFilename('assets/js/jg-[name].js?v=' + dateTime).end();
// // 清除css版本号
// config.plugin('mini-css-extract-plugin').use(require('mini-css-extract-plugin'), [{
// filename: 'assets/css/[name].css?v=' + dateTime,
// chunkFilename: 'assets/css/[name].css?v=' + dateTime
// }]).end();
// }
// },
configureWebpack: {
//vuepress 编译压缩
plugins: [new CompressionPlugin({
filename: "[path].gz", //编译后的文件名
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,//需要编译的文件
threshold: 10240,//需要编译的文件大小
minRatio: 0.8,//压缩比
deleteOriginalAssets: false,//编译时是否删除源文件
})],
},
head: [
// 百度站点验证
["meta", { name: "baidu-site-verification", content: "code-IZvTs9l2OK" }],
[
"script",
{ src: "https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js" },
],
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js",
},
],
["script", { src: "https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js" }],
[
"script",
{ src: "https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js" },
],
// 添加百度统计
[
"script", {},
`var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5dd2e8c97962d57b7b8fea1737c01743";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();`
]
],
locales: {
"/": {
lang: "zh-CN"
}
},
themeConfig: {
logo: "/logo.png", hostname: "https://javaguide.cn/", author: "Guide哥", repo: "https://github.com/Snailclimb/JavaGuide",
editLinks: true, docsDir: 'docs', seo: true,
nav: [
{ text: "Java面试指南", icon: "java", link: "/home", },
{ text: "官方知识星球", icon: "recommend", link: "https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc", },
{
text: "开发工具", icon: "Tools", link: "/tools/",
items: [
{ text: "Java", icon: "java", link: "/tools/java/jadx/" },
{ text: "Database", icon: "database", link: "/tools/database/chiner/" },
{ text: "Git", icon: "git", link: "/tools/git/git-intro/" },
{ text: "Docker", icon: "docker1", link: "/tools/docker/docker-intro/" },
{ text: "IntelliJ IDEA", icon: "intellijidea", link: "/idea-tutorial/" },
]
},
{ text: "关于作者", icon: "zuozhe", link: "/about-the-author/" },
],
sidebar: {
// 应该把更精确的路径放置在前边
"/javaguide/": [
"intro", "contribution-guideline", "faq", "todo"
],
"/about-the-author/": [
{
title: "个人经历", icon: "zuozhe", collapsable: false,
children: ["internet-addiction-teenager", "javaguide-100k-star", "feelings-after-one-month-of-induction-training", "feelings-of-half-a-year-from-graduation-to-entry",]
},
{
title: "杂谈", icon: "chat", collapsable: false,
children: ["my-article-was-stolen-and-made-into-video-and-it-became-popular", "dog-that-copies-other-people-essay",]
},
],
'/tools/': [
{
title: "Java", icon: "java", prefix: "java/", collapsable: false,
children: ["jadx"]
},
{
title: "Database", icon: "database", prefix: "database/", collapsable: false,
children: ["chiner", "dbeaver", "screw", "datagrip"]
},
{
title: "Git", icon: "git", prefix: "git/", collapsable: false,
children: ["git-intro", "github-tips"]
},
{
title: "Docker", icon: "docker1", prefix: "docker/", collapsable: false,
children: ["docker-intro", "docker-in-action"]
},
],
'/high-quality-technical-articles/': [
{
title: "练级攻略", icon: "lujing", prefix: "advanced-programmer/", collapsable: false,
children: ["seven-tips-for-becoming-an-advanced-programmer"]
},
{
title: "个人经历", icon: "zuozhe", prefix: "personal-experience/", collapsable: false,
children: ["two-years-of-back-end-develop--experience-in-didi&toutiao", "8-years-programmer-work-summary"]
},
{
title: "面试", icon: "mianshixinxi-02", prefix: "interview/", collapsable: false,
children: ["the-experience-and-thinking-of-an-interview-experienced-by-an-older-programmer", "technical-preliminary-preparation", "screen-candidates-for-packaging"],
},
{
title: "工作", icon: "work0", prefix: "work/", collapsable: false,
children: ["get-into-work-mode-quickly-when-you-join-a-company"]
}
],
'/idea-tutorial/':
[
{
title: "IDEA小技巧", icon: "tips", prefix: "idea-tips/", collapsable: false,
children: [
"idea-refractor-intro",
"idea-plug-in-development-intro",
"idea-source-code-reading-skills",
]
},
{
title: "IDEA插件推荐", icon: "chajian1", collapsable: false, prefix: "idea-plugins/",
children: [
"shortcut-key", "idea-themes", "improve-code", "interface-beautification",
"camel-case", "code-glance", "code-statistic",
"git-commit-template", "gson-format", "idea-features-trainer", "jclasslib",
"maven-helper", "rest-devlop", "save-actions", "sequence-diagram", "translation",
"others"
]
},
],
// 必须放在最后面
'/': [{
title: "Java", icon: "java", prefix: "java/",
children: [
{
title: "基础", prefix: "basis/",
children: [
"java-basic-questions-01", "java-basic-questions-02", "java-basic-questions-03",
{
title: "重要知识点",
children: [
"why-there-only-value-passing-in-java", "reflection", "proxy", "io",
"bigdecimal", "generics"
],
},],
},
{
title: "容器", prefix: "collection/",
children: [
"java-collection-questions-01", "java-collection-questions-02", "java集合使用注意事项",
{
title: "源码分析",
children: ["arraylist-source-code", "hashmap-source-code", "concurrent-hash-map-source-code"],
},],
},
{
title: "并发编程", prefix: "concurrent/",
children: [
"java-concurrent-questions-01", "java-concurrent-questions-02",
{
title: "重要知识点",
children: ["java-thread-pool-summary", "java-thread-pool-best-practices", "java-concurrent-collections", "aqs", "reentrantlock",
"atomic-classes", "threadlocal", "completablefuture-intro"],
},
],
},
{
title: "JVM", prefix: "jvm/",
children: ["memory-area", "jvm-garbage-collection", "class-file-structure", "class-loading-process", "classloader", "jvm-parameters-intro", "jvm-intro", "jdk-monitoring-and-troubleshooting-tools"],
},
{
title: "新特性", prefix: "new-features/",
children: ["java8-common-new-features", "java8-tutorial-translate", "java新特性总结"],
},
{
title: "小技巧", prefix: "tips/",
children: ["locate-performance-problems/手把手教你定位常见Java性能问题", "jad"],
},
],
},
{
title: "计算机基础", icon: "computer", prefix: "cs-basics/",
children: [
{
title: "计算机网络", prefix: "network/", icon: "network",
children: [
"计算机网络常见面试题", "谢希仁老师的《计算机网络》内容总结", "HTTPS中的TLS"
],
},
{
title: "操作系统", prefix: "operating-system/", icon: "caozuoxitong",
children: [
"操作系统常见面试题&知识点总结", "linux-intro", "shell-intro"
],
},
{
title: "数据结构", prefix: "data-structure/", icon: "people-network-full",
children: [
"线性数据结构", "", "", "", "红黑树", "bloom-filter"
],
},
{
title: "算法", prefix: "algorithms/", icon: "suanfaku",
children: [
"几道常见的字符串算法题", "几道常见的链表算法题", "剑指offer部分编程题"
],
},
],
},
{
title: "数据库", icon: "database", prefix: "database/",
children: [
"数据库基础知识",
"字符集",
{
title: "MySQL", prefix: "mysql/",
children: [
"mysql知识点&面试题总结",
"a-thousand-lines-of-mysql-study-notes",
"mysql-high-performance-optimization-specification-recommendations",
"mysql-index", "mysql-logs", "transaction-isolation-level",
"innodb-implementation-of-mvcc", "how-sql-executed-in-mysql",
"some-thoughts-on-database-storage-time"
],
},
{
title: "Redis", prefix: "redis/",
children: ["redis-questions-01", "3-commonly-used-cache-read-and-write-strategies"],
},
],
},
{
title: "系统设计", icon: "xitongsheji", prefix: "system-design/",
children: [
"system-design-questions",
{
title: "基础", prefix: "basis/", icon: "jibendebasic",
children: [
"RESTfulAPI",
"naming",
],
},
{
title: "常用框架", prefix: "framework/", icon: "framework",
children: [{
title: "Spring", prefix: "spring/",
children: [
"spring-knowledge-and-questions-summary", "spring-common-annotations", "spring-transaction", "spring-design-patterns-summary", "spring-boot-auto-assembly-principles"
]
},
"mybatis/mybatis-interview", "netty",
{
title: "SpringCloud", prefix: "springcloud/",
children: ["springcloud-intro"]
},
],
},
{
title: "安全", prefix: "security/", icon: "security-fill",
children: ["basis-of-authority-certification", "advantages&disadvantages-of-jwt", "sso-intro", "sentive-words-filter", "data-desensitization"]
},
"定时任务"
],
},
{
title: "分布式", icon: "distributed-network", prefix: "distributed-system/",
children: [
{
title: "理论&算法&协议", prefix: "theorem&algorithm&protocol/",
children: ["cap&base-theorem", "paxos-algorithm", "raft-algorithm"],
},
"api-gateway", "distributed-id",
{
title: "rpc", prefix: "rpc/",
children: ["dubbo", "why-use-rpc"]
},
"distributed-transaction",
{
title: "分布式协调", prefix: "distributed-process-coordination/",
children: ["zookeeper/zookeeper-intro", "zookeeper/zookeeper-plus", "zookeeper/zookeeper-in-action"]
},
],
}, {
title: "高性能", icon: "gaojixiaozuzhibeifen", prefix: "high-performance/",
children: [
"读写分离&分库分表", "负载均衡",
{
title: "消息队列", prefix: "message-queue/",
children: ["message-queue", "kafka知识点&面试题总结", "rocketmq-intro", "rocketmq-questions", "rabbitmq-intro"],
},
],
}, {
title: "高可用", icon: "CalendarAvailability-1", prefix: "high-availability/",
children: [
"高可用系统设计", "limit-request", "降级&熔断", "超时和重试机制", "集群", "灾备设计和异地多活", "性能测试"
],
}],
},
blog: {
intro: "/about-the-author/",
sidebarDisplay: "mobile",
links: {
Zhihu: "https://www.zhihu.com/people/javaguide",
Github: "https://github.com/Snailclimb",
Gitee: "https://gitee.com/SnailClimb",
},
},
footer: {
display: true,
content: '<a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a>',
},
copyright: {
status: "global",
},
git: {
timezone: "Asia/Shanghai",
},
mdEnhance: {
enableAll: false,
presentation: {
plugins: [
"highlight", "math", "search", "notes", "zoom", "anything", "audio", "chalkboard",
],
},
},
pwa: {
favicon: "/favicon.ico",
cachePic: false,
cacheHTML: false,
apple: {
icon: "/assets/icon/apple-icon-152.png",
statusBarColor: "black",
},
msTile: {
image: "/assets/icon/ms-icon-144.png",
color: "#ffffff",
},
manifest: {
icons: [
{
src: "/assets/icon/chrome-mask-512.png",
sizes: "512x512",
purpose: "maskable",
type: "image/png",
},
{
src: "/assets/icon/chrome-mask-192.png",
sizes: "192x192",
purpose: "maskable",
type: "image/png",
},
{
src: "/assets/icon/chrome-512.png",
sizes: "512x512",
type: "image/png",
},
{
src: "/assets/icon/chrome-192.png",
sizes: "192x192",
type: "image/png",
},
],
shortcuts: [
{
name: "Guide",
short_name: "Guide",
url: "/guide/",
icons: [
{
src: "/assets/icon/guide-maskable.png",
sizes: "192x192",
purpose: "maskable",
type: "image/png",
},
{
src: "/assets/icon/guide-monochrome.png",
sizes: "192x192",
purpose: "monochrome",
type: "image/png",
},
],
},
],
},
},
},
});

55
docs/.vuepress/config.ts Normal file
View File

@ -0,0 +1,55 @@
const { defineHopeConfig } = require("vuepress-theme-hope");
import themeConfig from "./themeConfig";
module.exports = defineHopeConfig({
port: "8080",
title: "JavaGuide",
description: "Java学习&&面试指南",
//指定 vuepress build 的输出目录
dest: "./dist",
// 是否开启默认预加载 js
shouldPrefetch: (file, type) => false,
head: [
// 百度站点验证
["meta", { name: "baidu-site-verification", content: "code-IZvTs9l2OK" }],
[
"script",
{ src: "https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js" },
],
[
"script",
{
src: "https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js",
},
],
["script", { src: "https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js" }],
[
"script",
{ src: "https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js" },
],
// 添加百度统计
[
"script", {},
`var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5dd2e8c97962d57b7b8fea1737c01743";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();`
],
[
"link",
{
rel: "stylesheet",
href: "//at.alicdn.com/t/font_2922463_lu595twe5t.css",
},
],
],
locales: {
"/": {
lang: "zh-CN"
}
},
themeConfig,
});

28
docs/.vuepress/navbar.ts Normal file
View File

@ -0,0 +1,28 @@
import { defineNavbarConfig } from "vuepress-theme-hope";
export const navbarConfig = defineNavbarConfig([
{ text: "Java面试指南", icon: "java", link: "/home" },
{
text: "Java面试指北",
icon: "recommend",
link: "https://www.yuque.com/docs/share/f37fc804-bfe6-4b0d-b373-9c462188fec7",
},
{
text: "官方知识星球",
icon: "recommend",
link: "https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc",
},
{
text: "开发工具",
icon: "Tools",
link: "/tools/",
children: [
{ text: "Java", icon: "java", link: "/tools/java/jadx/" },
{ text: "Database", icon: "database", link: "/tools/database/chiner/" },
{ text: "Git", icon: "git", link: "/tools/git/git-intro/" },
{ text: "Docker", icon: "docker1", link: "/tools/docker/docker-intro/" },
{ text: "IntelliJ IDEA", icon: "intellijidea", link: "/idea-tutorial/" },
],
},
{ text: "关于作者", icon: "zuozhe", link: "/about-the-author/" },
]);

472
docs/.vuepress/sidebar.ts Normal file
View File

@ -0,0 +1,472 @@
import { defineSidebarConfig } from "vuepress-theme-hope";
export const sidebarConfig = defineSidebarConfig({
// 应该把更精确的路径放置在前边
"/javaguide/": ["intro", "contribution-guideline", "faq", "todo"],
"/about-the-author/": [
{
text: "个人经历",
icon: "zuozhe",
collapsable: false,
children: [
"internet-addiction-teenager",
"javaguide-100k-star",
"feelings-after-one-month-of-induction-training",
"feelings-of-half-a-year-from-graduation-to-entry",
],
},
{
text: "杂谈",
icon: "chat",
collapsable: false,
children: [
"my-article-was-stolen-and-made-into-video-and-it-became-popular",
"dog-that-copies-other-people-essay",
],
},
],
"/tools/": [
{
text: "Java",
icon: "java",
prefix: "java/",
collapsable: false,
children: ["jadx"],
},
{
text: "Database",
icon: "database",
prefix: "database/",
collapsable: false,
children: ["chiner", "dbeaver", "screw", "datagrip"],
},
{
text: "Git",
icon: "git",
prefix: "git/",
collapsable: false,
children: ["git-intro", "github-tips"],
},
{
text: "Docker",
icon: "docker1",
prefix: "docker/",
collapsable: false,
children: ["docker-intro", "docker-in-action"],
},
],
"/high-quality-technical-articles/": [
{
text: "练级攻略",
icon: "et-performance",
prefix: "advanced-programmer/",
collapsable: false,
children: ["seven-tips-for-becoming-an-advanced-programmer"],
},
{
text: "个人经历",
icon: "zuozhe",
prefix: "personal-experience/",
collapsable: false,
children: [
"two-years-of-back-end-develop--experience-in-didi&toutiao",
"8-years-programmer-work-summary",
],
},
{
text: "面试",
icon: "mianshixinxi-02",
prefix: "interview/",
collapsable: false,
children: [
"the-experience-and-thinking-of-an-interview-experienced-by-an-older-programmer",
"technical-preliminary-preparation",
"screen-candidates-for-packaging",
],
},
{
text: "工作",
icon: "work0",
prefix: "work/",
collapsable: false,
children: ["get-into-work-mode-quickly-when-you-join-a-company"],
},
],
"/idea-tutorial/": [
{
text: "IDEA小技巧",
icon: "tips",
prefix: "idea-tips/",
collapsable: false,
children: [
"idea-refractor-intro",
"idea-plug-in-development-intro",
"idea-source-code-reading-skills",
],
},
{
text: "IDEA插件推荐",
icon: "chajian1",
collapsable: false,
prefix: "idea-plugins/",
children: [
"shortcut-key",
"idea-themes",
"improve-code",
"interface-beautification",
"camel-case",
"code-glance",
"code-statistic",
"git-commit-template",
"gson-format",
"idea-features-trainer",
"jclasslib",
"maven-helper",
"rest-devlop",
"save-actions",
"sequence-diagram",
"translation",
"others",
],
},
],
// 必须放在最后面
"/": [
{
text: "Java",
icon: "java",
prefix: "java/",
collapsable: true,
children: [
{
text: "基础",
prefix: "basis/",
icon: "basic",
collapsable: true,
children: [
"java-basic-questions-01",
"java-basic-questions-02",
"java-basic-questions-03",
{
text: "重要知识点",
icon: "important",
collapsable: true,
children: [
"why-there-only-value-passing-in-java",
"reflection",
"proxy",
"io",
"bigdecimal",
"generics",
],
},
],
},
{
text: "容器",
prefix: "collection/",
icon: "container",
collapsable: true,
children: [
"java-collection-questions-01",
"java-collection-questions-02",
"java-collection-precautions-for-use",
{
text: "源码分析",
collapsable: true,
children: [
"arraylist-source-code",
"hashmap-source-code",
"concurrent-hash-map-source-code",
],
},
],
},
{
text: "并发编程",
prefix: "concurrent/",
icon: "et-performance",
collapsable: true,
children: [
"java-concurrent-questions-01",
"java-concurrent-questions-02",
{
text: "重要知识点",
icon: "important",
collapsable: true,
children: [
"java-thread-pool-summary",
"java-thread-pool-best-practices",
"java-concurrent-collections",
"aqs",
"reentrantlock",
"atomic-classes",
"threadlocal",
"completablefuture-intro",
],
},
],
},
{
text: "JVM",
prefix: "jvm/",
icon: "virtual_machine",
collapsable: true,
children: [
"memory-area",
"jvm-garbage-collection",
"class-file-structure",
"class-loading-process",
"classloader",
"jvm-parameters-intro",
"jvm-intro",
"jdk-monitoring-and-troubleshooting-tools",
],
},
{
text: "新特性",
prefix: "new-features/",
icon: "features",
collapsable: true,
children: [
"java8-common-new-features",
"java8-tutorial-translate",
"java9",
"java10",
"java11",
"java12-13",
"java14-15",
],
},
],
},
{
text: "计算机基础",
icon: "computer",
prefix: "cs-basics/",
collapsable: true,
children: [
{
text: "网络",
prefix: "network/",
icon: "network",
collapsable: true,
children: [
"osi&tcp-ip-model",
"http&https",
"http1.0&http1.1",
"other-network-questions",
],
},
{
text: "操作系统",
prefix: "operating-system/",
icon: "caozuoxitong",
collapsable: true,
children: [
"operating-system-basic-questions-01",
"linux-intro",
"shell-intro",
],
},
{
text: "数据结构",
prefix: "data-structure/",
icon: "people-network-full",
collapsable: true,
children: [
"linear-data-structure",
"graph",
"heap",
"tree",
"red-black-tree",
"bloom-filter",
],
},
{
text: "算法",
prefix: "algorithms/",
icon: "suanfaku",
collapsable: true,
children: [
"string-algorithm-problems",
"linkedlist-algorithm-problems",
"the-sword-refers-to-offer",
],
},
],
},
{
text: "数据库",
icon: "database",
prefix: "database/",
collapsable: true,
children: [
"basis",
"character-set",
{
text: "MySQL",
prefix: "mysql/",
icon: "mysql",
collapsable: true,
children: [
"mysql-questions-01",
"a-thousand-lines-of-mysql-study-notes",
"mysql-high-performance-optimization-specification-recommendations",
{
text: "重要知识点",
icon: "important",
collapsable: true,
children: [
"mysql-index",
"mysql-logs",
"transaction-isolation-level",
"innodb-implementation-of-mvcc",
"how-sql-executed-in-mysql",
"some-thoughts-on-database-storage-time",
],
},
],
},
{
text: "Redis",
prefix: "redis/",
icon: "redis",
collapsable: true,
children: [
"redis-questions-01",
"3-commonly-used-cache-read-and-write-strategies",
],
},
],
},
{
text: "系统设计",
icon: "xitongsheji",
prefix: "system-design/",
collapsable: true,
children: [
"system-design-questions",
{
text: "基础",
prefix: "basis/",
icon: "basic",
collapsable: true,
children: ["RESTfulAPI", "naming"],
},
{
text: "常用框架",
prefix: "framework/",
icon: "framework",
collapsable: true,
children: [
{
text: "Spring",
prefix: "spring/",
collapsable: true,
children: [
"spring-knowledge-and-questions-summary",
"spring-common-annotations",
"spring-transaction",
"spring-design-patterns-summary",
"spring-boot-auto-assembly-principles",
],
},
"mybatis/mybatis-interview",
"netty",
{
text: "SpringCloud",
prefix: "springcloud/",
children: ["springcloud-intro"],
},
],
},
{
text: "安全",
prefix: "security/",
icon: "security-fill",
collapsable: true,
children: [
"basis-of-authority-certification",
"advantages&disadvantages-of-jwt",
"sso-intro",
"sentive-words-filter",
"data-desensitization",
],
},
"schedule-task",
],
},
{
text: "分布式",
icon: "distributed-network",
prefix: "distributed-system/",
collapsable: true,
children: [
{
text: "理论&算法&协议",
prefix: "theorem&algorithm&protocol/",
collapsable: true,
children: ["cap&base-theorem", "paxos-algorithm", "raft-algorithm"],
},
"api-gateway",
"distributed-id",
{
text: "RPC",
prefix: "rpc/",
collapsable: true,
children: ["dubbo", "why-use-rpc"],
},
"distributed-transaction",
{
text: "分布式协调",
prefix: "distributed-process-coordination/",
collapsable: true,
children: [
"zookeeper/zookeeper-intro",
"zookeeper/zookeeper-plus",
"zookeeper/zookeeper-in-action",
],
},
],
},
{
text: "高性能",
icon: "et-performance",
prefix: "high-performance/",
collapsable: true,
children: [
"read-and-write-separation-and-library-subtable",
"load-balancing",
{
text: "消息队列",
prefix: "message-queue/",
icon: "MQ",
collapsable: true,
children: [
"message-queue",
"kafka-questions-01",
"rocketmq-intro",
"rocketmq-questions",
"rabbitmq-intro",
],
},
],
},
{
text: "高可用",
icon: "CalendarAvailability-1",
prefix: "high-availability/",
collapsable: true,
children: [
"high-availability-system-design",
"limit-request",
"fallback&circuit-breaker",
"timeout-and-retry",
"cluster",
"disaster-recovery&remote-live",
"performance-test",
],
},
],
});

View File

View File

@ -1,2 +0,0 @@
// import icon
@import '//at.alicdn.com/t/font_2922463_m6dpqhk3xfh.css'

View File

@ -0,0 +1,4 @@
// colors
$themeColor: #2980B9;
$sidebarWidth: 20rem;
$sidebarMobileWidth: 16rem;

View File

@ -0,0 +1,103 @@
import { defineThemeConfig } from "vuepress-theme-hope";
import { navbarConfig } from "./navbar";
import { sidebarConfig } from "./sidebar";
export default defineThemeConfig({
logo: "/logo.png",
hostname: "https://javaguide.cn/",
author: "Guide哥",
repo: "https://github.com/Snailclimb/JavaGuide",
docsDir: "docs",
iconPrefix: "iconfont icon-",
pure: true,
navbar: navbarConfig,
sidebar: sidebarConfig,
blog: {
intro: "/about-the-author/",
sidebarDisplay: "mobile",
medias: {
Zhihu: "https://www.zhihu.com/people/javaguide",
Github: "https://github.com/Snailclimb",
Gitee: "https://gitee.com/SnailClimb",
},
},
footer:
'<a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a>',
displayFooter: true,
plugins: {
blog: {
autoExcerpt: true,
},
mdEnhance: {
enableAll: false,
presentation: {
plugins: ["highlight", "math", "search", "notes", "zoom"],
},
},
// docsearch: {
// appId: "",
// apiKey: "",
// indexName: "",
// },
pwa: {
favicon: "/favicon.ico",
cachePic: false,
cacheHTML: false,
apple: {
icon: "/assets/icon/apple-icon-152.png",
statusBarColor: "black",
},
msTile: {
image: "/assets/icon/ms-icon-144.png",
color: "#ffffff",
},
manifest: {
icons: [
{
src: "/assets/icon/chrome-mask-512.png",
sizes: "512x512",
purpose: "maskable",
type: "image/png",
},
{
src: "/assets/icon/chrome-mask-192.png",
sizes: "192x192",
purpose: "maskable",
type: "image/png",
},
{
src: "/assets/icon/chrome-512.png",
sizes: "512x512",
type: "image/png",
},
{
src: "/assets/icon/chrome-192.png",
sizes: "192x192",
type: "image/png",
},
],
shortcuts: [
{
name: "Guide",
short_name: "Guide",
url: "/guide/",
icons: [
{
src: "/assets/icon/guide-maskable.png",
sizes: "192x192",
purpose: "maskable",
type: "image/png",
},
{
src: "/assets/icon/guide-monochrome.png",
sizes: "192x192",
purpose: "monochrome",
type: "image/png",
},
],
},
],
},
},
},
});

View File

@ -23,7 +23,7 @@ tag:
下图所展示的就是图这种数据结构,并且还是一张有向图。 下图所展示的就是图这种数据结构,并且还是一张有向图。
![](pictures/图/图.png) ![](https://img-blog.csdnimg.cn/7f232c9660c54ee1ac182b7c0bf267a3.png)
图在我们日常生活中的例子很多!比如我们在社交软件上好友关系就可以用图来表示。 图在我们日常生活中的例子很多!比如我们在社交软件上好友关系就可以用图来表示。
@ -67,11 +67,11 @@ tag:
在无向图中我们只关心关系的有无所以当顶点i和顶点j有关系时`A[i][j]`=1当顶点i和顶点j没有关系时`A[i][j]`=0。如下图所示 在无向图中我们只关心关系的有无所以当顶点i和顶点j有关系时`A[i][j]`=1当顶点i和顶点j没有关系时`A[i][j]`=0。如下图所示
![无向图的邻接矩阵存储](pictures/图/无向图的邻接矩阵存储.png) ![无向图的邻接矩阵存储](./pictures/图/无向图的邻接矩阵存储.png)
值得注意的是:**无向图的邻接矩阵是一个对称矩阵因为在无向图中顶点i和顶点j有关系则顶点j和顶点i必有关系。** 值得注意的是:**无向图的邻接矩阵是一个对称矩阵因为在无向图中顶点i和顶点j有关系则顶点j和顶点i必有关系。**
![有向图的邻接矩阵存储](pictures/图/有向图的邻接矩阵存储.png) ![有向图的邻接矩阵存储](./pictures/图/有向图的邻接矩阵存储.png)
邻接矩阵存储的方式优点是简单直接(直接使用一个二维数组即可),并且,在获取两个定点之间的关系的时候也非常高效(直接获取指定位置的数组元素的值即可)。但是,这种存储方式的缺点也比较明显,那就是比较浪费空间, 邻接矩阵存储的方式优点是简单直接(直接使用一个二维数组即可),并且,在获取两个定点之间的关系的时候也非常高效(直接获取指定位置的数组元素的值即可)。但是,这种存储方式的缺点也比较明显,那就是比较浪费空间,
@ -83,11 +83,11 @@ tag:
![无向图的邻接表存储](pictures/图/无向图的邻接表存储.png) ![无向图的邻接表存储](./pictures/图/无向图的邻接表存储.png)
![有向图的邻接表存储](pictures/图/有向图的邻接表存储.png) ![有向图的邻接表存储](./pictures/图/有向图的邻接表存储.png)
大家可以数一数邻接表中所存储的元素的个数以及图中边的条数,你会发现: 大家可以数一数邻接表中所存储的元素的个数以及图中边的条数,你会发现:
@ -98,64 +98,64 @@ tag:
### 广度优先搜索 ### 广度优先搜索
广度优先搜索就像水面上的波纹一样一层一层向外扩展,如下图所示: 广度优先搜索就像水面上的波纹一样一层一层向外扩展,如下图所示:
![广度优先搜索图示](pictures/图/广度优先搜索图示.png) ![广度优先搜索图示](./pictures/图/广度优先搜索图示.png)
**广度优先搜索的具体实现方式用到了之前所学过的线性数据结构——队列** 。具体过程如下图所示: **广度优先搜索的具体实现方式用到了之前所学过的线性数据结构——队列** 。具体过程如下图所示:
**第1步** **第1步**
![广度优先搜索1](pictures/图/广度优先搜索1.png) ![广度优先搜索1](./pictures/图/广度优先搜索1.png)
**第2步** **第2步**
![广度优先搜索2](pictures/图/广度优先搜索2.png) ![广度优先搜索2](./pictures/图/广度优先搜索2.png)
**第3步** **第3步**
![广度优先搜索3](pictures/图/广度优先搜索3.png) ![广度优先搜索3](./pictures/图/广度优先搜索3.png)
**第4步** **第4步**
![广度优先搜索4](pictures/图/广度优先搜索4.png) ![广度优先搜索4](./pictures/图/广度优先搜索4.png)
**第5步** **第5步**
![广度优先搜索5](pictures/图/广度优先搜索5.png) ![广度优先搜索5](./pictures/图/广度优先搜索5.png)
**第6步** **第6步**
![广度优先搜索6](pictures/图/广度优先搜索6.png) ![广度优先搜索6](./pictures/图/广度优先搜索6.png)
### 深度优先搜索 ### 深度优先搜索
深度优先搜索就是“一条路走到黑”,从源顶点开始,一直走到没有后继节点,才回溯到上一顶点,然后继续“一条路走到黑”,如下图所示: 深度优先搜索就是“一条路走到黑”,从源顶点开始,一直走到没有后继节点,才回溯到上一顶点,然后继续“一条路走到黑”,如下图所示:
![深度优先搜索图示](pictures/图/深度优先搜索图示.png) ![深度优先搜索图示](./pictures/图/深度优先搜索图示.png)
**和广度优先搜索类似,深度优先搜索的具体实现用到了另一种线性数据结构——栈** 。具体过程如下图所示: **和广度优先搜索类似,深度优先搜索的具体实现用到了另一种线性数据结构——栈** 。具体过程如下图所示:
**第1步** **第1步**
![深度优先搜索1](pictures/图/深度优先搜索1.png) ![深度优先搜索1](./pictures/图/深度优先搜索1.png)
**第2步** **第2步**
![深度优先搜索1](pictures/图/深度优先搜索2.png) ![深度优先搜索1](./pictures/图/深度优先搜索2.png)
**第3步** **第3步**
![深度优先搜索1](pictures/图/深度优先搜索3.png) ![深度优先搜索1](./pictures/图/深度优先搜索3.png)
**第4步** **第4步**
![深度优先搜索1](pictures/图/深度优先搜索4.png) ![深度优先搜索1](./pictures/图/深度优先搜索4.png)
**第5步** **第5步**
![深度优先搜索1](pictures/图/深度优先搜索5.png) ![深度优先搜索1](./pictures/图/深度优先搜索5.png)
**第6步** **第6步**
![深度优先搜索1](pictures/图/深度优先搜索6.png) ![深度优先搜索1](./pictures/图/深度优先搜索6.png)

View File

@ -21,7 +21,7 @@ tag:
大家可以尝试判断下面给出的图是否是堆? 大家可以尝试判断下面给出的图是否是堆?
![](pictures/堆/堆1.png) ![](./pictures/堆/堆1.png)
第1个和第2个是堆。第1个是最大堆每个节点都比子树中所有节点大。第2个是最小堆每个节点都比子树中所有节点小。 第1个和第2个是堆。第1个是最大堆每个节点都比子树中所有节点大。第2个是最小堆每个节点都比子树中所有节点小。
@ -42,7 +42,7 @@ tag:
如下图所示图1是最大堆图2是最小堆 如下图所示图1是最大堆图2是最小堆
![](pictures/堆/堆2.png) ![](./pictures/堆/堆2.png)
## 堆的存储 ## 堆的存储
@ -50,7 +50,7 @@ tag:
为了方便存储和索引,(二叉)堆可以用完全二叉树的形式进行存储。存储的方式如下图所示: 为了方便存储和索引,(二叉)堆可以用完全二叉树的形式进行存储。存储的方式如下图所示:
![堆的存储](pictures/堆/堆的存储.png) ![堆的存储](./pictures/堆/堆的存储.png)
## 堆的操作 ## 堆的操作
堆的更新操作主要包括两种 : **插入元素****删除堆顶元素**。操作过程需要着重掌握和理解。 堆的更新操作主要包括两种 : **插入元素****删除堆顶元素**。操作过程需要着重掌握和理解。
@ -60,15 +60,15 @@ tag:
**1.将要插入的元素放到最后** **1.将要插入的元素放到最后**
![堆-插入元素-1](pictures/堆/堆-插入元素1.png) ![堆-插入元素-1](./pictures/堆/堆-插入元素1.png)
> 有能力的人会逐渐升职加薪,是金子总会发光的!!! > 有能力的人会逐渐升职加薪,是金子总会发光的!!!
**2.从底向上,如果父结点比该元素大,则该节点和父结点交换,直到无法交换** **2.从底向上,如果父结点比该元素大,则该节点和父结点交换,直到无法交换**
![堆-插入元素2](pictures/堆/堆-插入元素2.png) ![堆-插入元素2](./pictures/堆/堆-插入元素2.png)
![堆-插入元素3](pictures/堆/堆-插入元素3.png) ![堆-插入元素3](./pictures/堆/堆-插入元素3.png)
### 删除堆顶元素 ### 删除堆顶元素
@ -87,34 +87,34 @@ tag:
![删除堆顶元素1](pictures/堆/删除堆顶元素1.png) ![删除堆顶元素1](./pictures/堆/删除堆顶元素1.png)
> 那么他的位置由谁来接替呢,当然是他的直接下属了,谁能力强就让谁上呗 > 那么他的位置由谁来接替呢,当然是他的直接下属了,谁能力强就让谁上呗
比较根结点的左子节点和右子节点也就是下标为2,3的数组元素将较大的元素填充到根结点(下标为1)的位置。 比较根结点的左子节点和右子节点也就是下标为2,3的数组元素将较大的元素填充到根结点(下标为1)的位置。
![删除堆顶元素2](pictures/堆/删除堆顶元素2.png) ![删除堆顶元素2](./pictures/堆/删除堆顶元素2.png)
> 这个时候又空出一个位置了,老规矩,谁有能力谁上 > 这个时候又空出一个位置了,老规矩,谁有能力谁上
一直循环比较空出位置的左右子节点,并将较大者移至空位,直到堆的最底部 一直循环比较空出位置的左右子节点,并将较大者移至空位,直到堆的最底部
![删除堆顶元素3](pictures/堆/删除堆顶元素3.png) ![删除堆顶元素3](./pictures/堆/删除堆顶元素3.png)
这个时候已经完成了自底向上的堆化,没有元素可以填补空缺了,但是,我们可以看到数组中出现了“气泡”,这会导致存储空间的浪费。接下来我们试试自顶向下堆化。 这个时候已经完成了自底向上的堆化,没有元素可以填补空缺了,但是,我们可以看到数组中出现了“气泡”,这会导致存储空间的浪费。接下来我们试试自顶向下堆化。
#### 自顶向下堆化 #### 自顶向下堆化
自顶向下的堆化用一个词形容就是“石沉大海”,那么第一件事情,就是把石头抬起来,从海面扔下去。这个石头就是堆的最后一个元素,我们将最后一个元素移动到堆顶。 自顶向下的堆化用一个词形容就是“石沉大海”,那么第一件事情,就是把石头抬起来,从海面扔下去。这个石头就是堆的最后一个元素,我们将最后一个元素移动到堆顶。
![删除堆顶元素4](pictures/堆/删除堆顶元素4.png) ![删除堆顶元素4](./pictures/堆/删除堆顶元素4.png)
然后开始将这个石头沉入海底,不停与左右子节点的值进行比较,和较大的子节点交换位置,直到无法交换位置。 然后开始将这个石头沉入海底,不停与左右子节点的值进行比较,和较大的子节点交换位置,直到无法交换位置。
![删除堆顶元素5](pictures/堆/删除堆顶元素5.png) ![删除堆顶元素5](./pictures/堆/删除堆顶元素5.png)
![删除堆顶元素6](pictures/堆/删除堆顶元素6.png) ![删除堆顶元素6](./pictures/堆/删除堆顶元素6.png)
@ -139,20 +139,20 @@ tag:
具体过程如下图: 具体过程如下图:
![建堆1](pictures/堆/建堆1.png) ![建堆1](./pictures/堆/建堆1.png)
将初始的无序数组抽象为一棵树图中的节点个数为6所以4,5,6节点为叶节点1,2,3节点为非叶节点所以要对1-3号节点进行自顶向下沉底堆化注意顺序是从后往前堆化从3号节点开始一直到1号节点。 将初始的无序数组抽象为一棵树图中的节点个数为6所以4,5,6节点为叶节点1,2,3节点为非叶节点所以要对1-3号节点进行自顶向下沉底堆化注意顺序是从后往前堆化从3号节点开始一直到1号节点。
3号节点堆化结果 3号节点堆化结果
![建堆1](pictures/堆/建堆2.png) ![建堆1](./pictures/堆/建堆2.png)
2号节点堆化结果 2号节点堆化结果
![建堆1](pictures/堆/建堆3.png) ![建堆1](./pictures/堆/建堆3.png)
1号节点堆化结果 1号节点堆化结果
![建堆1](pictures/堆/建堆4.png) ![建堆1](./pictures/堆/建堆4.png)
至此,数组所对应的树已经成为了一个最大堆,建堆完成! 至此,数组所对应的树已经成为了一个最大堆,建堆完成!
@ -173,26 +173,26 @@ tag:
取出第一个元素并堆化: 取出第一个元素并堆化:
![堆排序1](pictures/堆/堆排序1.png) ![堆排序1](./pictures/堆/堆排序1.png)
取出第二个元素并堆化: 取出第二个元素并堆化:
![堆排序2](pictures/堆/堆排序2.png) ![堆排序2](./pictures/堆/堆排序2.png)
取出第三个元素并堆化: 取出第三个元素并堆化:
![堆排序3](pictures/堆/堆排序3.png) ![堆排序3](./pictures/堆/堆排序3.png)
取出第四个元素并堆化: 取出第四个元素并堆化:
![堆排序4](pictures/堆/堆排序4.png) ![堆排序4](./pictures/堆/堆排序4.png)
取出第五个元素并堆化: 取出第五个元素并堆化:
![堆排序5](pictures/堆/堆排序5.png) ![堆排序5](./pictures/堆/堆排序5.png)
取出第六个元素并堆化: 取出第六个元素并堆化:
![堆排序6](pictures/堆/堆排序6.png) ![堆排序6](./pictures/堆/堆排序6.png)
堆排序完成! 堆排序完成!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1,124 +0,0 @@
---
title: HTTPS中的TLS
category: 计算机基础
tag:
- 计算机网络
---
# 1. SSL 与 TLS
SSLSecure Socket Layer 安全套接层,于 1994 年由网景公司设计,并于 1995 年发布了 3.0 版本
TLSTransport Layer Security传输层安全性协议是 IETF 在 SSL3.0 的基础上设计的协议
以下全部使用 TLS 来表示
# 2. 从网络协议的角度理解 HTTPS
![此图并不准确][1]
HTTPHyperText Transfer Protocol 超文本传输协议
HTTPSHypertext Transfer Protocol Secure 超文本传输安全协议
TLS位于 HTTP 和 TCP 之间的协议,其内部有 TLS握手协议、TLS记录协议
HTTPS 经由 HTTP 进行通信,但利用 TLS 来保证安全,即 HTTPS = HTTP + TLS
# 3. 从密码学的角度理解 HTTPS
HTTPS 使用 TLS 保证安全,这里的“安全”分两部分,一是传输内容加密、二是服务端的身份认证
## 3.1. TLS 工作流程
![此图并不准确][2]
此为服务端单向认证,还有客户端/服务端双向认证,流程类似,只不过客户端也有自己的证书,并发送给服务器进行验证
## 3.2. 密码基础
### 3.2.1. 伪随机数生成器
为什么叫伪随机数,因为没有真正意义上的随机数,具体可以参考 Random/TheadLocalRandom
它的主要作用在于生成对称密码的秘钥、用于公钥密码生成秘钥对
### 3.2.2. 消息认证码
消息认证码主要用于验证消息的完整性与消息的认证,其中消息的认证指“消息来自正确的发送者”
>消息认证码用于验证和认证,而不是加密
![消息认证码过程][3]
1. 发送者与接收者事先共享秘钥
2. 发送者根据发送消息计算 MAC 值
3. 发送者发送消息和 MAC 值
4. 接收者根据接收到的消息计算 MAC 值
5. 接收者根据自己计算的 MAC 值与收到的 MAC 对比
6. 如果对比成功,说明消息完整,并来自于正确的发送者
### 3.2.3. 数字签名
消息认证码的缺点在于**无法防止否认**,因为共享秘钥被 client、server 两端拥有server 可以伪造 client 发送给自己的消息(自己给自己发送消息),为了解决这个问题,我们需要它们有各自的秘钥不被第二个知晓(这样也解决了共享秘钥的配送问题)
![数字签名过程][4]
>数字签名和消息认证码都**不是为了加密**
>可以将单向散列函数获取散列值的过程理解为使用 md5 摘要算法获取摘要的过程
使用自己的私钥对自己所认可的消息生成一个该消息专属的签名,这就是数字签名,表明我承认该消息来自自己
注意:**私钥用于加签,公钥用于解签,每个人都可以解签,查看消息的归属人**
### 3.2.4. 公钥密码
公钥密码也叫非对称密码,由公钥和私钥组成,它最开始是为了解决秘钥的配送传输安全问题,即,我们不配送私钥,只配送公钥,私钥由本人保管
它与数字签名相反,公钥密码的私钥用于解密、公钥用于加密,每个人都可以用别人的公钥加密,但只有对应的私钥才能解开密文
client明文 + 公钥 = 密文
server密文 + 私钥 = 明文
注意:**公钥用于加密,私钥用于解密,只有私钥的归属者,才能查看消息的真正内容**
### 3.2.5. 证书
证书全称公钥证书Public-Key Certificate, PKC,里面保存着归属者的基本信息以及证书过期时间、归属者的公钥并由认证机构Certification Authority, **CA**)施加数字签名,表明,某个认证机构认定该公钥的确属于此人
>想象这个场景:你想在支付宝页面交易,你需要支付宝的公钥进行加密通信,于是你从百度上搜索关键字“支付宝公钥”,你获得了支什宝的公钥,这个时候,支什宝通过中间人攻击,让你访问到了他们支什宝的页面,最后你在这个支什宝页面完美的使用了支什宝的公钥完成了与支什宝的交易
>![证书过程][5]
在上面的场景中,你可以理解支付宝证书就是由支付宝的公钥、和给支付宝颁发证书的企业的数字签名组成
任何人都可以给自己或别人的公钥添加自己的数字签名,表明:我拿我的尊严担保,我的公钥/别人的公钥是真的,至于信不信那是另一回事了
### 3.2.6. 密码小结
| 密码 | 作用 | 组成 |
| :-- | :-- | :-- |
| 消息认证码 | 确认消息的完整、并对消息的来源认证 | 共享秘钥+消息的散列值 |
| 数字签名 | 对消息的散列值签名 | 公钥+私钥+消息的散列值 |
| 公钥密码 | 解决秘钥的配送问题 | 公钥+私钥+消息 |
| 证书 | 解决公钥的归属问题 | 公钥密码中的公钥+数字签名 |
## 3.3. TLS 使用的密码技术
1. 伪随机数生成器:秘钥生成随机性,更难被猜测
2. 对称密码:对称密码使用的秘钥就是由伪随机数生成,相较于非对称密码,效率更高
3. 消息认证码:保证消息信息的完整性、以及验证消息信息的来源
4. 公钥密码:证书技术使用的就是公钥密码
5. 数字签名:验证证书的签名,确定由真实的某个 CA 颁发
6. 证书:解决公钥的真实归属问题,降低中间人攻击概率
## 3.4. TLS 总结
TLS 是一系列密码工具的框架,作为框架,它也是非常的灵活,体现在每个工具套件它都可以替换,即:客户端与服务端之间协商密码套件,从而更难的被攻破,例如使用不同方式的对称密码,或者公钥密码、数字签名生成方式、单向散列函数技术的替换等
# 4. RSA 简单示例
RSA 是一种公钥密码算法,我们简单的走一遍它的加密解密过程
加密算法:密文 = (明文^E) mod N其中公钥为{E,N}即”求明文的E次方的对 N 的余数“
解密算法:明文 = (密文^D) mod N其中秘钥为{D,N}即”求密文的D次方的对 N 的余数“
例:我们已知公钥为{5,323},私钥为{29,323}明文为300请写出加密和解密的过程
>加密:密文 = 123 ^ 5 mod 323 = 225
>解密:明文 = 225 ^ 29 mod 323 = [[(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 4) mod 323]] mod 323 = (4 * 4 * 4 * 4 * 4 * 290) mod 323 = 123
# 5. 参考
1. SSL加密发生在哪里<https://security.stackexchange.com/questions/19681/where-does-ssl-encryption-take-place>
2. TLS工作流程<https://blog.csdn.net/ustccw/article/details/76691248>
3. 《图解密码技术》:<https://book.douban.com/subject/26822106/> 豆瓣评分 9.5
[1]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/%E4%B8%83%E5%B1%82.png
[2]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/tls%E6%B5%81%E7%A8%8B.png
[3]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/%E6%B6%88%E6%81%AF%E8%AE%A4%E8%AF%81%E7%A0%81%E8%BF%87%E7%A8%8B.png
[4]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D%E8%BF%87%E7%A8%8B.png
[5]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/dns%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB.png

View File

@ -0,0 +1,149 @@
---
title: HTTP vs HTTPS应用层
category: 计算机基础
tag:
- 计算机网络
---
> 本文由 [SnailClimb](https://github.com/Snailclimb) 和 [csguide-dabai](https://github.com/csguide-dabai) 公众号“CS指南”作者共同完成。
## HTTP 协议
### HTTP 协议介绍
HTTP 协议全称超文本传输协议Hypertext Transfer Protocol。顾名思义HTTP 协议就是用来规范超文本的传输,超文本,也就是网络上的包括文本在内的各式各样的消,具体来说,主要是来规范浏览器和服务器端的行为的。
并且HTTP 是一个无状态stateless协议也就是说服务器不维护任何有关客户端过去所发请求的消息。这其实是一种懒政有状态协议会更加复杂需要维护状态历史信息而且如果客户或服务器失效会产生状态的不一致解决这种不一致的代价更高。
### HTTP 协议通信过程
HTTP 是应用层协议,它以 TCP传输层作为底层协议默认端口为 80. 通信过程主要如下:
1. 服务器在 80 端口等待客户的请求。
2. 浏览器发起到服务器的 TCP 连接(创建套接字 Socket
3. 服务器接收来自浏览器的 TCP 连接。
4. 浏览器HTTP 客户端)与 Web 服务器HTTP 服务器)交换 HTTP 消息。
5. 关闭 TCP 连接。
### HTTP 协议优点
扩展性强、速度快、跨平台支持性好。
## HTTPS 协议
### HTTPS 协议介绍
HTTPS 协议Hyper Text Transfer Protocol Secure是 HTTP 的加强安全版本。HTTPS 是基于 HTTP 的,也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证。默认端口号是 443.
HTTPS 协议中SSL 通道通常使用基于密钥的加密算法,密钥长度通常是 40 比特或 128 比特。
### HTTPS 协议优点
保密性好、信任度高。
## HTTPS 的核心—SSL/TLS协议
HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题。接下来重点介绍一下 SSL/TLS 的工作原理。
### SSL 和 TLS 的区别?
**SSL 和 TLS 没有太大的区别。**
SSL 指安全套接字协议Secure Sockets Layer首次发布与 1996 年。SSL 的首次发布其实已经是他的 3.0 版本SSL 1.0 从未面世SSL 2.0 则具有较大的缺陷DROWN 缺陷——Decrypting RSA with Obsolete and Weakened eNcryption。很快在 1999 年SSL 3.0 进一步升级,**新版本被命名为 TLS 1.0**。因此TLS 是基于 SSL 之上的,但由于习惯叫法,通常把 HTTPS 中的核心加密协议混成为 SSL/TLS。
### SSL/TLS 的工作原理
#### 非对称加密
SSL/TLS 的核心要素是**非对称加密**。非对称加密采用两个密钥——一个公钥,一个私钥。在通信时,私钥仅由解密者保存,公钥由任何一个想与解密者通信的发送者(加密者)所知。可以设想一个场景,
> 在某个自助邮局,每个通信信道都是一个邮箱,每一个邮箱所有者都在旁边立了一个牌子,上面挂着一把钥匙:这是我的公钥,发送者请将信件放入我的邮箱,并用公钥锁好。
>
> 但是公钥只能加锁,并不能解锁。解锁只能由邮箱的所有者——因为只有他保存着私钥。
>
> 这样,通信信息就不会被其他人截获了,这依赖于私钥的保密性。
![](./images/http&https/public-key-cryptography.png)
非对称加密的公钥和私钥需要采用一种复杂的数学机制生成(密码学认为,为了较高的安全性,尽量不要自己创造加密方案)。公私钥对的生成算法依赖于单向陷门函数。
> 单向函数:已知单向函数 f给定任意一个输入 x易计算输出 y=f(x);而给定一个输出 y假设存在 f(x)=y很难根据 f 来计算出 x。
>
> 单向陷门函数:一个较弱的单向函数。已知单向陷门函数 f陷门 h给定任意一个输入 x易计算出输出 y=f(x;h);而给定一个输出 y假设存在 f(x;h)=y很难根据 f 来计算出 x但可以根据 f 和 h 来推导出 x。
![单向函数](./images/http&https/OWF.png)
上图就是一个单向函数(不是单项陷门函数),假设有一个绝世秘籍,任何知道了这个秘籍的人都可以把苹果汁榨成苹果,那么这个秘籍就是“陷门”了吧。
在这里,函数 f 的计算方法相当于公钥,陷门 h 相当于私钥。公钥 f 是公开的,任何人对已有输入,都可以用 f 加密,而要想根据加密信息还原出原信息,必须要有私钥才行。
#### 对称加密
使用 SSL/TLS 进行通信的双方需要使用非对称加密方案来通信但是非对称加密设计了较为复杂的数学算法在实际通信过程中计算的代价较高效率太低因此SSL/TLS 实际对消息的加密使用的是对称加密。
> 对称加密:通信双方共享唯一密钥 k加解密算法已知加密方利用密钥 k 加密,解密方利用密钥 k 解密,保密性依赖于密钥 k 的保密性。
![](./images/http&https/symmetric-encryption.png)
对称加密的密钥生成代价比公私钥对的生成代价低得多,那么有的人会问了,为什么 SSL/TLS 还需要使用非对称加密呢?因为对称加密的保密性完全依赖于密钥的保密性。在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性。
#### 公钥传输的信赖性
SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐患,设想一个下面的场景:
> 客户端 C 和服务器 S 想要使用 SSL/TLS 通信,由上述 SSL/TLS 通信原理C 需要先知道 S 的公钥,而 S 公钥的唯一获取途径,就是把 S 公钥在网络信道中传输。要注意网络信道通信中有几个前提:
>
> 1. 任何人都可以捕获通信包
> 2. 通信包的保密性由发送者设计
> 3. 保密算法设计方案默认为公开,而(解密)密钥默认是安全的
>
> 因此,假设 S 公钥不做加密,在信道中传输,那么很有可能存在一个攻击者 A发送给 C 一个诈包,假装是 S 公钥,其实是诱饵服务器 AS 的公钥。当 C 收获了 AS 的公钥(却以为是 S 的公钥C 后续就会使用 AS 公钥对数据进行加密,并在公开信道传输,那么 A 将捕获这些加密包,用 AS 的私钥解密,就截获了 C 本要给 S 发送的内容,而 C 和 S 二人全然不知。
>
> 同样的S 公钥即使做加密也难以避免这种信任性问题C 被 AS 拐跑了!
![](./images/http&https/attack1.png)
为了公钥传输的信赖性问题第三方机构应运而生——证书颁发机构CACertificate Authority。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的**电子签名**(见下节)。
当客户端(浏览器)向服务器发送 HTTPS 请求时,一定要先获取目标服务器的证书,并根据证书上的信息,检验证书的合法性。一旦客户端检测到证书非法,就会发生错误。客户端获取了服务器的证书后,由于证书的信任性是由第三方信赖机构认证的,而证书上又包含着服务器的公钥信息,客户端就可以放心的信任证书上的公钥就是目标服务器的公钥。
#### 数字签名
好,到这一小节,已经是 SSL/TLS 的尾声了。上一小节提到了数字签名,数字签名要解决的问题,是防止证书被伪造。第三方信赖机构 CA 之所以能被信赖,就是靠数字签名技术。
数字签名,是 CA 在给服务器颁发证书时,使用散列+加密的组合技术,在证书上盖个章,以此来提供验伪的功能。具体行为如下:
> CA 知道服务器的公钥对该公钥采用散列技术生成一个摘要。CA 使用 CA 私钥对该摘要进行加密,并附在证书下方,发送给服务器。
>
> 现在服务器将该证书发送给客户端,客户端需要验证该证书的身份。客户端找到第三方机构 CA获知 CA 的公钥,并用 CA 公钥对证书的签名进行解密,获得了 CA 生成的摘要。
>
> 客户端对证书数据(也就是服务器的公钥)做相同的散列处理,得到摘要,并将该摘要与之前从签名中解码出的摘要做对比,如果相同,则身份验证成功;否则验证失败。
![](./images/http&https/digital-signature.png)
注意,验证身份的证书一定是由 CA 的公钥进行签名,而不能由发送者自己来签名。这是为了抵抗以下的攻击场景:
> 攻击者使用某种手段,欺骗了客户端,将服务器的公钥替换为攻击者的诱饵公钥。
>
> 假使证书的签名使用的是服务器的私钥,那么客户端在解码的时候,将会使用假的服务器公钥(实则为诱饵公钥)。那么,如果该证书实则由攻击者(使用自己的私钥签名)发出,那么客户端就会成功验证(攻击者的)身份为真,从而信赖了证书中的公钥。
>
> 如果使用 CA 的私钥和公钥来对签名处理,则不会出现上述问题。
总结来说,带有证书的公钥传输机制如下:
1. 设有服务器 S客户端 C和第三方信赖机构 CA。
2. S 信任 CACA 是知道 S 公钥的S 向 CA 颁发证书。并附上 CA 私钥对消息摘要的加密签名。
3. S 获得 CA 颁发的证书,将该证书传递给 C。
4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书山的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
5. 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)。
![](./images/http&https/public-key-transmission.png)
## 总结
- **端口号** HTTP 默认是 80HTTPS 默认是 443。
- **URL 前缀** HTTP 的 URL 前缀是 `http://`HTTPS 的 URL 前缀是 `https://`
- **安全性和资源消耗** HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。

View File

@ -0,0 +1,107 @@
---
title: HTTP 1.0 vs HTTP 1.1(应用层)
category: 计算机基础
tag:
- 计算机网络
---
> 本文由 [SnailClimb](https://github.com/Snailclimb) 和 [csguide-dabai](https://github.com/csguide-dabai) 公众号“CS指南”作者共同完成。
这篇文章会从下面几个维度来对比 HTTP 1.0 和 HTTP 1.1
- 响应状态码
- 缓存处理
- 连接方式
- Host头处理
- 带宽优化
## 响应状态码
HTTP/1.0仅定义了16种状态码。HTTP/1.1中新加入了大量的状态码光是错误响应状态码就新增了24种。比如说`100 (Continue)`——在请求大资源前的预热请求,`206 (Partial Content)`——范围请求的标识码,`409 (Conflict)`——请求与当前资源的规定冲突,`410 (Gone)`——资源已被永久转移,而且没有任何已知的转发地址。
## 缓存处理
缓存技术通过避免用户与源服务器的频繁交互,节约了大量的网络带宽,降低了用户接收信息的延迟。
### HTTP/1.0
HTTP/1.0提供的缓存机制非常简单。服务器端使用`Expires`标签来标志(时间)一个响应体,在`Expires`标志时间内的请求,都会获得该响应体缓存。服务器端在初次返回给客户端的响应体中,有一个`Last-Modified`标签,该标签标记了被请求资源在服务器端的最后一次修改。在请求头中,使用`If-Modified-Since`标签,该标签标志一个时间,意为客户端向服务器进行问询:“该时间之前,我要请求的资源是否有被修改过?”通常情况下,请求头中的`If-Modified-Since`的值即为上一次获得该资源时,响应体中的`Last-Modified`的值。
如果服务器接收到了请求头,并判断`If-Modified-Since`时间后,资源确实没有修改过,则返回给客户端一个`304 not modified`响应头,表示”缓冲可用,你从浏览器里拿吧!”。
如果服务器判断`If-Modified-Since`时间后,资源被修改过,则返回给客户端一个`200 OK`的响应体,并附带全新的资源内容,表示”你要的我已经改过的,给你一份新的”。
![HTTP1.0cache1](./images/http&https/HTTP1.0cache1.png)
![HTTP1.0cache2](./images/http&https/HTTP1.0cache2.png)
### HTTP/1.1
HTTP/1.1的缓存机制在HTTP/1.0的基础上大大增加了灵活性和扩展性。基本工作原理和HTTP/1.0保持不变,而是增加了更多细致的特性。其中,请求头中最常见的特性就是`Cache-Control`详见MDN Web文档 [Cache-Control](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control).
## 连接方式
**HTTP/1.0 默认使用短连接** ,也就是说,客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源浏览器就会重新建立一个TCP连接这样就会导致有大量的“握手报文”和“挥手报文”占用了带宽。
**为了解决 HTTP/1.0 存在的资源浪费的问题, HTTP/1.1 优化为默认长连接模式 。** 采用长连接模式的请求报文会通知服务端“我向你请求连接并且连接成功建立后请不要关闭”。因此该TCP连接将持续打开为后续的客户端-服务端的数据交互服务。也就是说在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。
如果 TCP 连接一直保持的话也是对资源的浪费,因此,一些服务器软件(如 Apache还会支持超时时间的时间。在超时时间之内没有新的请求达到TCP 连接才会被关闭。
有必要说明的是HTTP/1.0仍提供了长连接选项,即在请求头中加入`Connection: Keep-alive`。同样的在HTTP/1.1中,如果不希望使用长连接选项,也可以在请求头中加入`Connection: close`,这样会通知服务器端:“我不需要长连接,连接成功后即可关闭”。
**HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。**
**实现长连接需要客户端和服务端都支持长连接。**
## Host头处理
域名系统DNS允许多个主机名绑定到同一个IP地址上但是HTTP/1.0并没有考虑这个问题假设我们有一个资源URL是http://example1.org/home.htmlHTTP/1.0的请求报文中,将会请求的是`GET /home.html HTTP/1.0`.也就是不会加入主机名。这样的报文送到服务器端,服务器是理解不了客户端想请求的真正网址。
因此HTTP/1.1在请求头中加入了`Host`字段。加入`Host`字段的报文头部将会是:
```
GET /home.html HTTP/1.1
Host: example1.org
```
这样,服务器端就可以确定客户端想要请求的真正的网址了。
## 带宽优化
### 范围请求
HTTP/1.1引入了范围请求range request机制以避免带宽的浪费。当客户端想请求一个文件的一部分或者需要继续下载一个已经下载了部分但被终止的文件HTTP/1.1可以在请求中加入`Range`头部,以请求(并只能请求字节型数据)数据的一部分。服务器端可以忽略`Range`头部,也可以返回若干`Range`响应。
如果一个响应包含部分数据的话,那么将带有`206 (Partial Content)`状态码。该状态码的意义在于避免了HTTP/1.0代理缓存错误地把该响应认为是一个完整的数据响应,从而把他当作为一个请求的响应缓存。
在范围响应中,`Content-Range`头部标志指示出了该数据块的偏移量和数据块的长度。
### 状态码100
HTTP/1.1中新加入了状态码`100`。该状态码的使用场景为,存在某些较大的文件请求,服务器可能不愿意响应这种请求,此时状态码`100`可以作为指示请求是否会被正常响应,过程如下图:
![HTTP1.1continue1](./images/http&https/HTTP1.1continue1.png)
![HTTP1.1continue2](./images/http&https/HTTP1.1continue2.png)
然而在HTTP/1.0中,并没有`100 (Continue)`状态码,要想触发这一机制,可以发送一个`Expect`头部,其中包含一个`100-continue`的值。
### 压缩
许多格式的数据在传输时都会做预压缩处理。数据的压缩可以大幅优化带宽的利用。然而HTTP/1.0对数据压缩的选项提供的不多不支持压缩细节的选择也无法区分端到端end-to-end压缩或者是逐跳hop-by-hop压缩。
HTTP/1.1则对内容编码content-codings和传输编码transfer-codings做了区分。内容编码总是端到端的传输编码总是逐跳的。
HTTP/1.0包含了`Content-Encoding`头部对消息进行端到端编码。HTTP/1.1加入了`Transfer-Encoding`头部可以对消息进行逐跳传输编码。HTTP/1.1还加入了`Accept-Encoding`头部,是客户端用来指示他能处理什么样的内容编码。
## 总结
1. **连接方式** : HTTP 1.0 为短连接HTTP 1.1 支持长连接。
1. **状态响应码** : HTTP/1.1中新加入了大量的状态码光是错误响应状态码就新增了24种。比如说`100 (Continue)`——在请求大资源前的预热请求,`206 (Partial Content)`——范围请求的标识码,`409 (Conflict)`——请求与当前资源的规定冲突,`410 (Gone)`——资源已被永久转移,而且没有任何已知的转发地址。
1. **缓存处理** : 在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准HTTP1.1 则引入了更多的缓存控制策略例如 Entity tagIf-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
1. **带宽优化及网络连接的使用** :HTTP1.0 中存在一些浪费带宽的现象例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了并且不支持断点续传功能HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content这样就方便了开发者自由的选择以便于充分利用带宽和连接。
1. **Host头处理** : HTTP/1.1在请求头中加入了`Host`字段。
## 参考资料
[Key differences between HTTP/1.0 and HTTP/1.1](http://www.ra.ethz.ch/cdstore/www8/data/2136/pdf/pd1.pdf)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2021-12-27T12:18:49.363Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="BCO_bX0iVrMdmYNRiWAx" version="13.4.5" type="device"><diagram id="tmrIvn8UqugqhCCRZjQR" name="Page-1">7VzbcqM4EP0aVe0+eIs74hFjO0nVZCYzzu7M7ptsZJsdDF6sjO18/UogbC4icRIMsUNSlUDrAvQ53Wo1QkB1lturCK0Wt6GLfaBI7haoA6AosqWq9B+T7BKJZZmJYB55Lq90EIy9R8yFEpc+eC5e5yqSMPSJt8oLp2EQ4CnJyVAUhZt8tVno56+6QnNcEoynyC9Lv3suWSRSqJgH+TX25ov0yrJhJSVLlFbmT7JeIDfcZETqEKhOFIYkOVpuHewz5aV6SdqNKkr3NxbhgBzTwHDsx4FiP35XNv/0vvSvvvbgrsd7+YX8B/7AYAiBLQMbgqEJbA30bTDUQV8GUOHPQXapcqLwIXAx618Gan+z8Ager9CUlW4oHahsQZY+L56FAeH40jul557vO6EfRnFfqqtj6GpUviZR+BNnSqAyUQ2Dlsx9tGZwstZ7bbKup+HSm/LjslrSZ8QRwduMiKvpCodLTKIdrZKWanrShHPWUDmEmwMD5BTWRQZ9g8sQJ9183/UBF3rAoXkBTIoAJp1BY2kMJvqX4dUITAjD2VQEkzGFeDJrESbdbBsmVQATtSAHWHZsViNgDZqBaTbDxlQIk2taE0lq05qstmFKnXdG99ilXp+fhhFZhPMwQP7wIO0f0GEKO9T5FIYrrqx/MSE7Dgp6IGEesUpVrsOHaIqfuF8tqcfu8UmFR9hHxPuVH7lE2uNN70KP3soeKE2TckCZsAAAQdEcE96qgMH+Nl4Pi1ZlPbbErKc/BJbakPXAKRZbzwTqmt6m9Zh669YDz8t69HasB2rNWo8usB4T9AfAkuODPrCcZqwHyzSWM0XWYxmmitqM5KDctvUYApgMYFFcJHYAB8AegqHFXB11eMztmSxuaAQ4eYJkrIiAkyRjSO8i6SEXZrCfNgFtPeYzhXYHLWBbcWguAWg0A58k6RKeieGTB3QcfX/wWe3PrPTzGs0UpZ3hzCgicOrhrJUoA2898oM3Z8d/s+M/dH422GaKBjt+cgZYtgtl+phZF1ntB6Xn/WBISzyyS93gPEKuhw+OLQgDRgYXrRd7z5q4xDSDp9bkzZS8YoUJCFPgzeTizKo+d2admTtT23Fn+4GnIRsw5DZwoXBEux/Zk4xDY6cHjxaf1eDSOJ6JOp9SiFQ38G+zG0Hq7kJ81BEBs9BHKafyUanpHafrI+LiXMRaDJKzoW02mi2mfHT2K8xrxz/l4Dn5qQclTS+k3gRZHkVvMi5WXzRof0iQoNI6SC/yWh8SJEtqHSRBXrsDKQeS6AWrqjYKkiB9qhg+YRpaoSCHlvHfA3tnT9UbK8dmQcp88ptqAIVeXNJk/t/4PdaWxBTZW8cYsbqysdomBVRbpId8bx4kJT6ekbgkvQI9mrP/1/f3d+nt0MdL7igpKlGJdVrgSw5iHnnwyw6mFEVM5X2GnjdFvs0Llp7rxlGoiI35UKgY3GQzSz6aYL+Ppj/ncZvCXdTBJbPAJa3MJU1ApdOFN4KM4CuoJB3YJB0IpUjVnErLhLQqcWrwedxRSkwpXX1vlIKVlHK9X0JGHUeCZ4kp5FlVL6wyYEuxUswOFVVFUywFl9uOb6lrG6oASgDKd1/u1P3Jza2ddXpJ5/kLloi7F8dqyUvPXVNp20kkeN43aOeDG3spFhFMkBWpSWvXBIvyauXwW9j3Nv6PnohjnuNyR9rMCAXf2QiliWail8HZe+wHmHS0rYG2RtHXtk5b0dz8Mmg7Hl93nD0FZ422OVudqjj3EPfeqSni/+Cc1eU8Z01BTNssZwXL3i6Es38OOs7W4mel98bZ6jzeuXP2pqPsKVLPUPAao1nKXm6e0P7WcbaW0EB5b5y1LnYKduPcdumuU6S7WidtOie8QNJ+tu87ztYRzxZeIkLBkq5mOXu5rxW+3RzeIX4Z3432J/2rzgHXEukWP7sSrU+UG2WzcrFsHjjXHWvrYK1ZiHVbf92gnzp12x5p8/OzjrO1hQ2th7qXm7q9tZ0up1BHdFCYnlmChfHNcrY6dUsvgBhPFiha8w+UUlo8kFkPvoKnb14HnBQk/bKSIIyWyM+UbbjSWKEm8WWePiaUNr01+9AomJdbVq4uTko8yp6A9ynlViSTCAXrGe0p7ZPzRNqEkZu/3r6h661XPtolUi/wvbTNzA8RKXRU1LAzvqXlI2dQaXZiA3tmnXzeQo63tneVn7NkvWRLsmg5WvGDxvqMSZCg6zYf6xVXYLW+k4EhyEkJdoAxABwCW2eAwRGwG9pR6Yi9KY5CrmoDixMgKvpyqGFEy9OF8mfERwYbWTxOEH887Rcz5JBhTWjJxV0N2s6vGeWXb2Wb6tBKBK2/3TfKo5raoVWBVuuTULM8tmkdWhVoNTn9soMt+XQ1vv1meIu/kPR1NxpPhZsK02hDB3S+zfdDNXn80acHo2SHVGccBycOgEnhgNWq/OaFSV6fMzhz5gg+z+3Hv3GfBBEvZNdmOy3k46oa6KYW1mnppmCCAgV0k19ON3p62B872YrlsMu4Ovwf</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-02-25T07:27:08.543Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="4kxx-sCj15jdkqoPe9xM" version="13.4.5" type="device"><diagram id="IKFI_ZB9R2pDRW9sJrDE" name="Page-1">vZZdb5swFIZ/jS8rAQZiLhtKO22rNimb1lvHPoA1gyPjjKS/fqaYACGVNqnJFfg9xx/nfY4TEE6rw5Omu/JZcZAo8PgB4QcUBL7vxfbRKcdeSZJVLxRacJc0ChvxCk70nLoXHJpZolFKGrGbi0zVNTAz06jWqp2n5UrOd93RAhbChlG5VH8JbspeJcFq1D+BKMphZz9O+khFh2RXSVNSrtqJhDOEU62U6d+qQwqyM2/wpZ/3+E70dDANtfmXCZw9b799ecEvn8O82Xivd1+VunOr/KFy7wp2hzXHwQGt9jWHbhEf4XVbCgObHWVdtLXMrVaaSrpwrmrjINrj2LGQMlVS6be1MKdAcmb1xmj1GyaRmBHY5jZSSNp0zLrZJ8u6AVOVYG6bZe1DIaANHCaS8+IJVAVGH22KiwZe2E9xjRnFjlM7Yg5XrnvLKeLEJVLXWsVp7dF9++IA/AeMYAkjC9E6RfceyghaZyjBKIvQ2kdkycnWbeYw5ibXqoYzIk6iUhS1HTLrJlh93bko7B24d4FKcN5tc5H+2B/eWQPgc4QfgA1jPMe2WmILfLLEFl6LGl5Q+5F+v+otygkDdvEWbUkURt4tbxHxZjjiaInDH34Bpzjia+GIFjh+PlwXB4+A8PASDhJscRzfEEeY3A6HHY5/Xm+xyScAzv4C</diagram></mxfile>

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-02-25T06:26:44.060Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="fzicsnCHu9ESaRWQG5v1" version="13.4.5" type="device"><diagram id="0XygYSvObaGfJKnrfW3A" name="Page-1">7VzZbuM2FP0aAu1DCu0iHyVbmQJFgQIpujwVtEXL6mjxyPLEnq8vL0nJWujEznhJZzwDJBR33UOeu5AKsif59kNFV8tfy5hlyDLiLbKnyLJM0/D4L8jZyRxCfJmRVGmsKu0zntIvTGUaKneTxmzdq1iXZVanq37mvCwKNq97ebSqyud+tUWZ9Udd0YSNMp7mNBvn/pnG9VLmYsvf5//M0mTZjGx6RJbktKms3mS9pHH53MmyI2RPqrKsZSrfTlgGwmvkIts9HihtJ1axoj6mQfB79Aum4VOaT93oj392y60xfbBVN59ptlFvjCKMAhMFGEU+ChwUBihyUWgibKkXqXeNdKpyU8QMBjCRHT4v05o9regcSp/5euB5yzrPVPGiLGoFMJ8qf06zbFJmZSX6smOX4djh+eu6Kj+yTgm2Zrbn8ZIko2vAE1q34oSu52WezlV6LJfmHVlVs20nS8npAytzVlc7XkWVtqtPLVrfUc/P+yVgNrguO/B7Ko+qVZe0Xe+B4QmFzSk4WRqcXMCGOIAT/wmAXQUnyvBirsPJm2M2W9wQJw/fHCdbgxPfQxNEArGxHhGZXgenxYJ5cy1OsU9mhnFDnLBxc5ycQzgFBuAURojYV8IJz5kepxl2HfemOHk3x8nV4OSjcIqIKRIhIpPr4MRMrqF8HU7E8216S/1ErJvj5Glw8hDhwBiQwFMURCgisKv43oId5gMZXgU5c0ZNZumQMwwv4rOQPfS4E/7dEtHbazJfu/MwQQERFoeBsHcd/AzDNdhCj5855Zz9/vAzjdubjHgEoDmCib9e3ceiL+OiLNgAEJVFszQp+OOcC43x/BCElXLHKVAFeRrHMIwW/P3yMDT4nwEQ0x4CYo8BcTR4WBfDg4zwGG+b7wYPotkfV4WjGazLb0M0WBEHEEMAsQKRAGO8xFtsm9Z/qTJI/w3y/MlVT9OtEq942KmHg7Jdl5tqzl5aUGrCLO6FMMYQdETsakTc5FUso3X6uc8VOrmrEX4rUz7lFmHb6yPsmwPo5AupVt1AxaAj57WOalolrB51JJZB+9pfsTI0MRHLy2Bfrle06C0R79MG4jdcnYjNGIAYk9kPHncv+KT5+IZvtUli/ojUfjJg6TysxdqBRqa32vbLnhVCUOqBv6QKZ3T+MRHb9WEwqOW67VCD9I/7mfJUIn6Du4NFdAeDbRYIe5oniC8st4koaiML3IQTNhskHkH5Q3NeOVSVsfBqcQD9KGFx4Ut5qQHfJ9f1rIKuudC1EC5AiI4zWOUan5hbB9dkRE2M6V0x4nshuoEq8/1zEd2wo0sTnSZY9Qaia1iuobiD/HaY3I5htpbWWk4TZDaitbHX6UIYGzsdr+URIj1YRLghNOcJDuTsZwsO5HU4GdoIy4SkNUP08yiat5XbnG7lCOFQ9QyuUqfysEhOg3zbhGl6ZyLM4W7RBKfs65qQmiDinTBfJ0xsn4kwRx1dmjA10cgbEqbYqw9ruVmhpCirnGZnZVN/bxsOudOF6Ks0EoNQEFvLgiIwGzqCgwNg330RQdgX1iI3J7khGe1ZUHOe5cNP6FkUccMTrE4icggYqqGsHAh2Hx2z3Gn1DbSKNbFkW0cOl6NVTSz5TqtH0Co5F60OO7o0rWpCza/R6qzcAlumRSKJbVZWMaseePZxbvRZHfYL+OQiAcTpAu2FRlMUdpxzyaBhhyZfYEcCBExkz4+C0ceefFunQ8Cq+diqHp+Wfl+BgLMRsD/YfZqjH9u/KgGPTw7uBHwEARP3TAQ86ujSBDw+mrgDfgTgpnGuGPe4pwtD3kjkDvmpkJ8r2jfu6dKQv+Fc4wUz6xXn9JA/O7J51BSgvnYKR3cEZgdubidI82VsozhgQoGFhME8UnWkyXXKdRX9MYgj6vCiiXB1pWMrrifBuUok7k9EYggfmvBxweSyhFX3wiEMBnMKy+sXFlh4GjvPEz6vo65oQB0Pha5yxrsmIBYzJBhmspcPUe753mKTePQx+oYNuYzOWBa2dvxwxv3rJc4U/p/L/3YHtHDzuKarOwh6l/7YguZptpPNZJXmp0fzlaho2+JOOUtKxgs26ajocKMlyz4zWIUntKFVSrNT6q9WGWvfn6u9vPz3lDl2X+zrGq93+aw8ZepZOmMV162lWBG0WJ/QdsUXyoLyxcJbzk9oxzdwVa7LBaiKHeW74RQ404omaVG2szWS2QnNn1nxaUOLHchKTENuxzf28IUVJ7df17JJfVKjND9xlDRfb4qvfy344KVaHe4HMHhYsypd9Pf0xWMsrTIXZkIoDu2I1SjqR6GNXYgfc5XYjXZjrlHtRplr7QUXNLYMmwxvKHcCKWBuYDEN2bxrXESizndxLnipixS6m2XXjZ+4bzhXv+vPu/6868+7/vwf6M/xkbDOmx26rLKOPBLmzd0XzxZGhxV3TXiEJrSbc7vWldTcKbyyKjziikxfeK98KlLykrTeNVJLKhqnbO+cKzRjul62H5/IJdB8vW2fR9Ym7rvt2k9PdaI28cVkrbud8k3IerCutR9HaWV9uXU9vqNgv1M2usLHHLojy+tGrMY3CJzvFw7dzcgzwcEf93+xQh5M7P/uhx39Bw==</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-01-11T02:36:21.755Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="0H9U1Wz2i3VyUxEKUyq8" version="13.4.5" type="device"><diagram id="ox_IyTXRnZNLjcFnBTdz" name="Page-1">5Zhbb5swFMc/jR8rYQzGPAaaLFPVaRKT9uyAuawGZ8Rpkn362eCEa6VVapJJVaTE/p/jS87v2MYAFJbHLzXd5s8iYRzYVnIE6BHYNoQWVj9aObWK73utkNVFYpw6ISr+MCNaRt0XCdsNHKUQXBbboRiLqmKxHGi0rsVh6JYKPhx1SzM2EaKY8qn6s0hk3qrE9jp9zYosP48Msd9aSnp2Nv9kl9NEHHoSWgIU1kLItlQeQ8Z18M5xadut3rBeJlazSv5Lg234dHplx+Al/lU4NHjKTnb9gNpeXinfmz9sJitP5wjUYl8lTHcCAQoOeSFZtKWxth4Uc6XlsuTGnIpKGohqOqpecB4KLuqmL5RQRtJY6TtZixfWs+CYsE2qLBmnO81Mt76ETHcdi7KITdnMmtWSHd8MB7wEWWUnEyWT9Um5mAa25bRNTGI6xHA6dJgdz2Rv3kOMXONITWpll7676KuCAfAOGM4UxtIFwQL4Dlh6+ntBGgUCMuWkQiGHMIZBrkTFRkSMRHmRVaoaq9AxpQc6sIVaAwtjKIsk0cPM0u/ywxolAPoYUgihASnXmpKyIZmScq4Fyp2AWv/48f2qKyclMYtnV86GuI5r3XLlIGvIw5/ygOddr88DX4sHnvBYXRtHmtrzOBK8wS6+IQ4Ehziwd28c3gTH4zq8Lo/EZSRx5ngQe4PwLXk4cHiwuHfnQaY8vkVXxcGgAuLN4fCxh+gtcbguHC4P+944/AmO6PkTnR7ecLvynHvzOO+fPSBfnxef5vxw/BEQfHcgcLpCovVn2bAcPDrP7/54ZU9w6FsIccEiBEsHBCFQl3qtrECgCqtGWYQRWGJAQkBa46P2sjHXl5RNrUqZbALWKT24+Pde34sbbA+7httCOUC8PXbGro//8irE6YbxgMYvWaOPB+8SEmJT76Vd0HyaPiWVhdBjP6DxRv0R+/Ho8dGd24/JTLrB96ebqnbvOxpb760RWv4F</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-01-11T03:08:09.434Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="wZkdwQbGlyahQdMlLp3v" version="13.4.5" type="device"><diagram id="aLP9Q2JBGdJELPBJHqNY" name="Page-1">5Zhdb5swFIZ/jS8jYQzGXAZK2knrWjXTJu3OgCGoBqfEWdL9+hlwwmelVSrJpCoXsd/jL85zjo0ByM+PtyXdbu5FzDgwjfgI0A0wTQgNrP4q5bVRXNdphLTMYt2oFdbZH6ZFQ6v7LGa7XkMpBJfZti9GoihYJHsaLUtx6DdLBO/PuqUpGwnriPKx+jOL5aZRiem0+h3L0s1pZojdxpLTU2P9JLsNjcWhI6EAIL8UQjal/OgzXjnv5Jem3+oN63lhJSvkv3QI7n5Yd1+tPHnJ//x62C/iYHe70KP8pnyvH1gvVr6ePFCKfRGzahAIkHfYZJKttzSqrAfFXGkbmXNtTkQhNUS1HFXPOPcFF2U9FoopI0mk9J0sxTPrWHBEWJgoS8rprmJW9T67rBo6EnkW6bJeNSslO77pDnh2sopOJnImy1fVRHcwDavpogPTIprTocVsOTp6Nx3EyNYNqQ6t9Dx2631V0ADeAcMcwwgc4N0AF9YFD7g+CGzgQUDGnJQrZB9G38mFKNiAiJYoz9JCVSPlOqZ0r3JspnJgqQ15FsfVNJP02/gwBgGAPoYUQqhHyjbGpExIxqSsuUChEagvj7PmTUIiFk3mTUhsyzYumTfI6NNwxzTgac/r0sBz0bBGNL4tv8+LI0nMaRwxDrGNL4gDwT4O7Fwbhz3CsXyaNztim5HYmsJBzBDhS+KwYP9Usa+OA4/3Kv9+5t0qYfiN9HDc0LjkbmXbsJ8e5rV5OCMeTzMfHgyqBHGmcLjYQfSS6WE6/d3Ksa6Ng4xweLefBoflDnDga+NwRzge1o+rT8MDDw7zq79bnd4uencSGxAbLNVVxAKeD9SFvlJWwFOFVa0s/TUIMCA+II3xpmplYl5dUMJSlVJZe6xVOnTxy766E9fcFrsa3FI1gHh7bI3tGP/lNYjTkHGPRs9prQ8nbyMSYl3vxJ1X/+oxJZWZqOZeoOGx+RHb8eDl0Z7ajslEvMH3x5uqtt86alvnixEK/gI=</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-01-11T03:13:25.100Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="IKo_p9QaQrGGghVbgDv6" version="13.4.5" type="device"><diagram id="FvOr2f2zJKBByRSDsAu0" name="Page-1">5ZdNj5swEIZ/jY8rYQzGHIGQblXtoc2h6qlywCFoHZwSp0n213cMToDASl1pk61UIUXmHX9lnpmxQSTZHD/VfLt+UrmQyHXyIyIz5LoBxfBrhFMrYHhapajL3GqdsChfhBUdq+7LXOwGHbVSUpfboZipqhKZHmi8rtVh2G2l5HDVLS/ESFhkXI7V72Wu163K3KDTH0VZrM8rYxq2lg0/d7b/ZLfmuTr0JJIiktRK6ba1OSZCGued/dKOm79ivWysFpX+mwHh/uVH+ONLhANcPJ5mn79++zl7sLP85nJv/7DdrD6dPVCrfZULMwlGJD6sSy0WW54Z6wGYg7bWG2nNK1VpCxG2A++llImSqm7mIjkXbJWBvtO1ehY9C82YWK7AUki+M8zM6IvLzNSZ2pSZbdtdi1qL46vuwBcnQ3QKtRG6PkEXO8B1vHaIjUyPWU6HDrMX0FZb9xAT33bkNrSKy9yd96FhAbwBhjuGkQYonqEQN40YhQlKKWIpinyU+ojNUURGwMAnekhl6O1KVeIKjZW4LIsKXjPwoQA9Nh4uIRkia9iUeW6WmQyDLlCcq0gg74OMEDJA5jtjZC5mY2TerYiREbFk8RTBVMnspnm0YpnIJvNoyXzPd+6ZR8QZQgnHUPC5Bvah0FtB8UdQnqLktmXNFyz3pnAwd0kovSMODw/Lmh98NA46UdV8FAcoSlEaotBDYWiqGlQyKMHQiKGwxbdNn5Wg0+mTB+HSuWf6+GTIi5KP5sUmeHnm8GnPnMhDUdSdS7fEJDAkVjCFKaQB4fdMq8tRYzEF7kdjCifTCuiEQIc1+TU3DciyeN4kWpNx/wkvgq94TVwV7svrvKErYAyYJU2CJYZQe6kDeOm8UaJk0dz4EsRa48z0cqk0N7xlDa1CNx7rlB5d+mtvvi4abg+7BhxcThxMt8fO2M3xT94jJV8KGfPsuWj068W7iMTUvvfiLm6eZk7NdanM2g/kur6/xy3oKt58byLe2ES84bfHG7x2X42NrfftTdI/</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,116 @@
---
title: OSI 和 TCP/IP 网络分层模型详解(基础)
category: 计算机基础
tag:
- 计算机网络
---
> 本文由 [SnailClimb](https://github.com/Snailclimb) 和 [csguide-dabai](https://github.com/csguide-dabai) 公众号“CS指南”作者共同完成。
## OSI 七层模型
**OSI 七层模型** 是国际标准化组织提出一个网络分层模型,其大体结构以及每一层提供的功能如下图所示:
![osi七层模型](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/osi%E4%B8%83%E5%B1%82%E6%A8%A1%E5%9E%8B.png)
每一层都专注做一件事情,并且每一层都需要使用下一层提供的功能比如传输层需要使用网络层提供的路有和寻址功能,这样传输层才知道把数据传输到哪里去。
**OSI 的七层体系结构概念清楚,理论也很完整,但是它比较复杂而且不实用,而且有些功能在多个层中重复出现。**
上面这种图可能比较抽象,再来一个比较生动的图片。下面这个图片是我在国外的一个网站上看到的,非常赞!
![osi七层模型2](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/osi七层模型2.png)
**既然 OSI 七层模型这么厉害,为什么干不过 TCP/IP 四 层模型呢?**
的确OSI 七层模型当时一直被一些大公司甚至一些国家政府支持。这样的背景下,为什么会失败呢?我觉得主要有下面几方面原因:
1. OSI 的专家缺乏实际经验,他们在完成 OSI 标准时缺乏商业驱动力
2. OSI 的协议实现起来过分复杂,而且运行效率很低
3. OSI 制定标准的周期太长,因而使得按 OSI 标准生产的设备无法及时进入市场20 世纪 90 年代初期,虽然整套的 OSI 国际标准都已经制定出来,但基于 TCP/IP 的互联网已经抢先在全球相当大的范围成功运行了)
4. OSI 的层次划分不太合理,有些功能在多个层次中重复出现。
OSI 七层模型虽然失败了但是却提供了很多不错的理论基础。为了更好地去了解网络分层OSI 七层模型还是非常有必要学习的。
最后再分享一个关于 OSI 七层模型非常不错的总结图片!
![](./images/osi&tcp-ip-model/osi-model-detail.png)
## TCP/IP 四层模型
**TCP/IP 四层模型** 是目前被广泛采用的一种模型,我们可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本,由以下 4 层组成:
1. 应用层
2. 传输层
3. 网络层
4. 网络接口层
需要注意的是,我们并不能将 TCP/IP 四层模型 和 OSI 七层模型完全精确地匹配起来,不过可以简单将两者对应起来,如下图所示:
![TCP-IP-4-model](./images/osi&tcp-ip-model/TCP-IP-4-model.png)
### 应用层Application layer
**应用层位于传输层之上,主要提供两个终端设备上的应用程序之间信息交换的服务,它定义了信息交换的格式,消息会交给下一层传输层来传输。** 我们把应用层交互的数据单元称为报文。
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/5971-2-7I1-20220111095024771-20220111201807861.png)
应用层协议定义了网络通信规则,对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如支持 Web 应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等。
![application-layer](./images/osi&tcp-ip-model/application-layer.png)
### 传输层Transport layer
**传输层的主要任务就是负责向两台终端设备进程之间的通信提供通用的数据传输服务。** 应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。
**运输层主要使用以下两种协议:**
1. **传输控制协议 TCP**Transmisson Control Protocol--提供**面向连接**的,**可靠的**数据传输服务。
2. **用户数据协议 UDP**User Datagram Protocol--提供**无连接**的,尽最大努力的数据传输服务(**不保证数据传输的可靠性**)。
![transport-layer](./images/osi&tcp-ip-model/transport-layer.png)
### 网络层Network layer
**网络层负责为分组交换网上的不同主机提供通信服务。** 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报,简称数据报。
注意 ⚠️:**不要把运输层的“用户数据报 UDP”和网络层的“IP 数据报”弄混**。
**网络层的还有一个任务就是选择合适的路由,使源主机运输层所传下来的分株,能通过网络层中的路由器找到目的主机。**
这里强调指出,网络层中的“网络”二字已经不是我们通常谈到的具体网络,而是指计算机网络体系结构模型中第三层的名称。
互联网是由大量的异构heterogeneous网络通过路由器router相互连接起来的。互联网使用的网络层协议是无连接的网际协议Intert Prococol和许多路由选择协议因此互联网的网络层也叫做**网际层**或**IP 层**。
![](./images/osi&tcp-ip-model/nerwork-layer.png)
### 网络接口层Network interface layer
我们可以把网络接口层看作是数据链路层和物理层的合体。
1. 数据链路层(data link layer)通常简称为链路层( 两台主机之间的数据传输,总是在一段一段的链路上传送的)。**数据链路层的作用是将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。**
2. **物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异**
![network-interface-layer](./images/osi&tcp-ip-model/network-interface-layer.png)
## 为什么网络要分层?
在这篇文章的最后,我想聊聊:“为什么网络要分层?”。
说到分层,我们先从我们平时使用框架开发一个后台程序来说,我们往往会按照每一层做不同的事情的原则将系统分为三层(复杂的系统分层会更多):
1. Repository数据库操作
2. Service业务操作
3. Controller前后端数据交互
**复杂的系统需要分层,因为每一层都需要专注于一类事情。网络分层的原因也是一样,每一层只专注于做一类事情。**
好了,再来说回:“为什么网络要分层?”。我觉得主要有 3 方面的原因:
1. **各层之间相互独立**:各层之间相互独立,各层之间不需要关心其他层是如何实现的,只需要知道自己如何调用下层提供好的功能就可以了(可以简单理解为接口调用)**。这个和我们对开发时系统进行分层是一个道理。**
2. **提高了整体灵活性** :每一层都可以使用最适合的技术来实现,你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。**这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。**
3. **大问题化小** 分层可以将复杂的网络间题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计,实现和标准化。 **这个和我们平时开发的时候,一般会将系统功能分解,然后将复杂的问题分解为容易理解的更小的问题是相对应的,这些较小的问题具有更好的边界(目标和接口)定义。**
我想到了计算机世界非常非常有名的一句话,这里分享一下:
> 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,计算机整个体系从上到下都是按照严格的层次结构设计的。

View File

@ -1,77 +1,94 @@
--- ---
title: 计算机网络常见面试题 title: 计算机网络常见知识点&面试题(补充)
category: 计算机基础 category: 计算机基础
tag: tag:
- 计算机网络 - 计算机网络
--- ---
## 一 OSI 与 TCP/IP 各层的结构与功能, 都有哪些协议? ## 应用层有哪些常见的协议?
学习计算机网络时我们一般采用折中的办法,也就是中和 OSI 和 TCP/IP 的优点,采用一种只有五层协议的体系结构,这样既简洁又能将概念阐述清楚。 ### HTTP:超文本传输协议
![五层体系结构](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/五层体系结构.png) **超文本传输协议HTTPHyperText Transfer Protocol)** 主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的,整个过程如下图所示。
结合互联网的情况,自上而下地,非常简要的介绍一下各层的作用。 ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/450px-HTTP-Header.png)
### 1.1 应用层 HTTP 协是基于 TCP协议发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。目前使用的 HTTP 协议大部分都是 1.1。在 1.1 的协议里面,默认是开启了 Keep-Alive 的,这样的话建立的连接就可以在多次请求中被复用了。
**应用层(application-layer的任务是通过应用进程间的交互来完成特定网络应用。**应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如**域名系统 DNS**,支持万维网应用的 **HTTP 协议**,支持电子邮件的 **SMTP 协议**等等。我们把应用层交互的数据单元称为报文。
**域名系统** 另外, HTTP 协议是”无状态”的协议,它无法记录客户端用户的状态,一般我们都是通过 Session 来记录客户端用户的状态。
> 域名系统(Domain Name System 缩写 DNSDomain Name 被译为域名)是因特网的一项核心服务,它作为可以将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的 IP 数串。(百度百科)例如:一个公司的 Web 网站可看作是它在网上的门户而域名就相当于其门牌地址通常域名都使用该公司的名称或简称。例如上面提到的微软公司的域名类似的还有IBM 公司的域名是 www.ibm.com、Oracle 公司的域名是 www.oracle.com、Cisco 公司的域名是 www.cisco.com 等。 ### SMTP:简单邮件传输(发送)协议
**HTTP 协议** **简单邮件传输(发送)协议SMTPSimple Mail Transfer Protocol** 基于 TCP 协议,用来发送电子邮件。
> 超文本传输协议HTTPHyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的 WWW万维网 文件都必须遵守这个标准。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。(百度百科) 注意⚠️:**接受邮件的协议不是 SMTP 而是 POP3 协议。**
### 1.2 运输层 SMTP 协议这块涉及的内容比较多,下面这两个问题比较重要:
**运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务**。应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。由于一台主机可同时运行多个线程,因此运输层有复用和分用的功能。所谓复用就是指多个应用层进程可同时使用下面运输层的服务,分用和复用相反,是运输层把收到的信息分别交付上面应用层中的相应进程。 1. 电子邮件的发送过程
2. 如何判断邮箱是真正存在的?
**运输层主要使用以下两种协议:** **电子邮件的发送过程?**
1. **传输控制协议 TCP**Transmission Control Protocol--提供**面向连接**的,**可靠的**数据传输服务。 比如我的邮箱是“dabai@cszhinan.com”我要向“xiaoma@qq.com”发送邮件整个过程可以简单分为下面几步
2. **用户数据协议 UDP**User Datagram Protocol--提供**无连接**的,尽最大努力的数据传输服务(**不保证数据传输的可靠性**)。
**TCP 与 UDP 的对比见问题三。** 1. 通过 **SMTP** 协议我将我写好的邮件交给163邮箱服务器邮局
2. 163邮箱服务器发现我发送的邮箱是qq邮箱然后它使用 SMTP协议将我的邮件转发到 qq邮箱服务器。
3. qq邮箱服务器接收邮件之后就通知邮箱为“xiaoma@qq.com”的用户来收邮件然后用户就通过 **POP3/IMAP** 协议将邮件取出。
### 1.3 网络层 **如何判断邮箱是真正存在的?**
**在计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。** 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 **IP 协议**,因此分组也叫 **IP 数据报** ,简称 **数据报** 很多场景(比如邮件营销)下面我们需要判断我们要发送的邮箱地址是否真的存在,这个时候我们可以利用 SMTP 协议来检测:
这里要注意:**不要把运输层的“用户数据报 UDP ”和网络层的“ IP 数据报”弄混**。另外,无论是哪一层的数据单元,都可笼统地用“分组”来表示。 1. 查找邮箱域名对应的 SMTP 服务器地址
2. 尝试与服务器建立连接
3. 连接成功后尝试向需要验证的邮箱发送邮件
4. 根据返回结果判定邮箱地址的真实性
这里强调指出,网络层中的“网络”二字已经不是我们通常谈到的具体网络,而是指计算机网络体系结构模型中第三层的名称. 推荐几个在线邮箱是否有效检测工具:
互联网是由大量的异构heterogeneous网络通过路由器router相互连接起来的。互联网使用的网络层协议是无连接的网际协议Internet Protocol和许多路由选择协议因此互联网的网络层也叫做**网际层**或**IP 层**。 1. https://verify-email.org/
2. http://tool.chacuo.net/mailverify
3. https://www.emailcamel.com/
### 1.4 数据链路层 ### POP3/IMAP:邮件接收的协议
**数据链路层(data link layer)通常简称为链路层。两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。** 在两个相邻节点之间传送数据时,**数据链路层将网络层交下来的 IP 数据报组装成帧**,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。 这两个协议没必要多做阐述,只需要了解 **POP3 和 IMAP 两者都是负责邮件接收的协议**即可。另外,需要注意不要将这两者和 SMTP 协议搞混淆了。**SMTP 协议只负责邮件的发送真正负责接收的协议是POP3/IMAP。**
在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。这样,数据链路层在收到一个帧后,就可从中提出数据部分,上交给网络层。 IMAP 协议相比于POP3更新一点为用户提供的可选功能也更多一点,几乎所有现代电子邮件客户端和服务器都支持IMAP。大部分网络邮件服务提供商都支持POP3和IMAP。
控制信息还使接收端能够检测到所收到的帧中有无差错。如果发现差错,数据链路层就简单地丢弃这个出了差错的帧,以避免继续在网络中传送下去白白浪费网络资源。如果需要改正数据在链路层传输时出现差错(这就是说,数据链路层不仅要检错,而且还要纠错),那么就要采用可靠性传输协议来纠正出现的差错。这种方法会使链路层的协议复杂些。
### 1.5 物理层 ### FTP:文件传输协议
在物理层上所传送的数据单位是比特 **FTP 协议** 主要提供文件传输服务,基于 TCP 实现可靠的传输。使用 FTP 传输文件的好处是可以屏蔽操作系统和文件存储方式
**物理层(physical layer)的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异,** 使其上面的数据链路层不必考虑网络的具体传输介质是什么。“透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。 FTP 是基于客户—服务器C/S模型而设计的在客户端与 FTP 服务器之间建立两个连接。如果我们要基于 FTP 协议开发一个文件传输的软件的话,首先需要搞清楚 FTP 的原理。关于 FTP 的原理,很多书籍上已经描述的非常详细了:
在互联网使用的各种协议中最重要和最著名的就是 TCP/IP 两个协议。现在人们经常提到的 TCP/IP 并不一定单指 TCP 和 IP 这两个具体的协议,而往往表示互联网所使用的整个 TCP/IP 协议族。 > FTP 的独特的优势同时也是与其它客户服务器程序最大的不同点就在于它在两台通信的主机之间使用了两条 TCP 连接(其它客户服务器应用程序一般只有一条 TCP 连接):
>
> 1. 控制连接:用于传送控制信息(命令和响应)
> 2. 数据连接:用于数据传送;
>
> 这种将命令和数据分开传送的思想大大提高了 FTP 的效率。
### 1.6 总结一下 ![FTP工作过程](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E6%80%BB%E7%BB%93/ftp.png)
上面我们对计算机网络的五层体系结构有了初步的了解,下面附送一张七层体系结构图总结一下(图片来源于网络)。
![七层体系结构图](https://gitee.com/SnailClimb/blog-images/raw/master/network//%E4%B8%83%E5%B1%82%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E5%9B%BE.png) ### Telnet:远程登陆协议
## 二 TCP 三次握手和四次挥手(面试常客) **Telnet 协议** 通过一个终端登陆到其他服务器,建立在可靠的传输协议 TCP 之上。Telnet 协议的最大缺点之一是所有数据包括用户名和密码均以明文形式发送这有潜在的安全风险。这就是为什么如今很少使用Telnet并被一种称为SSH的非常安全的协议所取代的主要原因。
### SSH:安全的网络传输协议
**SSH Secure Shell** 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH 建立在可靠的传输协议 TCP 之上。
**Telnet 和 SSH 之间的主要区别在于 SSH 协议会对传输的数据进行加密保证数据安全性。**
## TCP 三次握手和四次挥手(面试常客)
为了准确无误地把数据送达目标处TCP 协议采用了三次握手策略。 为了准确无误地把数据送达目标处TCP 协议采用了三次握手策略。
### 2.1 TCP 三次握手漫画图解 ### TCP 三次握手漫画图解
如下图所示,下面的两个机器人通过 3 次握手确定了对方能正确接收和发送消息(图片来源:《图解 HTTP》)。 如下图所示,下面的两个机器人通过 3 次握手确定了对方能正确接收和发送消息(图片来源:《图解 HTTP》)。
@ -89,7 +106,7 @@ tag:
![](https://img-blog.csdnimg.cn/img_convert/0c9f470819684156cfdc27c682db4def.png) ![](https://img-blog.csdnimg.cn/img_convert/0c9f470819684156cfdc27c682db4def.png)
### 2.2 为什么要三次握手 ### 为什么要三次握手
**三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。** **三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。**
@ -99,15 +116,15 @@ tag:
第三次握手Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:自己发送、接收正常,对方发送、接收正常 第三次握手Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:自己发送、接收正常,对方发送、接收正常
所以三次握手就能确认双收发功能都正常,缺一不可。 所以三次握手就能确认双收发功能都正常,缺一不可。
### 2.3 第 2 次握手传回了 ACK为什么还要传回 SYN ### 第 2 次握手传回了 ACK为什么还要传回 SYN
接收端传回发送端所发送的 ACK 是为了告诉客户端,我接收到的信息确实就是你所发送的信号了,这表明从客户端到服务端的通信是正常的。而回传 SYN 则是为了建立并确认从服务端到客户端的通信。” 接收端传回发送端所发送的 ACK 是为了告诉客户端,我接收到的信息确实就是你所发送的信号了,这表明从客户端到服务端的通信是正常的。而回传 SYN 则是为了建立并确认从服务端到客户端的通信。”
> SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。 > SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
### 2.5 为什么要四次挥手 ### 为什么要四次挥手
![TCP四次挥手](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/TCP四次挥手.png) ![TCP四次挥手](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/TCP四次挥手.png)
@ -124,7 +141,7 @@ tag:
上面讲的比较概括,推荐一篇讲的比较细致的文章:[https://blog.csdn.net/qzcsu/article/details/72861891](https://blog.csdn.net/qzcsu/article/details/72861891) 上面讲的比较概括,推荐一篇讲的比较细致的文章:[https://blog.csdn.net/qzcsu/article/details/72861891](https://blog.csdn.net/qzcsu/article/details/72861891)
## TCP, UDP 协议的区别 ## TCP, UDP 协议的区别
![TCP、UDP协议的区别](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/tcp-vs-udp.jpg) ![TCP、UDP协议的区别](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/tcp-vs-udp.jpg)
@ -132,7 +149,7 @@ UDP 在传送数据之前不需要先建立连接,远地主机在收到 UDP
TCP 提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。 TCP 不提供广播或多播服务。由于 TCP 要提供可靠的面向连接的传输服务TCP 的可靠体现在 TCP 在传递数据之前会有三次握手来建立连接而且在数据传递时有确认、窗口、重传、拥塞控制机制在数据传完后还会断开连接用来节约系统资源这难以避免增加了许多开销如确认流量控制计时器以及连接管理等。这不仅使协议数据单元的首部增大很多还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。 TCP 提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。 TCP 不提供广播或多播服务。由于 TCP 要提供可靠的面向连接的传输服务TCP 的可靠体现在 TCP 在传递数据之前会有三次握手来建立连接而且在数据传递时有确认、窗口、重传、拥塞控制机制在数据传完后还会断开连接用来节约系统资源这难以避免增加了许多开销如确认流量控制计时器以及连接管理等。这不仅使协议数据单元的首部增大很多还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。
## TCP 协议如何保证可靠传输 ## TCP 协议如何保证可靠传输
1. 应用数据被分割成 TCP 认为最适合发送的数据块。 1. 应用数据被分割成 TCP 认为最适合发送的数据块。
2. TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。 2. TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
@ -143,7 +160,7 @@ TCP 提供面向连接的服务。在传送数据之前必须先建立连接,
7. **ARQ 协议:** 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。 7. **ARQ 协议:** 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
8. **超时重传:** 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。 8. **超时重传:** 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
### 4.1 ARQ 协议 ### ARQ 协议
**自动重传请求**Automatic Repeat-reQuestARQ是 OSI 模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧它通常会重新发送。ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。 **自动重传请求**Automatic Repeat-reQuestARQ是 OSI 模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧它通常会重新发送。ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
@ -180,11 +197,11 @@ TCP 提供面向连接的服务。在传送数据之前必须先建立连接,
* **优点:** 信道利用率高,容易实现,即使确认丢失,也不必重传。 * **优点:** 信道利用率高,容易实现,即使确认丢失,也不必重传。
* **缺点:** 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5 条 消息中间第三条丢失3 号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N回退 N表示需要退回来重传已经发送过的 N 个消息。 * **缺点:** 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5 条 消息中间第三条丢失3 号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N回退 N表示需要退回来重传已经发送过的 N 个消息。
### 4.2 滑动窗口和流量控制 ### 滑动窗口和流量控制
**TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。** 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0则发送方不能发送数据。 **TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。** 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0则发送方不能发送数据。
### 4.3 拥塞控制 ### 拥塞控制
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。 在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
@ -197,7 +214,7 @@ TCP 的拥塞控制采用了四种算法,即 **慢开始** 、 **拥塞避免*
* **快重传与快恢复:** * **快重传与快恢复:**
在 TCP/IP 中快速重传和恢复fast retransmit and recoveryFRR是一种拥塞控制算法它能快速恢复丢失的数据包。没有 FRR如果数据包丢失了TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR如果接收机接收到一个不按顺序的数据段它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认它会假定确认件指出的数据段丢失了并立即重传这些丢失的数据段。有了 FRR就不会因为重传时要求的暂停被耽误。  当有单独的数据包丢失时快速重传和恢复FRR能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时它则不能很有效地工作。 在 TCP/IP 中快速重传和恢复fast retransmit and recoveryFRR是一种拥塞控制算法它能快速恢复丢失的数据包。没有 FRR如果数据包丢失了TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR如果接收机接收到一个不按顺序的数据段它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认它会假定确认件指出的数据段丢失了并立即重传这些丢失的数据段。有了 FRR就不会因为重传时要求的暂停被耽误。  当有单独的数据包丢失时快速重传和恢复FRR能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时它则不能很有效地工作。
## 在浏览器中输入 url 地址 ->> 显示主页的过程(面试常客) ## 在浏览器中输入 url 地址 ->> 显示主页的过程(面试常客)
百度好像最喜欢问这个问题。 百度好像最喜欢问这个问题。
@ -222,11 +239,11 @@ TCP 的拥塞控制采用了四种算法,即 **慢开始** 、 **拥塞避免*
* [https://segmentfault.com/a/1190000006879700](https://segmentfault.com/a/1190000006879700) * [https://segmentfault.com/a/1190000006879700](https://segmentfault.com/a/1190000006879700)
## 状态码 ## 状态码
![状态码](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/状态码.png) ![状态码](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/状态码.png)
## 各种协议与 HTTP 协议之间的关系 ## 各种协议与 HTTP 协议之间的关系
一般面试官会通过这样的问题来考察你对计算机网络知识体系的理解。 一般面试官会通过这样的问题来考察你对计算机网络知识体系的理解。
@ -234,23 +251,7 @@ TCP 的拥塞控制采用了四种算法,即 **慢开始** 、 **拥塞避免*
![各种协议与HTTP协议之间的关系](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/各种协议与HTTP协议之间的关系.png) ![各种协议与HTTP协议之间的关系](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/各种协议与HTTP协议之间的关系.png)
## 八 HTTP 长连接, 短连接 ## HTTP 是不保存状态的协议, 如何保存用户状态?
在 HTTP/1.0 中默认使用短连接。也就是说,客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 HTTP 会话。
而从 HTTP/1.1 起,默认使用长连接,用以保持连接特性。使用长连接的 HTTP 协议,会在响应头加入这行代码:
```
Connection:keep-alive
```
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭客户端再次访问这个服务器时会继续使用这一条已经建立的连接。Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如 Apache中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
**HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。**
—— [《HTTP 长连接、短连接究竟是什么?》](https://www.cnblogs.com/gotodsp/p/6366163.html)
## 九 HTTP 是不保存状态的协议, 如何保存用户状态?
HTTP 是一种不保存状态即无状态stateless协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们保存用户状态呢Session 机制的存在就是为了解决这个问题Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session过了时间限制就会销毁这个 Session HTTP 是一种不保存状态即无状态stateless协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们保存用户状态呢Session 机制的存在就是为了解决这个问题Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session过了时间限制就会销毁这个 Session
@ -262,7 +263,7 @@ HTTP 是一种不保存状态即无状态stateless协议。也就是说
![HTTP是无状态协议](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/HTTP是无状态的.png) ![HTTP是无状态协议](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/HTTP是无状态的.png)
## Cookie 的作用是什么? 和 Session 有什么区别? ## Cookie 的作用是什么? 和 Session 有什么区别?
Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。 Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
@ -272,31 +273,13 @@ Cookie 数据保存在客户端(浏览器端)Session 数据保存在服务器
Cookie 存储在客户端中,而 Session 存储在服务器上,相对来说 Session 安全性更高。如果要在 Cookie 中存储一些敏感信息,不要直接写入 Cookie 中,最好能将 Cookie 信息加密,然后使用到的时候再去服务器端解密。 Cookie 存储在客户端中,而 Session 存储在服务器上,相对来说 Session 安全性更高。如果要在 Cookie 中存储一些敏感信息,不要直接写入 Cookie 中,最好能将 Cookie 信息加密,然后使用到的时候再去服务器端解密。
## 十一 HTTP 1.0 和 HTTP 1.1 的主要区别是什么? ## URI 和 URL 的区别是什么?
> 这部分回答引用这篇文章 <https://mp.weixin.qq.com/s/GICbiyJpINrHZ41u_4zT-A?> 的一些内容。
HTTP1.0 最早在网页中使用是在 1996 年,那个时候只是使用一些较为简单的网页上和网络请求上,而 HTTP1.1 则在 1999 年才开始广泛应用于现在的各大浏览器网络请求中,同时 HTTP1.1 也是当前使用最为广泛的 HTTP 协议。 主要区别主要体现在:
1. **长连接** : **在 HTTP/1.0 中,默认使用的是短连接**也就是说每次请求都要重新建立一次连接。HTTP 是基于 TCP/IP 协议的,每一次建立或者断开连接都需要三次握手四次挥手的开销,如果每次请求都要这样的话,开销会比较大。因此最好能维持一个长连接,可以用个长连接来发多个请求。**HTTP 1.1 起,默认使用长连接** ,默认开启 Connection keep-alive。 **HTTP/1.1 的持续连接有非流水线方式和流水线方式** 。流水线方式是客户在收到 HTTP 的响应报文之前就能接着发送新的请求报文。与之相对应的非流水线方式是客户在收到前一个响应后才能发送下一个请求。
1. **错误状态响应码** :在 HTTP1.1 中新增了 24 个错误状态响应码,如 409Conflict表示请求的资源与资源的当前状态发生冲突410Gone表示服务器上的某个资源被永久性的删除。
1. **缓存处理** :在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准HTTP1.1 则引入了更多的缓存控制策略例如 Entity tagIf-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
1. **带宽优化及网络连接的使用** :HTTP1.0 中存在一些浪费带宽的现象例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了并且不支持断点续传功能HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206Partial Content这样就方便了开发者自由的选择以便于充分利用带宽和连接。
## 十二 URI 和 URL 的区别是什么?
* URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。 * URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
* URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。 * URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。
URI 的作用像身份证号一样URL 的作用更像家庭住址一样。URL 是一种具体的 URI它不仅唯一标识资源而且还提供了定位该资源的信息。 URI 的作用像身份证号一样URL 的作用更像家庭住址一样。URL 是一种具体的 URI它不仅唯一标识资源而且还提供了定位该资源的信息。
## 十三 HTTP 和 HTTPS 的区别?
1. **端口** HTTP 的 URL 由“http://”起始且默认使用端口80而HTTPS的URL由“https://”起始且默认使用端口443。
2. **安全性和资源消耗:** HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
- 对称加密:密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有 DES、AES 等;
- 非对称加密:密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有 RSA、DSA 等。
## 建议 ## 建议
非常推荐大家看一下 《图解 HTTP》 这本书,这本书页数不多,但是内容很是充实,不管是用来系统的掌握网络方面的一些知识还是说纯粹为了应付面试都有很大帮助。下面的一些文章只是参考。大二学习这门课程的时候,我们使用的教材是 《计算机网络第七版》(谢希仁编著),不推荐大家看这本教材,书非常厚而且知识偏理论,不确定大家能不能心平气和的读完。 非常推荐大家看一下 《图解 HTTP》 这本书,这本书页数不多,但是内容很是充实,不管是用来系统的掌握网络方面的一些知识还是说纯粹为了应付面试都有很大帮助。下面的一些文章只是参考。大二学习这门课程的时候,我们使用的教材是 《计算机网络第七版》(谢希仁编著),不推荐大家看这本教材,书非常厚而且知识偏理论,不确定大家能不能心平气和的读完。

View File

@ -328,7 +328,7 @@ HTTP 协议的本质就是一种浏览器与服务器之间约定好的通信格
![一个电子邮件被发送的过程](https://img-blog.csdnimg.cn/img_convert/b16da4d4fea63de5fce53f54973967d7.png) ![一个电子邮件被发送的过程](https://img-blog.csdnimg.cn/img_convert/b16da4d4fea63de5fce53f54973967d7.png)
<p style="text-align:right;font-size:12px">https://www.campaignmonitor.com/resources/knowledge-base/what-is-the-code-that-makes-bcc-or-cc-operate-in-an-email/<p> <p style="text-align:right;font-size:12px">https://www.campaignmonitor.com/resources/knowledge-base/what-is-the-code-that-makes-bcc-or-cc-operate-in-an-email/</p>
11. **搜索引擎** :搜索引擎Search Engine是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息在对信息进行组织和处理后为用户提供检索服务将用户检索相关的信息展示给用户的系统。搜索引擎包括全文索引、目录索引、元搜索引擎、垂直搜索引擎、集合式搜索引擎、门户搜索引擎与免费链接列表等。 11. **搜索引擎** :搜索引擎Search Engine是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息在对信息进行组织和处理后为用户提供检索服务将用户检索相关的信息展示给用户的系统。搜索引擎包括全文索引、目录索引、元搜索引擎、垂直搜索引擎、集合式搜索引擎、门户搜索引擎与免费链接列表等。

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

View File

@ -37,7 +37,7 @@ _如果文章有任何需要改善和完善的地方欢迎在评论区指出
_玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Windows 用于玩游戏,一台 Mac 用于平时日常开发和学习使用。_ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Windows 用于玩游戏,一台 Mac 用于平时日常开发和学习使用。_
![windows](images/windows.png) ![windows](./images/windows.png)
#### 1.2.2. Unix #### 1.2.2. Unix
@ -45,7 +45,7 @@ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Win
目前这款操作系统已经逐渐逐渐退出操作系统的舞台。 目前这款操作系统已经逐渐逐渐退出操作系统的舞台。
![unix](images/unix.png) ![unix](./images/unix.png)
#### 1.2.3. Linux #### 1.2.3. Linux
@ -55,13 +55,13 @@ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Win
> >
> **很多人更倾向使用 “GNU/Linux” 一词来表达人们通常所说的 “Linux”。** > **很多人更倾向使用 “GNU/Linux” 一词来表达人们通常所说的 “Linux”。**
![linux](images/linux.png) ![linux](./images/linux.png)
#### 1.2.4. Mac OS #### 1.2.4. Mac OS
苹果自家的操作系统,编程体验和 Linux 相当,但是界面、软件生态以及用户体验各方面都要比 Linux 操作系统更好。 苹果自家的操作系统,编程体验和 Linux 相当,但是界面、软件生态以及用户体验各方面都要比 Linux 操作系统更好。
![macos](images/macos.png) ![macos](./images/macos.png)
### 1.3. 操作系统的内核Kernel ### 1.3. 操作系统的内核Kernel
@ -132,7 +132,7 @@ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Win
- **Linux 本质是指 Linux 内核** 严格来讲Linux 这个词本身只表示 Linux 内核,单独的 Linux 内核并不能成为一个可以正常工作的操作系统。所以,就有了各种 Linux 发行版。 - **Linux 本质是指 Linux 内核** 严格来讲Linux 这个词本身只表示 Linux 内核,单独的 Linux 内核并不能成为一个可以正常工作的操作系统。所以,就有了各种 Linux 发行版。
- **Linux 之父(林纳斯·本纳第克特·托瓦兹 Linus Benedict Torvalds)** 一个编程领域的传奇式人物,真大佬!我辈崇拜敬仰之楷模。他是 **Linux 内核** 的最早作者,随后发起了这个开源项目,担任 Linux 内核的首要架构师。他还发起了 Git 这个开源项目,并为主要的开发者。 - **Linux 之父(林纳斯·本纳第克特·托瓦兹 Linus Benedict Torvalds)** 一个编程领域的传奇式人物,真大佬!我辈崇拜敬仰之楷模。他是 **Linux 内核** 的最早作者,随后发起了这个开源项目,担任 Linux 内核的首要架构师。他还发起了 Git 这个开源项目,并为主要的开发者。
![Linux](images/Linux之父.png) ![Linux](./images/Linux之父.png)
### 2.2. Linux 诞生 ### 2.2. Linux 诞生
@ -142,7 +142,7 @@ _玩玩电脑游戏还是必须要有 Windows 的,所以我现在是一台 Win
1991 年Linus Torvalds 开源了 Linux 内核。Linux 以一只可爱的企鹅作为标志,象征着敢作敢为、热爱生活。 1991 年Linus Torvalds 开源了 Linux 内核。Linux 以一只可爱的企鹅作为标志,象征着敢作敢为、热爱生活。
![OPINION: Make the switch to a Linux operating system | Opinion ...](images/Linux-Logo.png) ![OPINION: Make the switch to a Linux operating system | Opinion ...](./images/Linux-Logo.png)
### 2.3. 常见 Linux 发行版本有哪些? ### 2.3. 常见 Linux 发行版本有哪些?
@ -182,7 +182,7 @@ Linux 的发行版本可以大体分为两类:
- **inode** :记录文件的属性信息,可以使用 stat 命令查看 inode 信息。 - **inode** :记录文件的属性信息,可以使用 stat 命令查看 inode 信息。
- **block** :实际文件的内容,如果一个文件大于一个块时候,那么将占用多个 block但是一个块只能存放一个文件。因为数据是由 inode 指向的,如果有两个文件的数据存放在同一个块中,就会乱套了) - **block** :实际文件的内容,如果一个文件大于一个块时候,那么将占用多个 block但是一个块只能存放一个文件。因为数据是由 inode 指向的,如果有两个文件的数据存放在同一个块中,就会乱套了)
![文件inode信息](images/文件inode信息.png) ![文件inode信息](./images/文件inode信息.png)
### 3.3. Linux 文件类型 ### 3.3. Linux 文件类型
@ -203,7 +203,7 @@ Linux 支持很多文件类型,其中非常重要的文件类型有: **普通
**Linux 的目录结构如下:** **Linux 的目录结构如下:**
Linux 文件系统的结构层次鲜明,就像一棵倒立的树,最顶层是其根目录: Linux 文件系统的结构层次鲜明,就像一棵倒立的树,最顶层是其根目录:
![Linux的目录结构](images/Linux目录树.png) ![Linux的目录结构](./images/Linux目录树.png)
**常见目录说明:** **常见目录说明:**
@ -287,11 +287,11 @@ Linux 中的打包文件一般是以.tar 结尾的,压缩的命令一般是以
示例:在随意某个目录下`ls -l` 示例:在随意某个目录下`ls -l`
![](images/Linux权限命令.png) ![](./images/Linux权限命令.png)
第一列的内容的信息解释如下: 第一列的内容的信息解释如下:
![](images/Linux权限解读.png) ![](./images/Linux权限解读.png)
> 下面将详细讲解文件的类型、Linux 中权限以及文件有所有者、所在组、其它组具体是什么? > 下面将详细讲解文件的类型、Linux 中权限以及文件有所有者、所在组、其它组具体是什么?
@ -343,7 +343,7 @@ Linux 中的打包文件一般是以.tar 结尾的,压缩的命令一般是以
**`chmod u=rwx,g=rw,o=r aaa.txt`** 或者 **`chmod 764 aaa.txt`** **`chmod u=rwx,g=rw,o=r aaa.txt`** 或者 **`chmod 764 aaa.txt`**
![](images/修改文件权限.png) ![](./images/修改文件权限.png)
**补充一个比较常用的东西:** **补充一个比较常用的东西:**

View File

@ -5,11 +5,9 @@ tag:
- 操作系统 - 操作系统
--- ---
大家好,我是 Guide 哥!
很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如**进程管理**、**内存管理**、**虚拟内存**等等。 很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如**进程管理**、**内存管理**、**虚拟内存**等等。
文章形式通过大部分比较喜欢的面试官和求职者之间的对话形式展开。另外Guide哥 也只是在大学的时候学习过操作系统,不过基本都忘了,为了写这篇文章这段时间看了很多相关的书籍和博客。如果文中有任何需要补充和完善的地方,你都可以在 issue 中指出! 文章形式通过大部分比较喜欢的面试官和求职者之间的对话形式展开。另外Guide 哥 也只是在大学的时候学习过操作系统,不过基本都忘了,为了写这篇文章这段时间看了很多相关的书籍和博客。如果文中有任何需要补充和完善的地方,你都可以在 issue 中指出!
这篇文章只是对一些操作系统比较重要概念的一个概览,深入学习的话,建议大家还是老老实实地去看书。另外, 这篇文章的很多内容参考了《现代操作系统》第三版这本书,非常感谢。 这篇文章只是对一些操作系统比较重要概念的一个概览,深入学习的话,建议大家还是老老实实地去看书。另外, 这篇文章的很多内容参考了《现代操作系统》第三版这本书,非常感谢。
@ -26,8 +24,6 @@ tag:
面试官顶着蓬松的假发向我走来,只见他一手拿着厚重的 Thinkpad ,一手提着他那淡黄的长裙。 面试官顶着蓬松的假发向我走来,只见他一手拿着厚重的 Thinkpad ,一手提着他那淡黄的长裙。
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/ceeb653ely1gd8wj5evc4j20i00n0dh0.jpg" height="300"></img>
### 1.1 什么是操作系统? ### 1.1 什么是操作系统?
👨‍💻**面试官** 先来个简单问题吧!**什么是操作系统?** 👨‍💻**面试官** 先来个简单问题吧!**什么是操作系统?**
@ -74,8 +70,6 @@ tag:
🙋 **我:** 好的! 下图是 Java 内存区域,我们从 JVM 的角度来说一下线程和进程之间的关系吧! 🙋 **我:** 好的! 下图是 Java 内存区域,我们从 JVM 的角度来说一下线程和进程之间的关系吧!
> 如果你对 Java 内存区域 (运行时数据区) 这部分知识不太了解的话可以阅读一下这篇文章:[《可能是把 Java 内存区域讲的最清楚的一篇文章》](https://snailclimb.gitee.io/javaguide/#/docs/java/jvm/Java内存区域)
![](https://oscimg.oschina.net/oscnet/up-cd8ac705f6f004c01e0a1312f1599430ba5.png) ![](https://oscimg.oschina.net/oscnet/up-cd8ac705f6f004c01e0a1312f1599430ba5.png)
从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的**堆**和**方法区 (JDK1.8 之后的元空间)**资源,但是每个线程有自己的**程序计数器**、**虚拟机栈** 和 **本地方法栈** 从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的**堆**和**方法区 (JDK1.8 之后的元空间)**资源,但是每个线程有自己的**程序计数器**、**虚拟机栈** 和 **本地方法栈**
@ -157,6 +151,88 @@ tag:
注意,只有四个条件同时成立时,死锁才会出现。 注意,只有四个条件同时成立时,死锁才会出现。
### 2.8 解决死锁的方法
解决死锁的方法可以从多个角度去分析,一般的情况下,有**预防,避免,检测和解除四种**。
- **预防** 是采用某种策略,**限制并发进程对资源的请求**,从而使得死锁的必要条件在系统执行的任何时间上都不满足。
- **避免**则是系统在分配资源时,根据资源的使用情况**提前做出预测**,从而**避免死锁的发生**
- **检测**是指系统设有**专门的机构**,当死锁发生时,该机构能够检测死锁的发生,并精确地确定与死锁有关的进程和资源。
- **解除** 是与检测相配套的一种措施,用于**将进程从死锁状态下解脱出来**。
#### 死锁的预防
死锁四大必要条件上面都已经列出来了,很显然,只要破坏四个必要条件中的任何一个就能够预防死锁的发生。
破坏第一个条件 **互斥条件**:使得资源是可以同时访问的,这是种简单的方法,磁盘就可以用这种方法管理,但是我们要知道,有很多资源 **往往是不能同时访问的** ,所以这种做法在大多数的场合是行不通的。
破坏第三个条件 **非抢占** :也就是说可以采用 **剥夺式调度算法**,但剥夺式调度方法目前一般仅适用于 **主存资源****处理器资源** 的分配,并不适用于所以的资源,会导致 **资源利用率下降**
所以一般比较实用的 **预防死锁的方法**,是通过考虑破坏第二个条件和第四个条件。
**1、静态分配策略**
静态分配策略可以破坏死锁产生的第二个条件(占有并等待)。所谓静态分配策略,就是指一个进程必须在执行前就申请到它所需要的全部资源,并且知道它所要的资源都得到满足之后才开始执行。进程要么占有所有的资源然后开始执行,要么不占有资源,不会出现占有一些资源等待一些资源的情况。
静态分配策略逻辑简单,实现也很容易,但这种策略 **严重地降低了资源利用率**,因为在每个进程所占有的资源中,有些资源是在比较靠后的执行时间里采用的,甚至有些资源是在额外的情况下才是用的,这样就可能造成了一个进程占有了一些 **几乎不用的资源而使其他需要该资源的进程产生等待** 的情况。
**2、层次分配策略**
层次分配策略破坏了产生死锁的第四个条件(循环等待)。在层次分配策略下,所有的资源被分成了多个层次,一个进程得到某一次的一个资源后,它只能再申请较高一层的资源;当一个进程要释放某层的一个资源时,必须先释放所占用的较高层的资源,按这种策略,是不可能出现循环等待链的,因为那样的话,就出现了已经申请了较高层的资源,反而去申请了较低层的资源,不符合层次分配策略,证明略。
#### 死锁的避免
上面提到的 **破坏** 死锁产生的四个必要条件之一就可以成功 **预防系统发生死锁** ,但是会导致 **低效的进程运行****资源使用率** 。而死锁的避免相反,它的角度是允许系统中**同时存在四个必要条件** ,只要掌握并发进程中与每个进程有关的资源动态申请情况,做出 **明智和合理的选择** ,仍然可以避免死锁,因为四大条件仅仅是产生死锁的必要条件。
我们将系统的状态分为 **安全状态****不安全状态** ,每当在未申请者分配资源前先测试系统状态,若把系统资源分配给申请者会产生死锁,则拒绝分配,否则接受申请,并为它分配资源。
> 如果操作系统能够保证所有的进程在有限的时间内得到需要的全部资源,则称系统处于安全状态,否则说系统是不安全的。很显然,系统处于安全状态则不会发生死锁,系统若处于不安全状态则可能发生死锁。
那么如何保证系统保持在安全状态呢?通过算法,其中最具有代表性的 **避免死锁算法** 就是 Dijkstra 的银行家算法,银行家算法用一句话表达就是:当一个进程申请使用资源的时候,**银行家算法** 通过先 **试探** 分配给该进程资源,然后通过 **安全性算法** 判断分配后系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待,若能够进入到安全的状态,则就 **真的分配资源给该进程**
银行家算法详情可见:[《一句话+一张图说清楚——银行家算法》](https://blog.csdn.net/qq_33414271/article/details/80245715) 。
操作系统教程树中讲述的银行家算法也比较清晰,可以一看.
死锁的避免(银行家算法)改善解决了 **资源使用率低的问题** ,但是它要不断地检测每个进程对各类资源的占用和申请情况,以及做 **安全性检查** ,需要花费较多的时间。
#### 死锁的检测
对资源的分配加以限制可以 **预防和避免** 死锁的发生,但是都不利于各进程对系统资源的**充分共享**。解决死锁问题的另一条途径是 **死锁检测和解除** (这里突然联想到了乐观锁和悲观锁,感觉死锁的检测和解除就像是 **乐观锁** ,分配资源时不去提前管会不会发生死锁了,等到真的死锁出现了再来解决嘛,而 **死锁的预防和避免** 更像是悲观锁,总是觉得死锁会出现,所以在分配资源的时候就很谨慎)。
这种方法对资源的分配不加以任何限制,也不采取死锁避免措施,但系统 **定时地运行一个 “死锁检测”** 的程序,判断系统内是否出现死锁,如果检测到系统发生了死锁,再采取措施去解除它。
##### 进程-资源分配图
操作系统中的每一刻时刻的**系统状态**都可以用**进程-资源分配图**来表示,进程-资源分配图是描述进程和资源申请及分配关系的一种有向图,可用于**检测系统是否处于死锁状态**。
用一个方框表示每一个资源类,方框中的黑点表示该资源类中的各个资源,每个键进程用一个圆圈表示,用 **有向边** 来表示**进程申请资源和资源被分配的情况**。
图中 2-21 是**进程-资源分配图**的一个例子,其中共有三个资源类,每个进程的资源占有和申请情况已清楚地表示在图中。在这个例子中,由于存在 **占有和等待资源的环路** ,导致一组进程永远处于等待资源的状态,发生了 **死锁**
![进程-资源分配图](./images/进程-资源分配图.jpg)
进程-资源分配图中存在环路并不一定是发生了死锁。因为循环等待资源仅仅是死锁发生的必要条件,而不是充分条件。图 2-22 便是一个有环路而无死锁的例子。虽然进程 P1 和进程 P3 分别占用了一个资源 R1 和一个资源 R2并且因为等待另一个资源 R2 和另一个资源 R1 形成了环路,但进程 P2 和进程 P4 分别占有了一个资源 R1 和一个资源 R2它们申请的资源得到了满足在有限的时间里会归还资源于是进程 P1 或 P3 都能获得另一个所需的资源,环路自动解除,系统也就不存在死锁状态了。
##### 死锁检测步骤
知道了死锁检测的原理,我们可以利用下列步骤编写一个 **死锁检测** 程序,检测系统是否产生了死锁。
1. 如果进程-资源分配图中无环路,则此时系统没有发生死锁
2. 如果进程-资源分配图中有环路,且每个资源类仅有一个资源,则系统中已经发生了死锁。
3. 如果进程-资源分配图中有环路,且涉及到的资源类有多个资源,此时系统未必会发生死锁。如果能在进程-资源分配图中找出一个 **既不阻塞又非独立的进程** ,该进程能够在有限的时间内归还占有的资源,也就是把边给消除掉了,重复此过程,直到能在有限的时间内 **消除所有的边** ,则不会发生死锁,否则会发生死锁。(消除边的过程类似于 **拓扑排序**)
#### 死锁的解除
当死锁检测程序检测到存在死锁发生时,应设法让其解除,让系统从死锁状态中恢复过来,常用的解除死锁的方法有以下四种:
1. **立即结束所有进程的执行,重新启动操作系统** :这种方法简单,但以前所在的工作全部作废,损失很大。
2. **撤销涉及死锁的所有进程,解除死锁后继续运行** :这种方法能彻底打破**死锁的循环等待**条件,但将付出很大代价,例如有些进程可能已经计算了很长时间,由于被撤销而使产生的部分结果也被消除了,再重新执行时还要再次进行计算。
3. **逐个撤销涉及死锁的进程,回收其资源直至死锁解除。**
4. **抢占资源** :从涉及死锁的一个或几个进程中抢占资源,把夺得的资源再分配给涉及死锁的进程直至死锁解除。
## 三 操作系统内存管理基础 ## 三 操作系统内存管理基础
### 3.1 内存管理介绍 ### 3.1 内存管理介绍
@ -346,7 +422,7 @@ tag:
- **OPT 页面置换算法(最佳页面置换算法)** :最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法。 - **OPT 页面置换算法(最佳页面置换算法)** :最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法。
- **FIFOFirst In First Out 页面置换算法(先进先出页面置换算法)** : 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。 - **FIFOFirst In First Out 页面置换算法(先进先出页面置换算法)** : 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。
- **LRU Least Recently Used页面置换算法最近最久未使用页面置换算法** LRU算法赋予每个页面一个访问字段用来记录一个页面自上次被访问以来所经历的时间 T当须淘汰一个页面时选择现有页面中其 T 值最大的,即最近最久未使用的页面予以淘汰。 - **LRU Least Recently Used页面置换算法最近最久未使用页面置换算法** LRU 算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T当须淘汰一个页面时选择现有页面中其 T 值最大的,即最近最久未使用的页面予以淘汰。
- **LFU Least Frequently Used页面置换算法最少使用页面置换算法** : 该置换算法选择在之前时期使用最少的页面作为淘汰页。 - **LFU Least Frequently Used页面置换算法最少使用页面置换算法** : 该置换算法选择在之前时期使用最少的页面作为淘汰页。
## Reference ## Reference
@ -360,16 +436,3 @@ tag:
- <https://www.geeksforgeeks.org/interprocess-communication-methods/> - <https://www.geeksforgeeks.org/interprocess-communication-methods/>
- <https://juejin.im/post/59f8691b51882534af254317> - <https://juejin.im/post/59f8691b51882534af254317>
- 王道考研操作系统知识点整理: https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/13.html - 王道考研操作系统知识点整理: https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/13.html

View File

@ -84,7 +84,7 @@ B 树也称 B-树,全称为 **多路平衡查找树** B+ 树是 B 树的一
MyISAM 引擎中B+Tree 叶节点的 data 域存放的是数据记录的地址。在索引检索的时候,首先按照 B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。 MyISAM 引擎中B+Tree 叶节点的 data 域存放的是数据记录的地址。在索引检索的时候,首先按照 B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。
InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM索引文件和数据文件是分离的其表数据文件本身就是按 B+Tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。这个索引的 key 是数据表的主键,因此 InnoDB 表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”,而其余的索引都作为辅助索引,辅助索引的 data 域存储相应记录主键的值而不是地址,这也是和 MyISAM 不同的地方。在根据主索引搜索时,直接找到 key 所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。 InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM索引文件和数据文件是分离的其表数据文件本身就是按 B+Tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。这个索引的 key 是数据表的主键,因此 InnoDB 表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”,而其余的索引都作为辅助索引,辅助索引的 data 域存储相应记录主键的值而不是地址,这也是和 MyISAM 不同的地方。在根据主索引搜索时,直接找到 key 所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。
## 索引类型 ## 索引类型
@ -94,7 +94,7 @@ InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM
一张数据表有只能有一个主键,并且主键不能为 null不能重复。 一张数据表有只能有一个主键,并且主键不能为 null不能重复。
在 MySQL 的 InnoDB 的表中当没有显示的指定表的主键时InnoDB 会自动先检查表中是否有唯一索引的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。 在 MySQL 的 InnoDB 的表中当没有显示的指定表的主键时InnoDB 会自动先检查表中是否有唯一索引且不允许存在null值的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。
### 二级索引(辅助索引) ### 二级索引(辅助索引)

View File

@ -241,7 +241,7 @@ MySQL InnoDB 引擎通过 **锁机制**、**MVCC** 等手段来保证事务的
**不可重复读和幻读区别:** **不可重复读和幻读区别:**
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。 不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次查询同一条查询语句DQL记录发现记录增多或减少了。
### 事务隔离级别有哪些? ### 事务隔离级别有哪些?
@ -276,7 +276,7 @@ mysql> SELECT @@tx_isolation;
~~这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 **REPEATABLE-READ可重读** 事务隔离级别下使用的是 Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说 InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ可重读** 已经可以完全保证事务的隔离性要求,即达到了 SQL 标准的 **SERIALIZABLE(可串行化)** 隔离级别。~~ ~~这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 **REPEATABLE-READ可重读** 事务隔离级别下使用的是 Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说 InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ可重读** 已经可以完全保证事务的隔离性要求,即达到了 SQL 标准的 **SERIALIZABLE(可串行化)** 隔离级别。~~
🐛 问题更正:**MySQL InnoDB 的 REPEATABLE-READ可重读并不保证避免幻读需要应用使用加锁读来保证。而这个加锁使用到的机制就是 Next-Key Locks。** 🐛 问题更正:**MySQL InnoDB 的 REPEATABLE-READ可重读并不保证避免幻读需要应用使用加锁读来保证。而这个加锁使用到的机制就是 Next-Key Locks。**
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 **READ-COMMITTED(读取提交内容)** ,但是你要知道的是 InnoDB 存储引擎默认使用 **REPEATABLE-READ可重读** 并不会有任何性能损失。 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 **READ-COMMITTED(读取提交内容)** ,但是你要知道的是 InnoDB 存储引擎默认使用 **REPEATABLE-READ可重读** 并不会有任何性能损失。

View File

@ -74,7 +74,7 @@ mysql> SELECT @@tx_isolation;
~~这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 **REPEATABLE-READ可重读** 事务隔离级别下使用的是 Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说 InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ可重读** 已经可以完全保证事务的隔离性要求,即达到了 SQL 标准的 **SERIALIZABLE(可串行化)** 隔离级别。~~ ~~这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 **REPEATABLE-READ可重读** 事务隔离级别下使用的是 Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说 InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ可重读** 已经可以完全保证事务的隔离性要求,即达到了 SQL 标准的 **SERIALIZABLE(可串行化)** 隔离级别。~~
🐛 问题更正:**MySQL InnoDB 的 REPEATABLE-READ可重读并不保证避免幻读需要应用使用加锁读来保证。而这个加锁使用到的机制就是 Next-Key Locks。** 🐛 问题更正:**MySQL InnoDB 的 REPEATABLE-READ可重读并不保证避免幻读需要应用使用加锁读来保证。而这个加锁使用到的机制就是 Next-Key Locks。**
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 **READ-COMMITTED(读取提交内容)** ,但是你要知道的是 InnoDB 存储引擎默认使用 **REPEATABLE-READ可重读** 并不会有任何性能损失。 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 **READ-COMMITTED(读取提交内容)** ,但是你要知道的是 InnoDB 存储引擎默认使用 **REPEATABLE-READ可重读** 并不会有任何性能损失。
@ -88,7 +88,7 @@ InnoDB 存储引擎在 **分布式事务** 的情况下一般会用到 **SERIALI
在下面我会使用 2 个命令行mysql ,模拟多线程(多事务)对同一份数据的脏读问题。 在下面我会使用 2 个命令行mysql ,模拟多线程(多事务)对同一份数据的脏读问题。
MySQL 命令行的默认配置中事务都是自动提交的即执行SQL语句后就会马上执行 COMMIT 操作。如果要显式地开启一个事务需要使用命令:`START TARNSACTION`。 MySQL 命令行的默认配置中事务都是自动提交的即执行SQL语句后就会马上执行 COMMIT 操作。如果要显式地开启一个事务需要使用命令:`START TRANSACTION`。
我们可以通过下面的命令来设置隔离级别。 我们可以通过下面的命令来设置隔离级别。
@ -98,7 +98,7 @@ SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTE
我们再来看一下我们在下面实际操作中使用到的一些并发控制语句: 我们再来看一下我们在下面实际操作中使用到的一些并发控制语句:
- `START TARNSACTION` |`BEGIN`:显式地开启一个事务。 - `START TRANSACTION` |`BEGIN`:显式地开启一个事务。
- `COMMIT`:提交事务,使得对数据库做的所有修改成为永久性。 - `COMMIT`:提交事务,使得对数据库做的所有修改成为永久性。
- `ROLLBACK`:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。 - `ROLLBACK`:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。

View File

@ -99,7 +99,7 @@ Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从
![](https://img-blog.csdnimg.cn/img_convert/9ada757c78614934aca11306f334638d.png) ![](https://img-blog.csdnimg.cn/img_convert/9ada757c78614934aca11306f334638d.png)
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache而 Read Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。 Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache而 Read-Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
和 Cache Aside Pattern 一样, Read-Through Pattern 也有首次请求数据一定不再 cache 的问题,对于热点数据可以提前放入缓存中。 和 Cache Aside Pattern 一样, Read-Through Pattern 也有首次请求数据一定不再 cache 的问题,对于热点数据可以提前放入缓存中。

View File

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -48,7 +48,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来
作为暖男一号,我给大家画了一个草图。 作为暖男一号,我给大家画了一个草图。
![正常缓存处理流程](images/redis-all/缓存的处理流程.png) ![正常缓存处理流程](./images/redis-all/cache-process.png)
简单来说就是: 简单来说就是:
@ -420,7 +420,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
- 文件事件分派器(将 socket 关联到相应的事件处理器) - 文件事件分派器(将 socket 关联到相应的事件处理器)
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器) - 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
![](images/redis-all/redis事件处理器.png) ![](./images/redis-all/redis事件处理器.png)
<p style="text-align:right; font-size:14px; color:gray">《Redis设计与实现12章》</p> <p style="text-align:right; font-size:14px; color:gray">《Redis设计与实现12章》</p>
@ -428,7 +428,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。** 虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。**
![redis4.0 more thread](images/redis-all/redis4.0-more-thread.png) ![redis4.0 more thread](./images/redis-all/redis4.0-more-thread.png)
不过Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他线程来“异步处理”。 不过Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他线程来“异步处理”。
@ -482,7 +482,7 @@ OK
(integer) 56 (integer) 56
``` ```
注意:**Redis 中除了字符串类型有自己独有设置过期时间的命令 `setex` 外,其他方法都需要依靠 `expire` 命令来设置过期时间 。另外, `persist` 命令可以移除一个键的过期时间。 ** 注意:**Redis 中除了字符串类型有自己独有设置过期时间的命令 `setex` 外,其他方法都需要依靠 `expire` 命令来设置过期时间 。另外, `persist` 命令可以移除一个键的过期时间。**
**过期时间除了有助于缓解内存的消耗,还有什么其他用么?** **过期时间除了有助于缓解内存的消耗,还有什么其他用么?**
@ -494,7 +494,7 @@ OK
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。 Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
![redis过期字典](images/redis-all/redis过期时间.png) ![redis过期字典](./images/redis-all/redis过期时间.png)
过期字典是存储在 redisDb 这个结构里的: 过期字典是存储在 redisDb 这个结构里的:
@ -577,7 +577,7 @@ AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数
```conf ```conf
appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度 appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec #每秒钟同步一次,显地将多个写命令同步到硬盘 appendfsync everysec #每秒钟同步一次,显地将多个写命令同步到硬盘
appendfsync no #让操作系统决定何时进行同步 appendfsync no #让操作系统决定何时进行同步
``` ```
@ -712,7 +712,7 @@ ERR EXEC without MULTI
Redis 官网相关介绍 [https://redis.io/topics/transactions](https://redis.io/topics/transactions) 如下: Redis 官网相关介绍 [https://redis.io/topics/transactions](https://redis.io/topics/transactions) 如下:
![redis事务](images/redis-all/redis事务.png) ![redis事务](./images/redis-all/redis事务.png)
但是Redis 的事务和我们平时理解的关系型数据库的事务不同。我们知道事务具有四大特性: **1. 原子性****2. 隔离性****3. 持久性****4. 一致性**。 但是Redis 的事务和我们平时理解的关系型数据库的事务不同。我们知道事务具有四大特性: **1. 原子性****2. 隔离性****3. 持久性****4. 一致性**。
@ -725,7 +725,7 @@ Redis 官网相关介绍 [https://redis.io/topics/transactions](https://redis.io
Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis 开发者们觉得没必要支持回滚这样更简单便捷并且性能更好。Redis 开发者觉得即使命令执行错误也应该在开发过程中就被发现而不是生产过程中。 Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis 开发者们觉得没必要支持回滚这样更简单便捷并且性能更好。Redis 开发者觉得即使命令执行错误也应该在开发过程中就被发现而不是生产过程中。
![redis roll back](images/redis-all/redis-rollBack.png) ![redis roll back](./images/redis-all/redis-rollBack.png)
你可以将 Redis 中的事务就理解为 **Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。** 你可以将 Redis 中的事务就理解为 **Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。**
@ -758,7 +758,8 @@ Redis 5.0 新增加的一个数据结构 `Stream` 可以用来做消息队列,
如下图所示,用户的请求最终都要跑到数据库中查询一遍。 如下图所示,用户的请求最终都要跑到数据库中查询一遍。
![缓存穿透情况](./images/redis-all/缓存穿透情况.png) ![缓存穿透情况](https://img-blog.csdnimg.cn/6358650a9bf742838441d636430c90b9.png)
#### 有哪些解决办法? #### 有哪些解决办法?
@ -801,7 +802,7 @@ public Object getObjectInclNullById(Integer id) {
加入布隆过滤器之后的缓存处理流程图如下。 加入布隆过滤器之后的缓存处理流程图如下。
![image](images/redis-all/加入布隆过滤器后的缓存处理流程.png) ![](./images/redis-all/加入布隆过滤器后的缓存处理流程.png)
但是,需要注意的是布隆过滤器可能会存在误判的情况。总结来说就是: **布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。** 但是,需要注意的是布隆过滤器可能会存在误判的情况。总结来说就是: **布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。**

View File

@ -36,7 +36,7 @@ root@eaf70fc620cb:/apache-zookeeper-3.5.8-bin# cd bin
如果你看到控制台成功打印出如下信息的话,说明你已经成功连接 ZooKeeper 服务。 如果你看到控制台成功打印出如下信息的话,说明你已经成功连接 ZooKeeper 服务。
![](images/连接ZooKeeper服务.png) ![](./images/连接ZooKeeper服务.png)
### 2.3. 常用命令演示 ### 2.3. 常用命令演示
@ -162,7 +162,7 @@ numChildren = 1
Curator 是Netflix公司开源的一套 ZooKeeper Java客户端框架相比于 Zookeeper 自带的客户端 zookeeper 来说Curator 的封装更加完善,各种 API 都可以比较方便地使用。 Curator 是Netflix公司开源的一套 ZooKeeper Java客户端框架相比于 Zookeeper 自带的客户端 zookeeper 来说Curator 的封装更加完善,各种 API 都可以比较方便地使用。
![](images/curator.png) ![](./images/curator.png)
下面我们就来简单地演示一下 Curator 的使用吧! 下面我们就来简单地演示一下 Curator 的使用吧!

View File

@ -79,7 +79,7 @@ ZooKeeper 数据模型采用层次化的多叉树形结构,每个节点上都
从下图可以更直观地看出ZooKeeper 节点路径标识方式和 Unix 文件系统路径非常相似,都是由一系列使用斜杠"/"进行分割的路径表示,开发人员可以向这个节点中写入数据,也可以在节点下面创建子节点。这些操作我们后面都会介绍到。 从下图可以更直观地看出ZooKeeper 节点路径标识方式和 Unix 文件系统路径非常相似,都是由一系列使用斜杠"/"进行分割的路径表示,开发人员可以向这个节点中写入数据,也可以在节点下面创建子节点。这些操作我们后面都会介绍到。
![ZooKeeper 数据模型](images/znode-structure.png) ![ZooKeeper 数据模型](./images/znode-structure.png)
### 3.2. znode数据节点 ### 3.2. znode数据节点
@ -172,9 +172,9 @@ ZooKeeper 采用 ACLAccessControlLists策略来进行权限控制类似
Watcher事件监听器是 ZooKeeper 中的一个很重要的特性。ZooKeeper 允许用户在指定节点上注册一些 Watcher并且在一些特定事件触发的时候ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。 Watcher事件监听器是 ZooKeeper 中的一个很重要的特性。ZooKeeper 允许用户在指定节点上注册一些 Watcher并且在一些特定事件触发的时候ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。
![watcher机制](images/watche机制.png) ![watcher机制](./images/watche机制.png)
_破音非常有用的一个特性出小本本记好了,后面用到 ZooKeeper 基本离不开 Watcher事件监听器机制。_ _破音非常有用的一个特性出小本本记好了,后面用到 ZooKeeper 基本离不开 Watcher事件监听器机制。_
### 3.6. 会话Session ### 3.6. 会话Session
@ -188,7 +188,7 @@ Session 有一个属性叫做:`sessionTimeout` `sessionTimeout` 代表会
为了保证高可用,最好是以集群形态来部署 ZooKeeper这样只要集群中大部分机器是可用的能够容忍一定的机器故障那么 ZooKeeper 本身仍然是可用的。通常 3 台服务器就可以构成一个 ZooKeeper 集群了。ZooKeeper 官方提供的架构图就是一个 ZooKeeper 集群整体对外提供服务。 为了保证高可用,最好是以集群形态来部署 ZooKeeper这样只要集群中大部分机器是可用的能够容忍一定的机器故障那么 ZooKeeper 本身仍然是可用的。通常 3 台服务器就可以构成一个 ZooKeeper 集群了。ZooKeeper 官方提供的架构图就是一个 ZooKeeper 集群整体对外提供服务。
![](images/zookeeper集群.png) ![](./images/zookeeper集群.png)
上图中每一个 Server 代表一个安装 ZooKeeper 服务的服务器。组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。集群间通过 ZAB 协议ZooKeeper Atomic Broadcast来保持数据的一致性。 上图中每一个 Server 代表一个安装 ZooKeeper 服务的服务器。组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。集群间通过 ZAB 协议ZooKeeper Atomic Broadcast来保持数据的一致性。
@ -198,7 +198,7 @@ Session 有一个属性叫做:`sessionTimeout` `sessionTimeout` 代表会
但是,在 ZooKeeper 中没有选择传统的 Master/Slave 概念,而是引入了 Leader、Follower 和 Observer 三种角色。如下图所示 但是,在 ZooKeeper 中没有选择传统的 Master/Slave 概念,而是引入了 Leader、Follower 和 Observer 三种角色。如下图所示
![](images/zookeeper集群中的角色.png) ![](./images/zookeeper集群中的角色.png)
ZooKeeper 集群中的所有机器通过一个 **Leader 选举过程** 来选定一台称为 “**Leader**” 的机器Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,**Follower** 和 **Observer** 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。 ZooKeeper 集群中的所有机器通过一个 **Leader 选举过程** 来选定一台称为 “**Leader**” 的机器Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,**Follower** 和 **Observer** 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。

View File

@ -316,7 +316,7 @@
首先肯定是如何获取锁,因为创建节点的唯一性,我们可以让多个客户端同时创建一个临时节点,**创建成功的就说明获取到了锁** 。然后没有获取到锁的客户端也像上面选主的非主节点创建一个 `watcher` 进行节点状态的监听,如果这个互斥锁被释放了(可能获取锁的客户端宕机了,或者那个客户端主动释放了锁)可以调用回调函数重新获得锁。 首先肯定是如何获取锁,因为创建节点的唯一性,我们可以让多个客户端同时创建一个临时节点,**创建成功的就说明获取到了锁** 。然后没有获取到锁的客户端也像上面选主的非主节点创建一个 `watcher` 进行节点状态的监听,如果这个互斥锁被释放了(可能获取锁的客户端宕机了,或者那个客户端主动释放了锁)可以调用回调函数重新获得锁。
> `zk` 中不需要向 `redis` 那样考虑锁得不到释放的问题了,因为当客户端挂了,节点也挂了,锁也释放了。是不是很简 > `zk` 中不需要向 `redis` 那样考虑锁得不到释放的问题了,因为当客户端挂了,节点也挂了,锁也释放了。是不是很简
那能不能使用 `zookeeper` 同时实现 **共享锁和独占锁** 呢?答案是可以的,不过稍微有点复杂而已。 那能不能使用 `zookeeper` 同时实现 **共享锁和独占锁** 呢?答案是可以的,不过稍微有点复杂而已。

View File

@ -13,12 +13,11 @@ category: 分布式
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231206733.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231206733.png)
专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入我的[知识星球](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) 如果你需要专属面试小册/一对一交流/简历修改/专属求职指南/学习打卡,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) (一定要确定自己真的需要再加入,一定要看完详细介绍之后再加我)
星球目前的定价为 **159/年**,即将调整为 **199/年**。如果的认可 JavaGuide相信我并且需要星球提供的专属服务那欢迎你加入我的星球。你可以添加我的私人微信领取星球专属优惠券限时 **100/年** 加入。一定要备注“**星球优惠券**”! 星球目前的定价为 **159/年**,即将调整为 **199/年**。如果的认可 JavaGuide相信我并且需要星球提供的专属服务那欢迎你加入我的星球。你可以添加我的私人微信领取星球专属优惠券限时 **100/年** 加入。一定要备注“**星球优惠券**”!
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231926486.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231926486.png)
**用心做内容,割韭菜。加油!!!** **用心做内容,真心希望帮助到你,拒绝知识付费割韭菜。加油!!!**
知识星球详细介绍请看(一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我):[https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc)。

View File

@ -71,7 +71,7 @@
Dubbo 目前已经有接近 34.4 k 的 Star 。 Dubbo 目前已经有接近 34.4 k 的 Star 。
**2020 年度 OSC 中国开源项目** 评选活动中Dubbo 位列开发框架和基础组件类项目的第7名。比几年前来说,热度和排名有所下降。 **2020 年度 OSC 中国开源项目** 评选活动中Dubbo 位列开发框架和基础组件类项目的第7名。比几年前来说,热度和排名有所下降。
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/%E6%BA%90%E7%A0%81/dubbo/image-20210107153159545.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/%E6%BA%90%E7%A0%81/dubbo/image-20210107153159545.png)

View File

@ -21,7 +21,7 @@ tag:
解决方案大致可以理解成:先在所有的将军中选出一个大将军,用来做出所有的决定。 解决方案大致可以理解成:先在所有的将军中选出一个大将军,用来做出所有的决定。
举例如下:假如现在一共有 3 个将军 AB 和 C每个讲解都有一个随机时间的倒计时器,倒计时一结束,这个将军就把自己当成大将军候选人,然后派信使传递选举投票的信息给将军 B 和 C如果将军 B 和 C 还没有把自己当作候选人(自己的倒计时还没有结束),并且没有把选举票投给其他人,它们就会把票投给将军 A信使回到将军 A 时,将军 A 知道自己收到了足够的票数,成为大将军。在有了大将军之后,是否需要进攻就由大将军 A 决定,然后再去派信使通知另外两个将军,自己已经成为了大将军。如果一段时间还没收到将军 B 和 C 的回复(信使可能会被暗示),那就再重派一个信使,直到收到回复。 举例如下:假如现在一共有 3 个将军 AB 和 C每个将军都有一个随机时间的倒计时器,倒计时一结束,这个将军就把自己当成大将军候选人,然后派信使传递选举投票的信息给将军 B 和 C如果将军 B 和 C 还没有把自己当作候选人(自己的倒计时还没有结束),并且没有把选举票投给其他人,它们就会把票投给将军 A信使回到将军 A 时,将军 A 知道自己收到了足够的票数,成为大将军。在有了大将军之后,是否需要进攻就由大将军 A 决定,然后再去派信使通知另外两个将军,自己已经成为了大将军。如果一段时间还没收到将军 B 和 C 的回复(信使可能会被暗示),那就再重派一个信使,直到收到回复。
### 1.2 共识算法 ### 1.2 共识算法

View File

@ -5,7 +5,7 @@
- **备份** 将系统所产生的的所有重要数据多备份几份。 - **备份** 将系统所产生的的所有重要数据多备份几份。
- **容灾** 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。 - **容灾** 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。
**异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者为灾害。 **异地多活** 描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者为灾害。
相关阅读: 相关阅读:

View File

@ -10,14 +10,13 @@
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231206733.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231206733.png)
专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入我的[知识星球](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) 如果你需要专属面试小册/一对一交流/简历修改/专属求职指南/学习打卡,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) (一定要确定自己真的需要再加入,一定要看完详细介绍之后再加我)
星球目前的定价为 **159/年**,即将调整为 **199/年**。如果的认可 JavaGuide相信我并且需要星球提供的专属服务那欢迎你加入我的星球。你可以添加我的私人微信领取星球专属优惠券限时 **100/年** 加入。一定要备注“**星球优惠券**”! 星球目前的定价为 **159/年**,即将调整为 **199/年**。如果的认可 JavaGuide相信我并且需要星球提供的专属服务那欢迎你加入我的星球。你可以添加我的私人微信领取星球专属优惠券限时 **100/年** 加入。一定要备注“**星球优惠券**”!
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231926486.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231926486.png)
**用心做内容,不割韭菜。加油!!!** **用心做内容,真心希望帮助到你,拒绝知识付费割韭菜。加油!!!**
知识星球详细介绍请看(一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我):[https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc)。

View File

@ -1,4 +1,7 @@
# 超时&重试机制 ---
title: 超时&重试机制
category: 高可用
---
**一旦用户的请求超过某个时间得不到响应就结束此次请求并抛出异常。** 如果不进行超时设置可能会导致请求响应速度慢,甚至导致请求堆积进而让系统无法在处理请求。 **一旦用户的请求超过某个时间得不到响应就结束此次请求并抛出异常。** 如果不进行超时设置可能会导致请求响应速度慢,甚至导致请求堆积进而让系统无法在处理请求。

View File

@ -376,7 +376,7 @@ emmm就两个字—— **幂等** 。在编程中一个*幂等* 操作的特
上面的同步刷盘和异步刷盘是在单个结点层面的,而同步复制和异步复制主要是指的 `Borker` 主从模式下,主节点返回消息给客户端的时候是否需要同步从节点。 上面的同步刷盘和异步刷盘是在单个结点层面的,而同步复制和异步复制主要是指的 `Borker` 主从模式下,主节点返回消息给客户端的时候是否需要同步从节点。
- 同步复制: 也叫 “同步双写”,也就是说,**只有消息同步双写到主从点上时才返回写入成功** 。 - 同步复制: 也叫 “同步双写”,也就是说,**只有消息同步双写到主从点上时才返回写入成功** 。
- 异步复制: **消息写入主节点之后就直接返回写入成功** - 异步复制: **消息写入主节点之后就直接返回写入成功**
然而,很多事情是没有完美的方案的,就比如我们进行消息写入的节点越多就更能保证消息的可靠性,但是随之的性能也会下降,所以需要程序员根据特定业务场景去选择适应的主从复制方案。 然而,很多事情是没有完美的方案的,就比如我们进行消息写入的节点越多就更能保证消息的可靠性,但是随之的性能也会下降,所以需要程序员根据特定业务场景去选择适应的主从复制方案。
@ -427,7 +427,7 @@ emmm是不是有一点复杂🤣看英文图片和英文文档的时候就
首先,在最上面的那一块就是我刚刚讲的你现在可以直接 **把 `ConsumerQueue` 理解为 `Queue`** 首先,在最上面的那一块就是我刚刚讲的你现在可以直接 **把 `ConsumerQueue` 理解为 `Queue`**
在图中最左边说明了 <font color = red>红色方块 </font> 代表被写入的消息,虚线方块代表等待被写入的。左边的生产者发送消息会指定 `Topic``QueueId` 和具体消息内容,而在 `Broker` 中管你是哪门子消息,他直接 **全部顺序存储到了 CommitLog**。而根据生产者指定的 `Topic``QueueId` 将这条消息本身在 `CommitLog` 的偏移(offset)消息本身大小和tag的hash值存入对应的 `ConsumeQueue` 索引文件中。而在每个队列中都保存了 `ConsumeOffset` 即每个消费者组的消费位置(我在架构那里提到了,忘了的同学可以回去看一下),而消费者拉取消息进行消费的时候只需要根据 `ConsumeOffset` 获取下一个未被消费的消息就行了。 在图中最左边说明了红色方块代表被写入的消息,虚线方块代表等待被写入的。左边的生产者发送消息会指定 `Topic``QueueId` 和具体消息内容,而在 `Broker` 中管你是哪门子消息,他直接 **全部顺序存储到了 CommitLog**。而根据生产者指定的 `Topic``QueueId` 将这条消息本身在 `CommitLog` 的偏移(offset)消息本身大小和tag的hash值存入对应的 `ConsumeQueue` 索引文件中。而在每个队列中都保存了 `ConsumeOffset` 即每个消费者组的消费位置(我在架构那里提到了,忘了的同学可以回去看一下),而消费者拉取消息进行消费的时候只需要根据 `ConsumeOffset` 获取下一个未被消费的消息就行了。
上述就是我对于整个消息存储架构的大概理解(这里不涉及到一些细节讨论,比如稀疏索引等等问题),希望对你有帮助。 上述就是我对于整个消息存储架构的大概理解(这里不涉及到一些细节讨论,比如稀疏索引等等问题),希望对你有帮助。

View File

@ -3,7 +3,7 @@ icon: creative
title: JavaGuideJava学习&&面试指南) title: JavaGuideJava学习&&面试指南)
--- ---
<div align="center"> <div style="text-align:center">
<p> <p>
<a href="https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc"> <a href="https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc">
<img src="../media/sponsor/xingqiu.png" style="margin: 0 auto; width: 850px;" /> <img src="../media/sponsor/xingqiu.png" style="margin: 0 auto; width: 850px;" />

View File

@ -67,7 +67,7 @@ REST 即 **REpresentational State Transfer** 的缩写。这个词组的翻译
举个例子。我们选中 `Controller` 中的某个请求对应的方法右击,你会发现多了几个可选项。当你选择`Generate & Copy Full URL`的话就可以把整个请求的路径直接复制下来。eg`http://localhost:9333/api/users?pageNum=1&pageSize=1` 举个例子。我们选中 `Controller` 中的某个请求对应的方法右击,你会发现多了几个可选项。当你选择`Generate & Copy Full URL`的话就可以把整个请求的路径直接复制下来。eg`http://localhost:9333/api/users?pageNum=1&pageSize=1`
![](pictures/RestfulToolkit3.png) ![](./pictures/RestfulToolkit3.png)
#### 将 Java 类转换为对应的 JSON 格式 #### 将 Java 类转换为对应的 JSON 格式
@ -75,7 +75,7 @@ REST 即 **REpresentational State Transfer** 的缩写。这个词组的翻译
我们选中的某个类对应的方法然后右击,你会发现多了几个可选项。 我们选中的某个类对应的方法然后右击,你会发现多了几个可选项。
![](pictures/RestfulToolkit4.png) ![](./pictures/RestfulToolkit4.png)
当我们选择`Convert to JSON`的话,你会得到如下 json 类型的数据: 当我们选择`Convert to JSON`的话,你会得到如下 json 类型的数据:

View File

@ -109,7 +109,7 @@ patchPluginXml {
## 03 手动创建 Action ## 03 手动创建 Action
我们可以把 Action 看作是 IDEA 提的事件响应处理器,通过 Action 我们可以自定义一些事件处理逻辑/动作。比如说你点击某个菜单的时候,我们进行一个展示对话框的操作。 我们可以把 Action 看作是 IDEA 提的事件响应处理器,通过 Action 我们可以自定义一些事件处理逻辑/动作。比如说你点击某个菜单的时候,我们进行一个展示对话框的操作。
**第一步,右键`java`目录并选择 new 一个 Action** **第一步,右键`java`目录并选择 new 一个 Action**
@ -130,9 +130,9 @@ patchPluginXml {
</actions> </actions>
``` ```
并且 `java` 目录下生成一个叫做 `HelloAction` 的类。并且,这个类继承了 `AnAction` ,并覆盖了 `actionPerformed()` 方法。这个 `actionPerformed` 方法就好比 JS 中的 `onClick` 方法,会在你点击的时候触发对应的动作。 并且 `java` 目录下生成一个叫做 `HelloAction` 的类。这个类继承了 `AnAction` ,并覆盖了 `actionPerformed()` 方法。这个 `actionPerformed` 方法就好比 JS 中的 `onClick` 方法,会在你点击的时候触发对应的动作。
我简单对`actionPerformed` 方法进行了修改,添加了一行代码。这行代码很简单,就是显示 1 个对话框并展示一些信息。 我简单对 `actionPerformed` 方法进行了修改,添加了一行代码。这行代码很简单,就是显示 1 个对话框并展示一些信息。
```java ```java
public class HelloAction extends AnAction { public class HelloAction extends AnAction {
@ -169,7 +169,7 @@ public class HelloAction extends AnAction {
## 04 验收成果 ## 04 验收成果
点击 `Gradle -> runIde` 就会启动一个默认了这个插件的 IDEA。然后你可以在这个 IDEA 上实际使用这个插件了。 点击 `Gradle -> Tasks -> intellij -> runIde` 就会启动一个默认了这个插件的 IDEA。然后你可以在这个 IDEA 上实际使用这个插件了。
![点击 runIde 就会启动一个默认了这个插件的 IDEA](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-11/image-20201118075912490.png) ![点击 runIde 就会启动一个默认了这个插件的 IDEA](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-11/image-20201118075912490.png)
@ -197,7 +197,27 @@ public class HelloAction extends AnAction {
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-11/image-20201118075803163.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-11/image-20201118075803163.png)
## 06 深入学习 ## 06 打包分发
插件写好之后,如果我们想把插件分享给小伙伴使用的话要怎么做呢。
### 首先,我们要打包插件
执行 Gradle -> Tasks -> intellij -> buildPlugin
执行完成后,项目中会生成一个 build 文件夹,点击进入后找到 distributions 文件夹,里面会出现一个 .zip 结尾的压缩包,里面打包了插件所需要的依赖、配置文件等。
### 其次,分发插件
打开 IDEA在 Settings -> Plugins -> 点击小齿轮后选择 Install Plugin From Disk
![](./pictures/install-plugin-from-disk.png)
### 最后,提交至官网
这步并不是必须的,如果你想把你的插件发布到官网上,别人直接可以在 [应用市场](https://plugins.jetbrains.com/) 中搜到你的插件的话可以做这步。
## 07 深入学习
如果你想要深入学习的 IDEA 插件的话,可以看一下官网文档:[https://jetbrains.org/intellij/sdk/docs/basics/basics.html ](https://jetbrains.org/intellij/sdk/docs/basics/basics.html "https://jetbrains.org/intellij/sdk/docs/basics/basics.html ") 。 如果你想要深入学习的 IDEA 插件的话,可以看一下官网文档:[https://jetbrains.org/intellij/sdk/docs/basics/basics.html ](https://jetbrains.org/intellij/sdk/docs/basics/basics.html "https://jetbrains.org/intellij/sdk/docs/basics/basics.html ") 。
@ -206,8 +226,74 @@ public class HelloAction extends AnAction {
- [8 条经验轻松上手 IDEA 插件开发](https://developer.aliyun.com/article/777850?spm=a2c6h.12873581.0.dArticle777850.118d6446r096V4&groupCode=alitech "8 条经验轻松上手 IDEA 插件开发") - [8 条经验轻松上手 IDEA 插件开发](https://developer.aliyun.com/article/777850?spm=a2c6h.12873581.0.dArticle777850.118d6446r096V4&groupCode=alitech "8 条经验轻松上手 IDEA 插件开发")
- [IDEA 插件开发入门教程](https://blog.xiaohansong.com/idea-plugin-development.html "IDEA 插件开发入门教程") - [IDEA 插件开发入门教程](https://blog.xiaohansong.com/idea-plugin-development.html "IDEA 插件开发入门教程")
## 07 后记 ## 08 后记
我们开发 IDEA 插件主要是为了让 IDEA 更加好用,比如有些框架使用之后可以减少重复代码的编写、有些主题类型的插件可以让你的 IDEA 更好看。 我们开发 IDEA 插件主要是为了让 IDEA 更加好用,比如有些框架使用之后可以减少重复代码的编写、有些主题类型的插件可以让你的 IDEA 更好看。
我这篇文章的这个案例说实话只是为了让大家简单入门一下 IDEA 开发,没有任何实际应用意义。**如果你想要开发一个不错的 IDEA 插件的话,还要充分发挥想象,利用 IDEA 插件平台的能力。** 我这篇文章的这个案例说实话只是为了让大家简单入门一下 IDEA 开发,没有任何实际应用意义。**如果你想要开发一个不错的 IDEA 插件的话,还要充分发挥想象,利用 IDEA 插件平台的能力。**
## 常见问题一JDK版本过低
创建好项目之后,运行 Gradle出现如下报错
```
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring root project 'string-template-error-scanner'.
> Could not resolve all artifacts for configuration ':classpath'.
> Could not resolve org.jetbrains.intellij.plugins:gradle-intellij-plugin:1.4.0.
Required by:
project : > org.jetbrains.intellij:org.jetbrains.intellij.gradle.plugin:1.4.0
> Unable to find a matching variant of org.jetbrains.intellij.plugins:gradle-intellij-plugin:1.4.0:
- Variant 'apiElements' capability org.jetbrains.intellij.plugins:gradle-intellij-plugin:1.4.0:
- Incompatible attributes:
- Required org.gradle.jvm.version '8' and found incompatible value '11'.
- Required org.gradle.usage 'java-runtime' and found incompatible value 'java-api'.
- Other attributes:
- Found org.gradle.category 'library' but wasn't required.
- Required org.gradle.dependency.bundling 'external' and found compatible value 'external'.
- Found org.gradle.jvm.environment 'standard-jvm' but wasn't required.
- Required org.gradle.libraryelements 'jar' and found compatible value 'jar'.
- Found org.gradle.status 'release' but wasn't required.
- Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
- Variant 'runtimeElements' capability org.jetbrains.intellij.plugins:gradle-intellij-plugin:1.4.0:
- Incompatible attribute:
- Required org.gradle.jvm.version '8' and found incompatible value '11'.
- Other attributes:
- Found org.gradle.category 'library' but wasn't required.
- Required org.gradle.dependency.bundling 'external' and found compatible value 'external'.
- Found org.gradle.jvm.environment 'standard-jvm' but wasn't required.
- Required org.gradle.libraryelements 'jar' and found compatible value 'jar'.
- Found org.gradle.status 'release' but wasn't required.
- Required org.gradle.usage 'java-runtime' and found compatible value 'java-runtime'.
- Found org.jetbrains.kotlin.platform.type 'jvm' but wasn't required.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 94ms
```
> 原因分析:一般情况下,我们都是使用 JDK8 进行开发,但是新版的 IDEA 插件的编译需要使用 JAVA11 版本以上,因此要把 JDK8 换成 JDK11。设置方法左上角点击 Settings -> Build, Execution, Deployment, Build Tools -> Gradle在下面找到 Gradle JVM: 改成 Java11 再次运行 Gradle 即可)
>
>
## 常见问题二:无法创建 org.jetbrains.intellij.utils.ArchiveUtils 的实例
```
Build file 'D:\project\string-template-error-scanner\build.gradle' line: 3
An exception occurred applying plugin request [id: 'org.jetbrains.intellij', version: '1.4.0']
> Failed to apply plugin [id 'org.jetbrains.intellij']
> Could not create an instance of type org.jetbrains.intellij.utils.ArchiveUtils.
> Could not generate a decorated class for type ArchiveUtils.
> org/gradle/api/file/ArchiveOperations
```
> 原因分析:这个问题我在 StackOverFlow、CSDN 等等网站搜了一大圈都从根源上找到怎么解决(知道的小伙伴可以编辑此页和我说一下~
>
> 最后通过修改 `build.gradle` 中 org.jetbrains.intellij 的版本解决的,我创建好项目之后版本是 1.4.0,换成 0.6.3,再重新运行一次 Gradle 就可以了

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -15,16 +15,13 @@ tag:
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231206733.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231206733.png)
专属面试小册/一对一交流/简历修改/专属求职指南,欢迎加入我的[知识星球](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) 如果你需要专属面试小册/一对一交流/简历修改/专属求职指南/学习打卡,不妨花 3 分钟左右看看星球的详细介绍: [JavaGuide 知识星球详细介绍](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc) (一定要确定自己真的需要再加入,一定要看完详细介绍之后再加我)
星球目前的定价为 **159/年**,即将调整为 **199/年**。如果的认可 JavaGuide相信我并且需要星球提供的专属服务那欢迎你加入我的星球。你可以添加我的私人微信领取星球专属优惠券限时 **100/年** 加入。一定要备注“**星球优惠券**”! 星球目前的定价为 **159/年**,即将调整为 **199/年**。如果的认可 JavaGuide相信我并且需要星球提供的专属服务那欢迎你加入我的星球。你可以添加我的私人微信领取星球专属优惠券限时 **100/年** 加入。一定要备注“**星球优惠券**”!
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231926486.png) ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/xingqiu/image-20220211231926486.png)
**用心做内容,不割韭菜。加油!!!** **用心做内容,真心希望帮助到你,拒绝知识付费割韭菜。加油!!!**
知识星球详细介绍请看(一定一定一定确定自己真的需要再加入,一定一定要看完详细介绍之后再加我):[https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc](https://www.yuque.com/docs/share/8a30ffb5-83f3-40f9-baf9-38de68b906dc)。

View File

@ -73,7 +73,7 @@ UNIX 系统下, IO 模型一共有 5 种: **同步阻塞 I/O**、**同步非
### NIO (Non-blocking/New I/O) ### NIO (Non-blocking/New I/O)
Java 中的 NIO 于 Java 1.4 中引入,对应 `java.nio` 包,提供了 `Channel` , `Selector``Buffer` 等抽象。NIO 中的 N 可以理解为 Non-blocking不单纯是 New。它支持面向缓冲的基于通道的 I/O 操作方法。 对于高负载、高并发的(网络)应用,应使用 NIO 。 Java 中的 NIO 于 Java 1.4 中引入,对应 `java.nio` 包,提供了 `Channel` , `Selector``Buffer` 等抽象。NIO 中的 N 可以理解为 Non-blocking不单纯是 New。它支持面向缓冲的,基于通道的 I/O 操作方法。 对于高负载、高并发的(网络)应用,应使用 NIO 。
Java 中的 NIO 可以看作是 **I/O 多路复用模型**。也有很多人认为Java 中的 NIO 属于同步非阻塞 IO 模型。 Java 中的 NIO 可以看作是 **I/O 多路复用模型**。也有很多人认为Java 中的 NIO 属于同步非阻塞 IO 模型。
@ -93,9 +93,9 @@ Java 中的 NIO 可以看作是 **I/O 多路复用模型**。也有很多人认
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/88ff862764024c3b8567367df11df6ab~tplv-k3u1fbpfcp-watermark.image) ![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/88ff862764024c3b8567367df11df6ab~tplv-k3u1fbpfcp-watermark.image)
IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间->用户空间)还是阻塞的。 IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间 -> 用户空间)还是阻塞的。
> 目前支持 IO 多路复用的系统调用,有 selectepoll 等等。select 系统调用,目前几乎在所有的操作系统上都有支持 > 目前支持 IO 多路复用的系统调用,有 selectepoll 等等。select 系统调用,目前几乎在所有的操作系统上都有支持
> >
> - **select 调用** :内核提供的系统调用,它支持一次查询多个系统调用的可用状态。几乎所有的操作系统都支持。 > - **select 调用** :内核提供的系统调用,它支持一次查询多个系统调用的可用状态。几乎所有的操作系统都支持。
> - **epoll 调用** linux 2.6 内核,属于 select 调用的增强版本,优化了 IO 的执行效率。 > - **epoll 调用** linux 2.6 内核,属于 select 调用的增强版本,优化了 IO 的执行效率。

View File

@ -105,11 +105,12 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有
相关阅读 👍:[《Differences Between Oracle JDK and OpenJDK》](https://www.baeldung.com/oracle-jdk-vs-openjdk) 相关阅读 👍:[《Differences Between Oracle JDK and OpenJDK》](https://www.baeldung.com/oracle-jdk-vs-openjdk)
### Java 和 C++的区别? ### Java 和 C++ 的区别?
我知道很多人没学过 C++,但是面试官就是没事喜欢拿咱们 Java 和 C++ 比呀!没办法!!!就算没学过 C++,也要记下来! 我知道很多人没学过 C++,但是面试官就是没事喜欢拿咱们 Java 和 C++ 比呀!没办法!!!就算没学过 C++,也要记下来。
虽然Java 和 C++ 都是面向对象的语言,都支持封装、继承和多态,但是,它们还是有挺多不相同的地方:
- 都是面向对象的语言,都支持封装、继承和多态
- Java 不提供指针来直接访问内存,程序内存更加安全 - Java 不提供指针来直接访问内存,程序内存更加安全
- Java 的类是单继承的C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。 - Java 的类是单继承的C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。
- Java 有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存。 - Java 有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存。
@ -120,90 +121,13 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有
### 字符型常量和字符串常量的区别? ### 字符型常量和字符串常量的区别?
1. **形式** : 字符常量是单引号引起的一个字符,字符串常量是双引号引起的 0 个或若干个字符 1. **形式** : 字符常量是单引号引起的一个字符,字符串常量是双引号引起的 0 个或若干个字符
2. **含义** : 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置) 2. **含义** : 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
3. **占内存大小** 字符常量只占 2 个字节; 字符串常量占若干个字节 (**注意: `char` 在 Java 中占两个字节**) 3. **占内存大小** 字符常量只占 2 个字节; 字符串常量占若干个字节
### 使用过可变长参数吗? (**注意: `char` 在 Java 中占两个字节**)
从 Java5 开始Java 支持定义可变长参数,所谓可变长参数就是允许在调用方法时传入不定长度的参数。就比如下面的这个 `printVariable` 方法就可以接受 0 个或者多个参数。 ### 注释有哪几种形式?
```java
public static void method1(String... args) {
//......
}
```
另外,可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数。
```java
public static void method2(String arg1, String... args) {
//......
}
```
**遇到方法重载的情况怎么办呢?会优先匹配固定参数还是可变参数的方法呢?**
答案是会优先匹配固定参数的方法,因为固定参数的方法匹配度更高。
我们通过下面这个例子来证明一下。
```java
/**
* 微信搜 JavaGuide 回复"面试突击"即可免费领取个人原创的 Java 面试手册
*
* @author Guide哥
* @date 2021/12/13 16:52
**/
public class VariableLengthArgument {
public static void printVariable(String... args) {
for (String s : args) {
System.out.println(s);
}
}
public static void printVariable(String arg1, String arg2) {
System.out.println(arg1 + arg2);
}
public static void main(String[] args) {
printVariable("a", "b");
printVariable("a", "b", "c", "d");
}
}
```
输出:
```
ab
a
b
c
d
```
另外Java 的可变参数编译后实际会被转换成一个数组,我们看编译后生成的 `class`文件就可以看出来了。
```java
public class VariableLengthArgument {
public static void printVariable(String... args) {
String[] var1 = args;
int var2 = args.length;
for(int var3 = 0; var3 < var2; ++var3) {
String s = var1[var3];
System.out.println(s);
}
}
// ......
}
```
### 注释有哪几种?注释越多越好吗?
Java 中的注释有三种: Java 中的注释有三种:
@ -238,12 +162,14 @@ Java 中的注释有三种:
### 标识符和关键字的区别是什么? ### 标识符和关键字的区别是什么?
在我们编写程序的时候,需要大量地为程序、类、变量、方法等取名字,于是就有了标识符简单来说标识符就是一个名字。但是有一些标识符Java 语言已经赋予了其特殊的含义,只能用于特定的地方,这些特殊的标识符就是关键字。因此,关键字是被赋予特殊含义的标识符。比如,在我们的日常生活中,如果我们想要开一家店,则要给这个店起一个名字,起的这个“名字”就叫标识符。但是我们店的名字不能叫“警察局”,因为“警察局”这个名字已经被赋予了特殊的含义,而“警察局”就是我们日常生活中的关键字 在我们编写程序的时候,需要大量地为程序、类、变量、方法等取名字,于是就有了 **标识符** 。简单来说, **标识符就是一个名字**
### Java 中有 `53` 个关键字: 有一些标识符Java 语言已经赋予了其特殊的含义,只能用于特定的地方,这些特殊的标识符就是 **关键字** 。简单来说,**关键字是被赋予特殊含义的标识**符 。比如,在我们的日常生活中,如果我们想要开一家店,则要给这个店起一个名字,起的这个“名字”就叫标识符。但是我们店的名字不能叫“警察局”,因为“警察局”这个名字已经被赋予了特殊的含义,而“警察局”就是我们日常生活中的关键字。
### Java 语言关键字有哪些?
| 分类 | 关键字 | | | | | | | | 分类 | 关键字 | | | | | | |
| :------------------- | -------- | ---------- | -------- | ------------ | ---------- | --------- | ------ | | :------------------- | -------- |-------- | -------- | -------- | --------| --------| -------- |
| 访问控制 | private | protected | public | | | | | | 访问控制 | private | protected | public | | | | |
| 类,方法和变量修饰符 | abstract | class | extends | final | implements | interface | native | | 类,方法和变量修饰符 | abstract | class | extends | final | implements | interface | native |
| | new | static | strictfp | synchronized | transient | volatile | enum | | | new | static | strictfp | synchronized | transient | volatile | enum |
@ -252,7 +178,7 @@ Java 中的注释有三种:
| 错误处理 | try | catch | throw | throws | finally | | | | 错误处理 | try | catch | throw | throws | finally | | |
| 包相关 | import | package | | | | | | | 包相关 | import | package | | | | | |
| 基本类型 | boolean | byte | char | double | float | int | long | | 基本类型 | boolean | byte | char | double | float | int | long |
| | short | null | true | false | | | | | | short | | | | | | |
| 变量引用 | super | this | void | | | | | | 变量引用 | super | this | void | | | | |
| 保留字 | goto | const | | | | | | | 保留字 | goto | const | | | | | |
@ -260,9 +186,14 @@ Java 中的注释有三种:
> >
> `default` 这个关键字很特殊,既属于程序控制,也属于类,方法和变量修饰符,还属于访问控制。 > `default` 这个关键字很特殊,既属于程序控制,也属于类,方法和变量修饰符,还属于访问控制。
> >
> - 在程序控制中,当在 `switch` 中匹配不到任何情况时,可以使用 `default` 来编写默认匹配的情况。在类,方法和变量修饰符中,从 JDK8 开始引入了默认方法,可以使用 `default` 关键字来定义一个方法的默认实现。 > - 在程序控制中,当在 `switch` 中匹配不到任何情况时,可以使用 `default` 来编写默认匹配的情况。
> - 在类,方法和变量修饰符中,从 JDK8 开始引入了默认方法,可以使用 `default` 关键字来定义一个方法的默认实现。
> - 在访问控制中,如果一个方法前没有任何修饰符,则默认会有一个修饰符 `default`,但是这个修饰符加上了就会报错。 > - 在访问控制中,如果一个方法前没有任何修饰符,则默认会有一个修饰符 `default`,但是这个修饰符加上了就会报错。
注意 ⚠️:虽然 `true`, `false`, 和 `null` 看起来像关键字但实际上他们是字面值,同时你也不可以作为标识符来使用。
官方文档:[https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html)
### 自增自减运算符 ### 自增自减运算符
在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1Java 提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)和自减运算符(--)。 在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1Java 提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)和自减运算符(--)。
@ -501,7 +432,7 @@ public class SuperSuperMan extends SuperMan {
> 因为 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。 > 因为 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。
**`equals()`** 不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。`equals()`方法存在于`Object`类中,而`Object`类是所有类的直接或间接父类。 **`equals()`** 不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。`equals()`方法存在于`Object`类中,而`Object`类是所有类的直接或间接父类,因此所有的类都有`equals()`方法
`Object``equals()` 方法: `Object``equals()` 方法:
@ -513,8 +444,8 @@ public boolean equals(Object obj) {
`equals()` 方法存在两种使用情况: `equals()` 方法存在两种使用情况:
- **类没有覆盖 `equals()`方法** :通过`equals()`比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是 `Object``equals()`方法。 - **类没有重写 `equals()`方法** :通过`equals()`比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是 `Object``equals()`方法。
- **类覆盖了 `equals()`方法** :一般我们都覆盖 `equals()`方法来比较两个对象中的属性是否相等;若它们的属性相等,则返回 true(即,认为这两个对象相等)。 - **类重写了 `equals()`方法** :一般我们都重写 `equals()`方法来比较两个对象中的属性是否相等;若它们的属性相等,则返回 true(即,认为这两个对象相等)。
举个例子(这里只是为了举例。实际上,你按照下面这种写法的话,像 IDEA 这种比较智能的 IDE 都会提示你将 `==` 换成 `equals()` 举个例子(这里只是为了举例。实际上,你按照下面这种写法的话,像 IDEA 这种比较智能的 IDE 都会提示你将 `==` 换成 `equals()`
@ -563,7 +494,7 @@ public boolean equals(Object anObject) {
面试官可能会问你:“你重写过 `hashCode()``equals()`么?为什么重写 `equals()` 时必须重写 `hashCode()` 方法?” 面试官可能会问你:“你重写过 `hashCode()``equals()`么?为什么重写 `equals()` 时必须重写 `hashCode()` 方法?”
一个非常基础的问题,面试中的重中之重,然而,很多求职者还是会不到点子上去。 一个非常基础的问题,面试中的重中之重,然而,很多求职者还是会回答不到点子上去。
#### hashCode() 有什么用? #### hashCode() 有什么用?
@ -583,7 +514,7 @@ public native int hashCode();
下面这段内容摘自我的 Java 启蒙书《Head First Java》: 下面这段内容摘自我的 Java 启蒙书《Head First Java》:
> 当你把对象加入 `HashSet` 时,`HashSet` 会先计算对象的 `hashCode` 值来判断对象加入的位置,同时也会与其他已经加入的对象的 `hashCode` 值作比较,如果没有相符的 `hashCode``HashSet` 会假设对象没有重复出现。但是如果发现有相同 `hashCode` 值的对象,这时会调用 `equals()` 方法来检查 `hashCode` 相等的对象是否真的相同。如果两者相同,`HashSet` 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 `equals` 的次数,相应就大大提高了执行速度。 > 当你把对象加入 `HashSet` 时,`HashSet` 会先计算对象的 `hashCode` 值来判断对象加入的位置,同时也会与其他已经加入的对象的 `hashCode` 值作比较,如果没有相符的 `hashCode``HashSet` 会假设对象没有重复出现。但是如果发现有相同 `hashCode` 值的对象,这时会调用 `equals()` 方法来检查 `hashCode` 相等的对象是否真的相同。如果两者相同,`HashSet` 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 `equals` 的次数,相应就大大提高了执行速度。
其实, `hashCode()``equals()`都是用于比较两个对象是否相等。 其实, `hashCode()``equals()`都是用于比较两个对象是否相等。
@ -604,7 +535,7 @@ public native int hashCode();
总结下来就是 总结下来就是
- 如果两个对象的`hashCode` 值相等,那这两个对象不一定相等(哈希碰撞)。 - 如果两个对象的`hashCode` 值相等,那这两个对象不一定相等(哈希碰撞)。
- 如果两个对象的`hashCode` 值相等并且`equals()`方法返回 `true`,我们才认为这两个对象相等。 - 如果两个对象的`hashCode` 值相等并且`equals()`方法返回 `true`,我们才认为这两个对象相等。
- 如果两个对象的`hashCode` 值不相等,我们就可以直接认为这两个对象不相等。 - 如果两个对象的`hashCode` 值不相等,我们就可以直接认为这两个对象不相等。
相信大家看了我前面对 `hashCode()``equals()` 的介绍之后,下面这个问题已经难不倒你们了。 相信大家看了我前面对 `hashCode()``equals()` 的介绍之后,下面这个问题已经难不倒你们了。
@ -624,6 +555,85 @@ public native int hashCode();
更多关于 `hashCode()``equals()` 的内容可以查看:[Java hashCode() 和 equals()的若干问题解答](https://www.cnblogs.com/skywang12345/p/3324958.html) 更多关于 `hashCode()``equals()` 的内容可以查看:[Java hashCode() 和 equals()的若干问题解答](https://www.cnblogs.com/skywang12345/p/3324958.html)
### 什么是可变长参数?
从 Java5 开始Java 支持定义可变长参数,所谓可变长参数就是允许在调用方法时传入不定长度的参数。就比如下面的这个 `printVariable` 方法就可以接受 0 个或者多个参数。
```java
public static void method1(String... args) {
//......
}
```
另外,可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数。
```java
public static void method2(String arg1, String... args) {
//......
}
```
**遇到方法重载的情况怎么办呢?会优先匹配固定参数还是可变参数的方法呢?**
答案是会优先匹配固定参数的方法,因为固定参数的方法匹配度更高。
我们通过下面这个例子来证明一下。
```java
/**
* 微信搜 JavaGuide 回复"面试突击"即可免费领取个人原创的 Java 面试手册
*
* @author Guide哥
* @date 2021/12/13 16:52
**/
public class VariableLengthArgument {
public static void printVariable(String... args) {
for (String s : args) {
System.out.println(s);
}
}
public static void printVariable(String arg1, String arg2) {
System.out.println(arg1 + arg2);
}
public static void main(String[] args) {
printVariable("a", "b");
printVariable("a", "b", "c", "d");
}
}
```
输出:
```
ab
a
b
c
d
```
另外Java 的可变参数编译后实际会被转换成一个数组,我们看编译后生成的 `class`文件就可以看出来了。
```java
public class VariableLengthArgument {
public static void printVariable(String... args) {
String[] var1 = args;
int var2 = args.length;
for(int var3 = 0; var3 < var2; ++var3) {
String s = var1[var3];
System.out.println(s);
}
}
// ......
}
```
## 基本数据类型 ## 基本数据类型
### Java 中的几种基本数据类型了解么? ### Java 中的几种基本数据类型了解么?
@ -739,7 +749,7 @@ Double i4 = 1.2;
System.out.println(i3 == i4);// 输出 false System.out.println(i3 == i4);// 输出 false
``` ```
下面我们来看一下问题。下面的代码的输出结果是 `true` 还是 `flase` 呢? 下面我们来看一下问题。下面的代码的输出结果是 `true` 还是 `false` 呢?
```java ```java
Integer i1 = 40; Integer i1 = 40;

View File

@ -36,9 +36,11 @@ new 运算符new 创建对象实例(对象实例在堆内存中),对象
- 对象的相等一般比较的是内存中存放的内容是否相等。 - 对象的相等一般比较的是内存中存放的内容是否相等。
- 引用相等一般比较的是他们指向的内存地址是否相等。 - 引用相等一般比较的是他们指向的内存地址是否相等。
### 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? ### 一个类的构造方法的作用是什么?
构造方法主要作用是完成对类对象的初始化工作。 构造方法是一种特殊的方法,主要作用是完成对象的初始化工作。
### 如果一个类没有声明构造方法,该程序能正确执行吗?
如果一个类没有声明构造方法也可以执行因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。如果我们自己添加了类的构造方法无论是否有参Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直在不知不觉地使用构造方法,这也是为什么我们在创建对象的时候后面要加一个括号(因为要调用无参的构造方法)。如果我们重载了有参的构造方法,记得都要把无参的构造方法也写出来(无论是否用到),因为这可以帮助我们在创建对象的时候少踩坑。 如果一个类没有声明构造方法也可以执行因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。如果我们自己添加了类的构造方法无论是否有参Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直在不知不觉地使用构造方法,这也是为什么我们在创建对象的时候后面要加一个括号(因为要调用无参的构造方法)。如果我们重载了有参的构造方法,记得都要把无参的构造方法也写出来(无论是否用到),因为这可以帮助我们在创建对象的时候少踩坑。
@ -106,6 +108,20 @@ public class Student {
- 多态不能调用“只在子类存在但在父类不存在”的方法; - 多态不能调用“只在子类存在但在父类不存在”的方法;
- 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。 - 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。
### 接口和抽象类有什么共同点和区别?
**共同点**
- 都不能被实例化。
- 都可以包含抽象方法。
- 都可以有默认实现的方法Java 8 可以用 `default` 关键在接口中定义默认方法)。
**区别**
- 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是所属关系(比如说我们抽象了一个发送短信的抽象类,)。
- 一个类只能继承一个类,但是可以实现多个接口。
- 接口中的成员变量只能是 `public static final` 类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 default可在子类中被重新定义也可被重新赋值。
### 深拷贝和浅拷贝区别了解吗?什么是引用拷贝? ### 深拷贝和浅拷贝区别了解吗?什么是引用拷贝?
关于深拷贝和浅拷贝区别,我这里先给结论: 关于深拷贝和浅拷贝区别,我这里先给结论:

View File

@ -271,7 +271,7 @@ Finally
```java ```java
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(f(2));; System.out.println(f(2));
} }
public static int f(int value) { public static int f(int value) {

View File

@ -63,7 +63,7 @@ public class DebugInvocationHandler implements InvocationHandler {
如果我们动态获取到这些信息,我们需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。Java 提供了四种方式获取 Class 对象: 如果我们动态获取到这些信息,我们需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。Java 提供了四种方式获取 Class 对象:
**1.知道具体类的情况下可以使用:** **1. 知道具体类的情况下可以使用:**
```java ```java
Class alunbarClass = TargetObject.class; Class alunbarClass = TargetObject.class;
@ -71,30 +71,30 @@ Class alunbarClass = TargetObject.class;
但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化 但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化
**2.通过 `Class.forName()`传入类的路径获取:** **2. 通过 `Class.forName()`传入类的路径获取:**
```java ```java
Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject"); Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
``` ```
**3.通过对象实例`instance.getClass()`获取:** **3. 通过对象实例`instance.getClass()`获取:**
```java ```java
TargetObject o = new TargetObject(); TargetObject o = new TargetObject();
Class alunbarClass2 = o.getClass(); Class alunbarClass2 = o.getClass();
``` ```
**4.通过类加载器`xxxClassLoader.loadClass()`传入类路径获取:** **4. 通过类加载器`xxxClassLoader.loadClass()`传入类路径获取:**
```java ```java
Class clazz = ClassLoader.loadClass("cn.javaguide.TargetObject"); Class clazz = ClassLoader.loadClass("cn.javaguide.TargetObject");
``` ```
通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态块和静态对象不会得到执行 通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行
### 反射的一些基本操作 ### 反射的一些基本操作
1.创建一个我们要使用反射操作的类 `TargetObject` 1. 创建一个我们要使用反射操作的类 `TargetObject`
```java ```java
package cn.javaguide; package cn.javaguide;
@ -116,7 +116,7 @@ public class TargetObject {
} }
``` ```
2.使用反射操作这个类的方法以及参数 2. 使用反射操作这个类的方法以及参数
```java ```java
package cn.javaguide; package cn.javaguide;
@ -128,35 +128,38 @@ import java.lang.reflect.Method;
public class Main { public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
/** /**
* 获取TargetObject类的Class对象并且创建TargetObject类实例 * 获取 TargetObject 类的 Class 对象并且创建 TargetObject 类实例
*/ */
Class<?> tagetClass = Class.forName("cn.javaguide.TargetObject"); Class<?> tagetClass = Class.forName("cn.javaguide.TargetObject");
TargetObject targetObject = (TargetObject) tagetClass.newInstance(); TargetObject targetObject = (TargetObject) tagetClass.newInstance();
/** /**
* 获取所有类中所有定义的方法 * 获取 TargetObject 类中定义的所有方法
*/ */
Method[] methods = tagetClass.getDeclaredMethods(); Method[] methods = targetClass.getDeclaredMethods();
for (Method method : methods) { for (Method method : methods) {
System.out.println(method.getName()); System.out.println(method.getName());
} }
/** /**
* 获取指定方法并调用 * 获取指定方法并调用
*/ */
Method publicMethod = tagetClass.getDeclaredMethod("publicMethod", Method publicMethod = targetClass.getDeclaredMethod("publicMethod",
String.class); String.class);
publicMethod.invoke(targetObject, "JavaGuide"); publicMethod.invoke(targetObject, "JavaGuide");
/** /**
* 获取指定参数并对参数进行修改 * 获取指定参数并对参数进行修改
*/ */
Field field = tagetClass.getDeclaredField("value"); Field field = targetClass.getDeclaredField("value");
//为了对类中的参数进行修改我们取消安全检查 //为了对类中的参数进行修改我们取消安全检查
field.setAccessible(true); field.setAccessible(true);
field.set(targetObject, "JavaGuide"); field.set(targetObject, "JavaGuide");
/** /**
* 调用 private 方法 * 调用 private 方法
*/ */
Method privateMethod = tagetClass.getDeclaredMethod("privateMethod"); Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
//为了调用private方法我们取消安全检查 //为了调用private方法我们取消安全检查
privateMethod.setAccessible(true); privateMethod.setAccessible(true);
privateMethod.invoke(targetObject); privateMethod.invoke(targetObject);
@ -177,6 +180,6 @@ value is JavaGuide
**注意** : 有读者提到上面代码运行会抛出 `ClassNotFoundException` 异常,具体原因是你没有下面把这段代码的包名替换成自己创建的 `TargetObject` 所在的包 。 **注意** : 有读者提到上面代码运行会抛出 `ClassNotFoundException` 异常,具体原因是你没有下面把这段代码的包名替换成自己创建的 `TargetObject` 所在的包 。
```java ```java
Class<?> tagetClass = Class.forName("cn.javaguide.TargetObject"); Class<?> targetClass = Class.forName("cn.javaguide.TargetObject");
``` ```

View File

@ -123,7 +123,7 @@ public interface RandomAccess {
### 说一说 ArrayList 的扩容机制吧 ### 说一说 ArrayList 的扩容机制吧
详见笔主的这篇文章:[通过源码一步一步分析 ArrayList 扩容机制](https://snailclimb.gitee.io/javaguide/#/docs/java/collection/arraylist-source-code?id=_2-arraylist-%e6%a0%b8%e5%bf%83%e6%ba%90%e7%a0%81%e8%a7%a3%e8%af%bb) 详见笔主的这篇文章:[ArrayList 扩容机制分析](https://javaguide.cn/java/collection/arraylist-source-code/#_2-arraylist-核心源码解读)
## Collection 子接口之 Set ## Collection 子接口之 Set

View File

@ -213,13 +213,13 @@ static int hash(int h) {
所谓 **“拉链法”** 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。 所谓 **“拉链法”** 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
![jdk1.8之前的内部结构-HashMap](images/jdk1.8之前的内部结构-HashMap.png) ![jdk1.8之前的内部结构-HashMap](./images/jdk1.8之前的内部结构-HashMap.png)
#### JDK1.8 之后 #### JDK1.8 之后
相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8将链表转换成红黑树前会判断如果当前数组的长度小于 64那么会选择先进行数组扩容而不是转换为红黑树将链表转化为红黑树以减少搜索时间。 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8将链表转换成红黑树前会判断如果当前数组的长度小于 64那么会选择先进行数组扩容而不是转换为红黑树将链表转化为红黑树以减少搜索时间。
![jdk1.8之后的内部结构-HashMap](images/jdk1.8之后的内部结构-HashMap.png) ![jdk1.8之后的内部结构-HashMap](./images/jdk1.8之后的内部结构-HashMap.png)
> TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。 > TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。

View File

@ -393,11 +393,11 @@ ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
比如我们在同一个线程中声明了两个 `ThreadLocal` 对象的话, `Thread`内部都是使用仅有的那个`ThreadLocalMap` 存放数据的,`ThreadLocalMap`的 key 就是 `ThreadLocal`对象value 就是 `ThreadLocal` 对象调用`set`方法设置的值。 比如我们在同一个线程中声明了两个 `ThreadLocal` 对象的话, `Thread`内部都是使用仅有的那个`ThreadLocalMap` 存放数据的,`ThreadLocalMap`的 key 就是 `ThreadLocal`对象value 就是 `ThreadLocal` 对象调用`set`方法设置的值。
![ThreadLocal数据结构](images/threadlocal数据结构.png) ![ThreadLocal数据结构](./images/threadlocal数据结构.png)
`ThreadLocalMap``ThreadLocal`的静态内部类。 `ThreadLocalMap``ThreadLocal`的静态内部类。
![ThreadLocal内部类](images/ThreadLocal内部类.png) ![ThreadLocal内部类](./images/ThreadLocal内部类.png)
### 3.4. ThreadLocal 内存泄露问题 ### 3.4. ThreadLocal 内存泄露问题
@ -427,7 +427,7 @@ static class Entry extends WeakReference<ThreadLocal<?>> {
> **池化技术想必大家已经屡见不鲜了线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。** > **池化技术想必大家已经屡见不鲜了线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。**
**线程池**提供了一种限制和管理资源(包括执行一个任务)。 每个**线程池**还维护一些基本统计信息,例如已完成任务的数量。 **线程池**提供了一种限制和管理资源(包括执行一个任务)的方式。 每个**线程池**还维护一些基本统计信息,例如已完成任务的数量。
这里借用《Java 并发编程的艺术》提到的来说一下**使用线程池的好处** 这里借用《Java 并发编程的艺术》提到的来说一下**使用线程池的好处**
@ -761,7 +761,7 @@ public void execute(Runnable command) {
通过下图可以更好的对上面这 3 步做一个展示,下图是我为了省事直接从网上找到,原地址不明。 通过下图可以更好的对上面这 3 步做一个展示,下图是我为了省事直接从网上找到,原地址不明。
![图解线程池实现原理](images/java-thread-pool-summary/图解线程池实现原理.png) ![图解线程池实现原理](./images/java-thread-pool-summary/图解线程池实现原理.png)
现在,让我们在回到 4.6 节我们写的 Demo 现在是不是很容易就可以搞懂它的原理了呢? 现在,让我们在回到 4.6 节我们写的 Demo 现在是不是很容易就可以搞懂它的原理了呢?
@ -1042,7 +1042,7 @@ try {
System.out.println("all done. "); System.out.println("all done. ");
``` ```
上面的代码还可以续优化,当任务过多的时候,把每一个 task 都列出来不太现实,可以考虑通过循环来添加任务。 上面的代码还可以续优化,当任务过多的时候,把每一个 task 都列出来不太现实,可以考虑通过循环来添加任务。
```java ```java
//文件夹位置 //文件夹位置

Some files were not shown because too many files have changed in this diff Show More