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

Merge pull request #7 from Snailclimb/master

更新
This commit is contained in:
RyzeZhao 2019-11-07 16:44:12 +08:00 committed by GitHub
commit 06b5f186fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1068 additions and 137 deletions

View File

@ -1,10 +1,6 @@
点击关注[公众号](#公众号)及时获取笔主最新更新文章并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
作者的其他开源项目推荐:
1. [springboot-guide](https://github.com/Snailclimb/springboot-guide) : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维护)。
2. [programmer-advancement](https://github.com/Snailclimb/programmer-advancement) : 我觉得技术人员应该有的一些好习惯!
3. [spring-security-jwt-guide](https://github.com/Snailclimb/spring-security-jwt-guide) :从零入门 Spring Security With JWT含权限验证后端部分代码。
**[推荐一下阿里云双11的活动云服务器1折起仅86元/年,限量抢购!](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** 仅限新人老用户可以考虑使用家人或者朋友账号购买推荐799/3年 2核4G 这个性价比和适用面更广。不懂怎么使用云服务器的朋友可以看这篇[阿里云服务器使用经验](docs/tools/阿里云服务器使用经验.md))。
<p align="center">
<a href="https://github.com/Snailclimb/JavaGuide" target="_blank">
@ -23,7 +19,7 @@
<h3 align="center">Sponsor</h3>
<p align="center">
<a href="https://study.163.com/topics/JavaGuide/" >
<a href="https://url.163.com/hXm" >
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/WechatIMG1.png"width="" style="margin: 0 auto;"/>
</a >
</p>
@ -39,7 +35,7 @@
- [JVM](#jvm)
- [I/O](#io)
- [Java 8](#java-8)
- [编程规范](#编程规范)
- [优雅 Java 代码必备实践(Java编程规范)](#优雅-java-代码必备实践java编程规范)
- [网络](#网络)
- [操作系统](#操作系统)
- [Linux相关](#linux相关)
@ -51,14 +47,15 @@
- [Redis](#redis)
- [系统设计](#系统设计)
- [常用框架(Spring/SpringBoot、Zookeeper ... )](#常用框架)
- [数据通信(消息队列、Dubbo ... )](#数据通信)
- [权限认证](#权限认证)
- [设计模式(工厂模式、单例模式 ... )](#设计模式)
- [数据通信(消息队列、Dubbo ... )](#数据通信)
- [网站架构](#网站架构)
- [架构](#架构)
- [面试指南](#面试指南)
- [备战面试](#备战面试)
- [常见面试题总结](#常见面试题总结)
- [面经](#面经)
- [Java学习常见问题汇总](#java学习常见问题汇总)
- [工具](#工具)
- [Git](#git)
- [Docker](#Docker)
@ -113,9 +110,9 @@
* [Java 8 学习资源推荐](docs/java/What's%20New%20in%20JDK8/Java8教程推荐.md)
* [Java8 forEach 指南](docs/java/What's%20New%20in%20JDK8/Java8foreach指南.md)
### 编程规范
### 优雅 Java 代码必备实践(Java编程规范)
- [Java 编程规范](docs/java/Java编程规范.md)
* [Java 编程规范以及优雅Java代码实践总结](docs/java/Java编程规范.md)
## 网络
@ -161,7 +158,8 @@
* [Redis 总结](docs/database/Redis/Redis.md)
* [Redlock分布式锁](docs/database/Redis/Redlock分布式锁.md)
* [如何做可靠的分布式锁Redlock真的可行么](docs/database/Redis/如何做可靠的分布式锁Redlock真的可行么.md)
* [如何做可靠的分布式锁Redlock真的可行么]()
* [几种常见的 Redis 集群以及使用场景](docs/database/Redis/redis集群以及应用场景.md)
## 系统设计
@ -181,6 +179,23 @@
- [ZooKeeper 相关概念总结](docs/system-design/framework/ZooKeeper.md)
- [ZooKeeper 数据模型和常见命令](docs/system-design/framework/ZooKeeper数据模型和常见命令.md)
### 数据通信
- [数据通信(RESTful、RPC、消息队列)相关知识点总结](docs/system-design/data-communication/summary.md)
- [服务之间的调用为啥不直接用 HTTP 而用 RPC](docs/system-design/data-communication/why-use-rpc.md)
#### Dubbo
- [Dubbo 总结:关于 Dubbo 的重要知识点](docs/system-design/data-communication/dubbo.md)
#### 消息中间件
- [消息队列总结](docs/system-design/data-communication/message-queue.md)
- [RabbitMQ 入门](docs/system-design/data-communication/rabbitmq.md)
- [RocketMQ的几个简单问题与答案](docs/system-design/data-communication/RocketMQ-Questions.md)
- [Kafka入门看这一篇就够了](docs/system-design/data-communication/Kafka入门看这一篇就够了.md)
- [Kafka系统设计开篇-面试看这篇就够了](docs/system-design/data-communication/Kafka系统设计开篇-面试看这篇就够了.md)
### 权限认证
- **[权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](docs/system-design/authority-certification/basis-of-authority-certification.md)**
@ -191,21 +206,11 @@
- [设计模式系列文章](docs/system-design/设计模式.md)
### 数据通信
- [数据通信(RESTful、RPC、消息队列)相关知识点总结](docs/system-design/data-communication/summary.md)
- [Dubbo 总结:关于 Dubbo 的重要知识点](docs/system-design/data-communication/dubbo.md)
- [消息队列总结](docs/system-design/data-communication/message-queue.md)
- [RabbitMQ 入门](docs/system-design/data-communication/rabbitmq.md)
- [RocketMQ的几个简单问题与答案](docs/system-design/data-communication/RocketMQ-Questions.md)
- [Kafka入门看这一篇就够了](docs/system-design/data-communication/Kafka入门看这一篇就够了.md)
- [Kafka系统设计开篇-面试看这篇就够了](docs/system-design/data-communication/Kafka系统设计开篇-面试看这篇就够了.md)
### 网站架构
### 架构
- [一文读懂分布式应该学什么](docs/system-design/website-architecture/分布式.md)
- [8 张图读懂大型网站技术架构](docs/system-design/website-architecture/8%20张图读懂大型网站技术架构.md)
- [【面试精选】关于大型网站系统架构你不得不懂的10个问题](docs/system-design/website-architecture/【面试精选】关于大型网站系统架构你不得不懂的10个问题.md)
- [【面试精选】关于大型网站系统架构你不得不懂的10个问题](docs/system-design/website-architecture/关于大型网站系统架构你不得不懂的10个问题.md)
## 面试指南
@ -232,6 +237,11 @@
- [蚂蚁金服2019实习生面经总结(已拿口头offer)](docs/essential-content-for-interview/BATJrealInterviewExperience/蚂蚁金服实习生面经总结(已拿口头offer).md)
- [2019年蚂蚁金服、头条、拼多多的面试总结](docs/essential-content-for-interview/BATJrealInterviewExperience/2019alipay-pinduoduo-toutiao.md)
## Java学习常见问题汇总
- [Java学习路线和方法推荐](docs/questions/java-learning-path-and-methods.md)
- [Java培训四个月能学会吗](docs/questions/java-training-4-month.md)
## 工具
### Git
@ -240,9 +250,13 @@
### Docker
* [Docker 入门](docs/tools/Docker.md)
* [Docker 基本概念解读](docs/tools/Docker.md)
* [一文搞懂 Docker 镜像的常用操作!](docs/tools/Docker-Image.md)
### 其他
- [阿里云服务器使用经验](docs/tools/阿里云服务器使用经验.md)
## 资源
### 书单
@ -267,7 +281,7 @@
## 说明
### 介绍
### JavaGuide介绍
* **对于 Java 初学者来说:** 本文档倾向于给你提供一个比较详细的学习路径让你对于Java整体的知识体系有一个初步认识。另外本文的一些文章
也是你学习和复习 Java 知识不错的实践;
@ -277,6 +291,12 @@ Markdown 格式参考:[Github Markdown格式](https://guides.github.com/featur
利用 docsify 生成文档部署在 Github pages: [docsify 官网介绍](https://docsify.js.org/#/)
### 作者的其他开源项目推荐
1. [springboot-guide](https://github.com/Snailclimb/springboot-guide) : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维护)。
2. [programmer-advancement](https://github.com/Snailclimb/programmer-advancement) : 我觉得技术人员应该有的一些好习惯!
3. [spring-security-jwt-guide](https://github.com/Snailclimb/spring-security-jwt-guide) :从零入门 Spring Security With JWT含权限验证后端部分代码。
### 关于转载
如果你需要转载本仓库的一些文章到自己的博客的话,记得注明原文地址就可以了。
@ -310,6 +330,10 @@ Markdown 格式参考:[Github Markdown格式](https://guides.github.com/featur
<a href="https://github.com/fanchenggang">
<img src="https://avatars2.githubusercontent.com/u/8225921?s=460&v=4" width="45px">
</a>
<a href="https://github.com/Rustin-Liu">
<img src="https://avatars2.githubusercontent.com/u/29879298?s=400&v=4" width="45px">
</a>
<a href="https://github.com/ipofss">
<img src="https://avatars1.githubusercontent.com/u/5917359?s=460&v=4" width="45px"></a>
<a href="https://github.com/Gene1994">

View File

@ -84,6 +84,7 @@
- [《设计模式 : 可复用面向对象软件的基础》](https://book.douban.com/subject/1052241/) (推荐,豆瓣评分 9.1):设计模式的经典!
- [《Head First 设计模式(中文版)》](https://book.douban.com/subject/2243615/) (推荐,豆瓣评分 9.2):相当赞的一本设计模式入门书籍。用实际的编程案例讲解算法设计中会遇到的各种问题和需求变更(对的,连需求变更都考虑到了!),并以此逐步推导出良好的设计模式解决办法。
- [《大话设计模式》](https://book.douban.com/subject/2334288/) (推荐,豆瓣评分 8.3本书通篇都是以情景对话的形式用多个小故事或编程示例来组织讲解GOF(即《设计模式 : 可复用面向对象软件的基础》这本书)),但是不像《设计模式 : 可复用面向对象软件的基础》难懂。但是设计模式只看书是不够的,还是需要在实际项目中运用,结合[设计模式](docs/system-design/设计模式.md)更佳!
### 常用框架

View File

@ -0,0 +1,149 @@
相关阅读:
- [史上最全Redis高可用技术解决方案大全](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484850&idx=1&sn=3238360bfa8105cf758dcf7354af2814&chksm=cea24a79f9d5c36fb2399aafa91d7fb2699b5006d8d037fe8aaf2e5577ff20ae322868b04a87&token=1082669959&lang=zh_CN&scene=21#wechat_redirect)
# Redis 集群以及应用
## 集群
### 主从复制
#### 主从链(拓扑结构)
![主从](https://user-images.githubusercontent.com/26766909/67539461-d1a26c00-f714-11e9-81ae-61fa89faf156.png)
![主从](https://user-images.githubusercontent.com/26766909/67539485-e0891e80-f714-11e9-8980-d253239fcd8b.png)
#### 复制模式
- 全量复制:master 全部同步到 slave
- 部分复制:slave 数据丢失进行备份
#### 问题点
- 同步故障
- 复制数据延迟(不一致)
- 读取过期数据(Slave 不能删除数据)
- 从节点故障
- 主节点故障
- 配置不一致
- maxmemory 不一致:丢失数据
- 优化参数不一致:内存不一致.
- 避免全量复制
- 选择小主节点(分片)、低峰期间操作.
- 如果节点运行 id 不匹配(如主节点重启、运行 id 发送变化),此时要执行全量复制,应该配合哨兵和集群解决.
- 主从复制挤压缓冲区不足产生的问题(网络中断,部分复制无法满足),可增大复制缓冲区( rel_backlog_size 参数).
- 复制风暴
### 哨兵机制
#### 拓扑图
![image](https://user-images.githubusercontent.com/26766909/67539495-f0086780-f714-11e9-9eab-c11a163ac6c0.png)
#### 节点下线
- 客观下线
- 所有 Sentinel 节点对 Redis 节点失败要达成共识,即超过 quorum 个统一.
- 主管下线
- 即 Sentinel 节点对 Redis 节点失败的偏见,超出超时时间认为 Master 已经宕机.
#### leader选举
- 选举出一个 Sentinel 作为 Leader:集群中至少有三个 Sentinel 节点,但只有其中一个节点可完成故障转移.通过以下命令可以进行失败判定或领导者选举.
- 选举流程
1. 每个主观下线的 Sentinel 节点向其他 Sentinel 节点发送命令,要求设置它为领导者.
1. 收到命令的 Sentinel 节点如果没有同意通过其他 Sentinel 节点发送的命令,则同意该请求,否则拒绝.
1. 如果该 Sentinel 节点发现自己的票数已经超过 Sentinel 集合半数且超过 quorum,则它成为领导者.
1. 如果此过程有多个 Sentinel 节点成为领导者,则等待一段时间再重新进行选举.
#### 故障转移
- 转移流程
1. Sentinel 选出一个合适的 Slave 作为新的 Master(slaveof no one 命令).
1. 向其余 Slave 发出通知,让它们成为新 Master 的 Slave( parallel-syncs 参数).
1. 等待旧 Master 复活,并使之称为新 Master 的 Slave.
1. 向客户端通知 Master 变化.
- 从 Slave 中选择新 Master 节点的规则(slave 升级成 master 之后)
1. 选择 slave-priority 最高的节点.
1. 选择复制偏移量最大的节点(同步数据最多).
1. 选择 runId 最小的节点.
#### 读写分离
#### 定时任务
- 每 1s 每个 Sentinel 对其他 Sentinel 和 Redis 执行 ping,进行心跳检测.
- 每 2s 每个 Sentinel 通过 Master 的 Channel 交换信息(pub - sub).
- 每 10s 每个 Sentinel 对 Master 和 Slave 执行 info,目的是发现 Slave 节点、确定主从关系.
### 分布式集群(Cluster)
#### 拓扑图
![image](https://user-images.githubusercontent.com/26766909/67539510-f8f93900-f714-11e9-9d8d-08afdecff95a.png)
#### 通讯
##### 集中式
> 将集群元数据(节点信息、故障等等)几种存储在某个节点上.
- 优势
1. 元数据的更新读取具有很强的时效性,元数据修改立即更新
- 劣势
1. 数据集中存储
##### Gossip
![image](https://user-images.githubusercontent.com/26766909/67539546-16c69e00-f715-11e9-9891-1e81b6af624c.png)
- [Gossip 协议](https://www.jianshu.com/p/8279d6fd65bb)
#### 寻址分片
##### hash取模
- hash(key)%机器数量
- 问题
1. 机器宕机,造成数据丢失,数据读取失败
1. 伸缩性
##### 一致性hash
- ![image](https://user-images.githubusercontent.com/26766909/67539595-352c9980-f715-11e9-8e4a-9d9c04027785.png)
- 问题
1. 一致性哈希算法在节点太少时,容易因为节点分布不均匀而造成缓存热点的问题。
- 解决方案
- 可以通过引入虚拟节点机制解决:即对每一个节点计算多个 hash每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布负载均衡。
##### hash槽
- CRC16(key)%16384
-
![image](https://user-images.githubusercontent.com/26766909/67539610-3fe72e80-f715-11e9-8e0d-ea58bc965795.png)
## 使用场景
### 热点数据
### 会话维持 session
### 分布式锁 SETNX
### 表缓存
### 消息队列 list
### 计数器 string
## 缓存设计
### 更新策略
- LRU、LFU、FIFO 算法自动清除:一致性最差,维护成本低.
- 超时自动清除(key expire):一致性较差,维护成本低.
- 主动更新:代码层面控制生命周期,一致性最好,维护成本高.
### 更新一致性
- 读请求:先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应.
- 写请求:先删除缓存,然后再更新数据库(避免大量地写、却又不经常读的数据导致缓存频繁更新).
### 缓存粒度
- 通用性:全量属性更好.
- 占用空间:部分属性更好.
- 代码维护成本.
### 缓存穿透
> 当大量的请求无命中缓存、直接请求到后端数据库(业务代码的 bug、或恶意攻击),同时后端数据库也没有查询到相应的记录、无法添加缓存.
这种状态会一直维持,流量一直打到存储层上,无法利用缓存、还会给存储层带来巨大压力.
>
#### 解决方案
1. 请求无法命中缓存、同时数据库记录为空时在缓存添加该 key 的空对象(设置过期时间),缺点是可能会在缓存中添加大量的空值键(比如遭到恶意攻击或爬虫),而且缓存层和存储层数据短期内不一致;
1. 使用布隆过滤器在缓存层前拦截非法请求、自动为空值添加黑名单(同时可能要为误判的记录添加白名单).但需要考虑布隆过滤器的维护(离线生成/ 实时生成).
### 缓存雪崩
> 缓存崩溃时请求会直接落到数据库上,很可能由于无法承受大量的并发请求而崩溃,此时如果只重启数据库,或因为缓存重启后没有数据,新的流量进来很快又会把数据库击倒
>
#### 出现后应对
- 事前:Redis 高可用,主从 + 哨兵,Redis Cluster,避免全盘崩溃.
- 事中:本地 ehcache 缓存 + hystrix 限流 & 降级,避免数据库承受太多压力.
- 事后:Redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据.
#### 请求过程
1. 用户请求先访问本地缓存,无命中后再访问 Redis,如果本地缓存和 Redis 都没有再查数据库,并把数据添加到本地缓存和 Redis
1. 由于设置了限流,一段时间范围内超出的请求走降级处理(返回默认值,或给出友情提示).

View File

@ -0,0 +1,21 @@
- 公众号和Github待发文章[数据库:数据库连接池原理详解与自定义连接池实现](https://www.fangzhipeng.com/javainterview/2019/07/15/mysql-connector-pool.html)
- [基于JDBC的数据库连接池技术研究与应用](http://blog.itpub.net/9403012/viewspace-111794/)
- [数据库连接池技术详解](https://juejin.im/post/5b7944c6e51d4538c86cf195)
数据库连接本质就是一个 socket 的连接。数据库服务端还要维护一些缓存和用户权限信息之类的 所以占用了一些内存
连接池是维护的数据库连接的缓存,以便将来需要对数据库的请求时可以重用这些连接。为每个用户打开和维护数据库连接,尤其是对动态数据库驱动的网站应用程序的请求,既昂贵又浪费资源。**在连接池中,创建连接后,将其放置在池中,并再次使用它,因此不必建立新的连接。如果使用了所有连接,则会建立一个新连接并将其添加到池中。**连接池还减少了用户必须等待建立与数据库的连接的时间。
操作过数据库的朋友应该都知道数据库连接池这个概念,它几乎每天都在和我们打交道,但是你真的了解 **数据库连接池** 吗?
### 没有数据库连接池之前
我相信你一定听过这样一句话:**Java语言中JDBCJava DataBase Connection是应用程序与数据库沟通的桥梁**。

View File

@ -78,7 +78,7 @@ num2 = 20
![example 2](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-27/3825204.jpg)
array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。
array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。
**通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。**

View File

@ -450,7 +450,7 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
### 1.3 介绍一下你知道哪几种消息队列,该如何选择呢?
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafaka |
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
| :---------------------- | -----------------------------------------------------------: | -----------------------------------------------------------: | -----------------------------------------------------------: | -----------------------------------------------------------: |
| 单机吞吐量 | 万级吞吐量比RocketMQ和Kafka要低了一个数量级 | 万级吞吐量比RocketMQ和Kafka要低了一个数量级 | 10万级RocketMQ也是可以支撑高吞吐的一种MQ | 10万级别这是kafka最大的优点就是吞吐量高。一般配合大数据类的系统来进行实时数据计算、日志采集等场景 |
| topic数量对吞吐量的影响 | | | topic可以达到几百几千个的级别吞吐量会有较小幅度的下降这是RocketMQ的一大优势在同等机器下可以支撑大量的topic | topic从几十个到几百个的时候吞吐量会大幅度下降。所以在同等机器下kafka尽量保证topic数量不要过多。如果要支撑大规模topic需要增加更多的机器资源 |

View File

@ -417,9 +417,9 @@ final关键字主要用在三个地方变量、方法、类。
### Throwable类常用方法
- **public string getMessage()**:返回异常发生时的详细信息
- **public string toString()**:返回异常发生时的简要描述
- **public string getLocalizedMessage()**:返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法可以声称本地化信息。如果子类没有覆盖该方法则该方法返回的信息与getMessage返回的结果相同
- **public string getMessage()**:返回异常发生时的简要描述
- **public string toString()**:返回异常发生时的详细信息
- **public string getLocalizedMessage()**:返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法可以生成本地化信息。如果子类没有覆盖该方法则该方法返回的信息与getMessage返回的结果相同
- **public void printStackTrace()**:在控制台上打印Throwable对象封装的异常信息
### 异常处理总结

View File

@ -1,4 +1,4 @@
根据各位建议加上了这部分内容,我暂时只是给出了两个资源,后续可能会对重要的点进行总结,然后更新在这里,如果你总结过这类东西,欢迎与我联系!
讲真的,下面推荐的文章或者资源建议阅读 3 遍以上。
### 团队
@ -8,3 +8,23 @@
### 个人
- **程序员你为什么这么累:** <https://xwjie.github.io/rule/>
### 如何写出优雅的 Java 代码
1. 使用 IntelliJ IDEA 作为您的集成开发环境 (IDE)
1. 使用 JDK 8 或更高版本
1. 使用 Maven/Gradle
1. 使用 Lombok
1. 编写单元测试
1. 重构:常见,但也很慢
1. 注意代码规范
1. 定期联络客户,以获取他们的反馈
上述建议的详细内容:[八点建议助您写出优雅的Java代码](docs/八点建议助您写出优雅的Java代码.md)。
更多代码优化相关内容推荐:
- [业务复杂=if else刚来的大神竟然用策略+工厂彻底干掉了他们!](https://juejin.im/post/5dad23685188251d2c4ea2b6)
- [一些不错的 Java 实践推荐阅读3遍以上](http://lrwinx.github.io/2017/03/04/%E7%BB%86%E6%80%9D%E6%9E%81%E6%81%90-%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BC%9A%E5%86%99java%E5%90%97/)
- [[解锁新姿势] 兄dei你代码需要优化了](https://juejin.im/post/5dafbc02e51d4524a0060bdd)
- [消灭 Java 代码的“坏味道”](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485599&idx=1&sn=d83ff4e6b1ee951a0a33508a10980ea3&chksm=cea24754f9d5ce426d18b435a8c373ddc580c06c7d6a45cc51377361729c31c7301f1bbc3b78&token=1328169465&lang=zh_CN#rd)

View File

@ -95,7 +95,7 @@ uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueIns
2. 初始化 uniqueInstance
3. 将 uniqueInstance 指向分配的内存地址
但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance但此时 uniqueInstance 还未被初始化。
但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance但此时 uniqueInstance 还未被初始化。
使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。

View File

@ -39,7 +39,7 @@
- [LocalDate\(本地日期\)](#localdate本地日期)
- [LocalDateTime\(本地日期时间\)](#localdatetime本地日期时间)
- [Annotations\(注解\)](#annotations注解)
- [Whete to go from here?](#whete-to-go-from-here)
- [Where to go from here?](#where-to-go-from-here)
<!-- /MarkdownTOC -->

View File

@ -118,7 +118,7 @@ protected Class<?> loadClass(String name, boolean resolve)
### 如果我们不想用双亲委派模型怎么办?
为了避免双亲委托机制,我们可以自己定义一个类加载器,然后重 `loadClass()` 即可。
为了避免双亲委托机制,我们可以自己定义一个类加载器,然后重 `loadClass()` 即可。
## 自定义类加载器

View File

@ -331,20 +331,29 @@ passwd命令用于设置用户的认证信息包括用户密码、密码过
### 4.8 其他常用命令
- **`pwd`** 显示当前所在位置
- `sudo + 其他命令`:以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行。
- **`grep 要搜索的字符串 要搜索的文件 --color`** 搜索命令,--color代表高亮显示
- **`ps -ef`/`ps -aux`** 这两个命令都是查看当前系统正在运行进程,两者的区别是展示格式不同。如果想要查看特定的进程可以使用这样的格式:**`ps aux|grep redis`** 查看包括redis字符串的进程也可使用 `pgrep redis -a`
注意如果直接用psProcess Status命令会显示所有进程的状态通常结合grep命令查看某进程的状态。
- **`kill -9 进程的pid`** 杀死进程(-9 表示强制终止。)
先用ps查找进程然后用kill杀掉
- **网络通信命令:**
- 查看当前系统的网卡信息ifconfig
- 查看与某台机器的连接情况ping
- 查看当前系统的端口使用netstat -an
- **net-tools 和 iproute2 **
`net-tools`起源于BSD的TCP/IP工具箱后来成为老版本Linux内核中配置网络功能的工具。但自2001年起Linux社区已经对其停止维护。同时一些Linux发行版比如Arch Linux和CentOS/RHEL 7则已经完全抛弃了net-tools只支持`iproute2`。linux ip命令类似于ifconfig但功能更强大旨在替代它。更多详情请阅读[如何在Linux中使用IP命令和示例](https://linoxide.com/linux-command/use-ip-command-linux)
- **`shutdown`** `shutdown -h now` 指定现在立即关机;`shutdown +5 "System will shutdown after 5 minutes"`指定5分钟后关机同时送出警告信息给登入用户。
- **`reboot`** **`reboot`** 重开机。**`reboot -w`** 做个重开机的模拟(只有纪录并不会真的重开机)。
## 公众号

View File

@ -0,0 +1,182 @@
如遇链接无法打开,建议使用 https://github.com/Snailclimb/JavaGuide/blob/master/docs/questions/java-learning-path-and-methods.md 这个链接进行阅读。
到目前为止,我觉得不管是在公众号后台、知乎还是微信上面我被问的做多的就是:“大佬,有没有 Java 学习路线和方法”。所以,这部分单独就自己的学习经历来说点自己的看法。
## 前言
大一的时候,我仅仅接触过 C 语言,对 C 语言的掌握程度仅仅是可以完成老师布置的课后习题。那时候我的主要的精力都放在了参加各种课外活动,跟着一个很不错的社团尝试了很多我之前从未尝试过的事情:露营、户外烧烤、公交车演讲、环跑古城墙、徒步旅行、异地求生、圣诞节卖苹果等等。
到了大二我才接触到 HTML、CSS、JS、Java、Linux、PHP 这些名词。最开始接触 Java 的时候因为工作的需要我选择的安卓方向,我自己是在学习了大概 3 个月的安卓方向的知识后才转向 Java 后台方向的。最开始自己学习的时候,走了一些弯路,但是总体路线相对来说还是没问题的。我读的第一本 Java Web 方向的书籍是《Java Web 整合开发王者归来》,这本书我现在已经不推荐别人看了,一是内容太冗杂,二是年代比较久远导致很多东西在现在都不适用了。
很多人在学完 Java 基础之后,不知道后面该如何进行下一步地进行学习,或者不知道如何去学习。如何系统地学习 Java 一直是困扰着很多新手或者期待在 Java 方向进阶的小伙伴的一个问题。我也在知乎上回答了好几个类似的问题,我觉得既然很多人都需要这方面的指导,那我就写一篇自己对于如何系统学习 Java 后端的看法。刚好关注公众号的很多朋友都是学 Java 不太久的,希望这篇文章对学习 Java 的朋友能有一点启示作用。
由于我个人能力有限,下面的学习路线以及方法推荐一定还有很多欠缺的地方。欢迎有想法的朋友在评论区说一下自己的看法。本文比较适合刚入门或者想打好 Java 基础的朋友,比较基础。
## 学习路线以及方法推荐
**下面的学习路线以及方法是笔主根据个人学习经历总结改进后得出,我相信照着这条学习路线来你的学习效率会非常高。**
学习某个知识点的过程中如果不知道看什么书的话,可以查看这篇文章 [Java 学习必备书籍推荐终极版!](https://github.com/Snailclimb/JavaGuide/blob/master/docs/data/java-recommended-books.md)。
另外,很重要的一点:**建议使用 Intellij IDEA 进行编码,可以单独抽点时间学习 Intellij IDEA 的使用。**
**下面提到的一些视频,[公众号](#公众号 "公众号")后台回复关键“1”即可获取**
### step 1:Java 基础
**《Java 核心技术卷 1/2》** 和 **《Head First Java》** 这两本书在我看来都是入门 Java 的很不错的书籍 (**《Java 核心技术卷 1/2》** 知识点更全,我更推荐这本书),我倒是觉得 **《Java 编程思想》** 有点属于新手劝退书的意思,慎看,建议有点基础后再看。你也可以边看视频边看书学习(黑马、尚硅谷、慕课网的视频都还行)。对于 Java8 新特性的东西,我建议你基础学好之后可以看一下,暂时看不太明白也没关系,后面抽时间再回过头来看。
看完之后,你可以用自己学的东西实现一个简单的 Java 程序,也可以尝试用 Java 解决一些编程问题,以此来将自己学到的东西付诸于实践。
**记得多总结!打好基础!把自己重要的东西都记录下来。** API 文档放在自己可以看到的地方,以备自己可以随时查阅。为了能让自己写出更优秀的代码,**《Effective Java》**、**《重构》** 这两本书没事也可以看看。
学习完之后可以看一下下面这几篇文章,检查一下自己的学习情况:
- **[Java 基础知识回顾](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md)**
- **[Java 基础知识疑难点/易错点](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java%E7%96%91%E9%9A%BE%E7%82%B9.md)**
- **[一些重要的 Java 程序设计题](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E9%A2%98.md)**
检测一下自己的掌握情况,这 34 个问题都时 Java 中比较重要的知识点,最重要的是在 Java 后端面试中的出场率非常高。
### step 2:多线程的简单使用
多线程这部分内容可能会比较难以理解和上手,前期可以先简单地了解一下基础,到了后面有精力和能力后再回来仔细看。推荐 **《Java 并发编程之美》** 或者 **《实战 Java 高并发程序设计》** 这两本书。我目前也在重构一份我之前写的多线程学习指南,后面会更新在公众号里面。
学习完多线程之后可以通过下面这些问题检测自己是否掌握。
**Java 多线程知识基础:**
1. 什么是线程和进程?
2. 请简要描述线程与进程的关系,区别及优缺点?
3. 说说并发与并行的区别?
4. 为什么要使用多线程呢?
5. 使用多线程可能带来什么问题?
6. 说说线程的生命周期和状态?
7. 什么是上下文切换?
8. 什么是线程死锁?如何避免死锁?
9. 说说 sleep() 方法和 wait() 方法区别和共同点?
10. 为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
**Java 多线程知识进阶:**
1. synchronized 关键字:① 说一说自己对于 synchronized 关键字的了解;② 说说自己是怎么使用 synchronized 关键字,在项目中用到了吗;③ 讲一下 synchronized 关键字的底层原理;④ 说说 JDK1.6 之后的 synchronized 关键字底层做了哪些优化,可以详细介绍一下这些优化吗;⑤ 谈谈 synchronized 和 ReentrantLock 的区别。
2. volatile 关键字: ① 讲一下 Java 内存模型;② 说说 synchronized 关键字和 volatile 关键字的区别。
3. ThreadLocal① 简介;② 原理;③ 内存泄露问题。
4. 线程池:① 为什么要用线程池?;② 实现 Runnable 接口和 Callable 接口的区别;③ 执行 execute() 方法和 submit() 方法的区别是什么呢?;④ 如何创建线程池。
5. Atomic 原子类: ① 介绍一下 Atomic 原子类;② JUC 包中的原子类是哪 4 类?;③ 讲讲 AtomicInteger 的使用;④ 能不能给我简单介绍一下 AtomicInteger 类的原理。
6. AQS :① 简介;② 原理;③ AQS 常用组件。
另外,推荐看一下下面这几篇文章:
- **[Java 并发基础常见面试题总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md)**
- **[Java 并发进阶常见面试题总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md)**
- [并发容器总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Multithread/%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8%E6%80%BB%E7%BB%93.md)
- [乐观锁与悲观锁](https://github.com/Snailclimb/JavaGuide/blob/master/docs/essential-content-for-interview/%E9%9D%A2%E8%AF%95%E5%BF%85%E5%A4%87%E4%B9%8B%E4%B9%90%E8%A7%82%E9%94%81%E4%B8%8E%E6%82%B2%E8%A7%82%E9%94%81.md)
- [JUC 中的 Atomic 原子类总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Multithread/Atomic.md)
- [AQS 原理以及 AQS 同步组件总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Multithread/AQS.md)
### step 3(可选):操作系统与计算机网络
操作系统这方面我觉得掌握操作系统的基础知识和 Linux 的常用命令就行以及一些重要概念就行了。
关于操作系统的话,我没有什么操作系统方面的书籍可以推荐,因为我自己也没认真看过几本。因为操作系统比较枯燥的原因,我建议这部分看先看视频学可能会比较好一点。我推荐一个 Github 上开源的哈工大《操作系统》课程给大家吧地址https://github.com/hoverwinter/HIT-OSLab 。
另外,对于 Linux 我们要掌握基本的使用就需要对一些常用命令非常熟悉比如:目录切换命令、目录操作命令、文件的操作命令、压缩或者解压文件的命令等等。推荐一个 Github 上学习 Linux 的开源文档:[《Java 程序员眼中的 Linux》](https://github.com/judasn/Linux-Tutorial "《Java 程序员眼中的 Linux》")
计算机网络方面的学习,我觉得掌握基本的知识就行了,不需要太深究,一般面试对这方面要求也不高,毕竟不是专门做网络的。推荐 **《网络是怎样连接的》** 、**《图解 HTTP》** 这两本书来看,这两本书都属于比较有趣易懂的类型,也适合没有基础的人来看。
### step 4(可选):数据结构与算法
如果你想进入大厂的话,我推荐你在学习完 Java 基础或者多线程之后,就开始每天抽出一点时间来学习算法和数据结构。为了提高自己的编程能力,你也可以坚持刷 **[Leetcode](https://leetcode-cn.com "Leetcode")**。就目前国内外的大厂面试来说,刷 Leetcode 可以说已经成了不得不走的一条路。
对于想要入门算法和数据结构的朋友,建议看这两本书 **《算法图解》** 和 **《大话数据结构》**,这两本书虽然算不上很经典的书籍,但是比较有趣,对于刚入门算法和数据结构的朋友非常友好。**《算法导论》** 非常经典,但是对于刚入门的就不那么友好了。
另外,还有一本非常赞的算法书推荐给各位,这本书的名字就叫 **《算法》**,书中的代码都是用 Java 语言编写。这本书的优点太多太多比如它的讲解基础而全面、对阅读者比较友好等等。我觉得这本书唯一的缺点就是太厚了 (小声 BB可能和作者讲解某些知识点的时候有点啰嗦有关)。除了这本书之外,**《剑指 offer》** 、**《编程珠玑》** 、**《编程之美》** 这三本书都被很多大佬推荐过了,对于算法面试非常有帮助。**《算法之美》** 这本书也非常不错,非常适合闲暇的时候看。
### step 5:前端知识
这一步主要是学习前端基础 (HTML、CSS、JavaScript),当然 BootStrap、Layui 等等比较简单的前端框架你也可以了解一下。网上有很多这方面资源我只推荐一个大部分初学这些知识都会看的网站http://www.w3school.com.cn/ ,这个网站用来回顾知识也很不错 。推荐先把 HTML、CSS、JS 的基础知识过一遍,然后通过一个实际的前端项目来巩固。
现在都是前后端分离,就目前来看大部分项目都优先选择 React、Angular、Vue 这些厉害的框架来开发。如果你想往全栈方向发展的话(笔主目前的方向,我用 React 在公司做过两个小型项目),建议先把 JS 基础打好,然后再选择 React、Angular、Vue 其中的一个来认真学习一下。国内使用 Vue 比较多一点,国外一般用的是 React 和 Angular。
### step 5:MySQL
学习 MySQL 的基本使用基本的增删改查SQL 命令,索引、存储过程这些都学一下吧!推荐书籍 **《SQL 基础教程(第 2 版)》**(入门级)、**《高性能 MySQL : 第 3 版》**(进阶)、**《MySQL 必知必会》**。
下面这些 MySQL 相关的文章强烈推荐你看看:
- **[【推荐】MySQL/数据库 知识点总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/MySQL.md)**
- **[阿里巴巴开发手册数据库部分的一些最佳实践](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E9%83%A8%E5%88%86%E7%9A%84%E4%B8%80%E4%BA%9B%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.md)**
- **[一千行 MySQL 学习笔记](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/%E4%B8%80%E5%8D%83%E8%A1%8CMySQL%E5%91%BD%E4%BB%A4.md)**
- [MySQL 高性能优化规范建议](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/MySQL%E9%AB%98%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E8%A7%84%E8%8C%83%E5%BB%BA%E8%AE%AE.md)
- [数据库索引总结](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/MySQL%20Index.md)
- [事务隔离级别(图文详解)](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB(%E5%9B%BE%E6%96%87%E8%AF%A6%E8%A7%A3).md)
- [一条 SQL 语句在 MySQL 中如何执行的](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/%E4%B8%80%E6%9D%A1sql%E8%AF%AD%E5%8F%A5%E5%9C%A8mysql%E4%B8%AD%E5%A6%82%E4%BD%95%E6%89%A7%E8%A1%8C%E7%9A%84.md)
### step 6:常用工具
1. **Maven** :建议学习常用框架之前可以提前花半天时间学习一下**Maven**的使用。(到处找 Jar 包,下载 Jar 包是真的麻烦费事,使用 Maven 可以为你省很多事情)。
2. **Git** :基本的 Git 技能也是必备的,试着在学习的过程中将自己的代码托管在 Github 上。([Git 入门](https://github.com/Snailclimb/JavaGuide/blob/master/docs/tools/Git.md)
3. **Docker** :学着用 Docker 安装学习中需要用到的软件比如 MySQL ,这样方便很多,可以为你节省不少时间。([Docker 入门](https://github.com/Snailclimb/JavaGuide/blob/master/docs/tools/Docker.md)
### step 7:常用框架
学习 Struts2(可不用学)、**Spring**、**SpringMVC**、**Hibernate**、**Mybatis**、**shiro** 等框架的使用, (可选) 熟悉 **Spring 原理**(大厂面试必备),然后很有必要学习一下 **SpringBoot** **学好 SpringBoot 真的很重要**。很多公司对于应届生都是直接上手 **SpringBoot**,不过如果时间允许的话,我还是推荐你把 **Spring**、**SpringMVC** 提前学一下。
关于 SpringBoot ,推荐看一下笔主开源的 [Spring Boot 教程](https://github.com/Snailclimb/springboot-guide "Spring Boot 教程") SpringBoot 核心知识点总结。 基于 Spring Boot 2.19+)。
**Spring 真的很重要!** 一定要搞懂 AOP 和 IOC 这两个概念。Spring 中 bean 的作用域与生命周期、SpringMVC 工作原理详解等等知识点都是非常重要的,一定要搞懂。
推荐看文档+视频结合的方式,中途配合实战来学习,学习期间可以多看看 JavaGuide 对于[常用框架的总结](https://github.com/Snailclimb/JavaGuide#%E5%B8%B8%E7%94%A8%E6%A1%86%E6%9E%B6 "常用框架的总结")。
**另外,都 2019 年了,咱千万不要再学 JSP 了好不?**
### step 8:高性能网站架构
学习 **Dubbo、Zookeeper**、常见的**消息队列**(比如**ActiveMq、RabbitMQ**)、**Redis** 、**Elasticsearch** 的使用。
我当时学习这些东西的时候是通过黑马视频最后一个分布式项目来学的,我的这种方式也是很多人普遍采用和接受的方式。我觉得应该是掌握这些知识点比较好的一种方式了,另外,**推荐边看视频边自己做,遇到不懂的知识点要及时查阅网上博客和相关书籍,这样学习效果更好。**
**一定要学会拓展知识,养成自主学习的意识。** 黑马项目对这些知识点的介绍都比较蜻蜓点水。
### step 9:其他
可以再回来看一下多线程方面的知识,还可以利用业余时间学习一下 **[NIO](https://github.com/Snailclimb/JavaGuide#io "NIO")** 和 **Netty** ,这样简历上也可以多点东西。如果想去大厂,**[JVM](https://github.com/Snailclimb/JavaGuide#jvm "JVM")** 的一些知识也是必学的(**Java 内存区域、虚拟机垃圾算法、虚拟垃圾收集器、JVM 内存管理**)推荐《深入理解 Java 虚拟机JVM 高级特性与最佳实践(最新第二版》和《实战 Java 虚拟机》,如果嫌看书麻烦的话,你也可以看我整理的文档。
另外,现在微服务特别火,很多公司在面试也明确要求需要微服务方面的知识。如果有精力的话可以去学一下 SpringCloud 生态系统微服务方面的东西。
## 总结
我上面主要概括一下每一步要学习的内容,对学习规划有一个建议。知道要学什么之后,如何去学呢?我觉得学习每个知识点可以考虑这样去入手:
1. **官网(大概率是英文,不推荐初学者看)**
2. **书籍(知识更加系统完全,推荐)**
3. **视频(比较容易理解,推荐,特别是初学的时候。慕课网和哔哩哔哩上面有挺多学习视频可以看,只直接在上面搜索关键词就可以了)**
4. **网上博客(解决某一知识点的问题的时候可以看看)**
这里给各位一个建议,**看视频的过程中最好跟着一起练,要做笔记!!!**
**最好可以边看视频边找一本书籍看,看视频没弄懂的知识点一定要尽快解决,如何解决?**
首先百度/Google通过搜索引擎解决不了的话就找身边的朋友或者认识的一些人。另外一定要进行项目实战很多人这时候就会问没有实际项目让我做怎么办我觉得可以通过下面这几种方式
1. 在网上找一个符合自己能力与找工作需求的实战项目视频或者博客跟着老师一起做。做的过程中,你要有自己的思考,不要浅尝辄止,对于很多知识点,别人的讲解可能只是满足项目就够了,你自己想多点知识的话,对于重要的知识点就要自己学会去往深处学。
2. Github 或者码云上面有很多实战类别项目,你可以选择一个来研究,为了让自己对这个项目更加理解,在理解原有代码的基础上,你可以对原有项目进行改进或者增加功能。
3. 自己动手去做一个自己想完成的东西,遇到不会的东西就临时去学,现学现卖(这种方式比较难,初学不推荐用这种方式,因为你脑海中没有基本的概念,写出来的代码一般会很难或者根本就做不出来一个像样的东西)。
4. ......
**做项目不光要做,还要改进,改善。另外,如果你的老师有相关 Java 后台项目的话,你也可以主动申请参与进来。**
**一定要学会分配自己时间,要学的东西很多,真的很多,搞清楚哪些东西是重点,哪些东西仅仅了解就够了。一定不要把精力都花在了学各种框架上,算法和数据结构真的很重要!**
另外,**学习的过程中有一个可以参考的文档很重要,非常有助于自己的学习**。我当初弄 JavaGuide https://github.com/Snailclimb/JavaGuide 的很大一部分目的就是因为这个。**客观来说相比于博客JavaGuide 里面的内容因为更多人的参与变得更加准确和完善。**
### 公众号
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
**《Java 面试突击》:** 由本文档衍生的专为面试而生的《Java 面试突击》V2.0 PDF 版本[公众号](#公众号 "公众号")后台回复 **"Java 面试突击"** 即可免费领取!
**Java 工程师必备学习资源:** 一些 Java 工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png)

View File

@ -0,0 +1,104 @@
问题描述:
> 最近在北京华软科技公司看到一个招聘去咨询了人事部他说培训四个月就能上岗并且不要学费上岗后再每还1000元还一年这个可靠吗本人高中毕业四个月能学会吗谢谢了
下面是正文:
一般说不要学费上岗后每月再还1000元这种十有八九都不靠谱就算你把合同看的再仔细别人也总有各种办法去刁难你。
另外,目前的互联网行业已经完全不是它刚开始盛行的样子了。在互联网爆火🔥的初期,你可能会简单用一下语言就能找到一个不错的工作。那时候,即使是没有学历支撑直接从培训班出来的基本也都找到了还算是不错的工作。但是,现在已经完全不一样了。我觉得主要可以从以下几个方面讲:
1. **没有学历支撑,直接从培训班出来的找工作会很难,甚至找不到**
2. **面试的难度可以说一年比一年难,学的人越来越多,和你竞争的也越来越多,特别是像面试阿里、腾讯、字节跳动这样的大厂,你可能要和更多人去竞争。“面试造火箭,入职拎螺丝”想想也是正常,毕竟这么多人去竞争那少数的 offer如果不难点的话区分度就没那么明显了**
3. 学习计算机专业的越来越多,和你竞争的也越来越多,需求就那么一些,人多了之后,平均工资水平以后应该不会和其他行业差别这么大。但是,我个人感觉技术厉害的还是会很吃香。只是,普通的程序员的工资可能比不上前几年了。
**养成一个学习习惯和编程习惯真的太重要了,一个好习惯的养成真的对后面的学习有很大帮助。** 说实话我自己当初在这方面吃了不少亏,很多比较好的习惯我也是后面自己才慢慢发现,所以这里想着重给大家说一下有哪些好的学习和编程习惯。另外,**不要在意自己会多少框架,真的没有一点用!**
下面是一些我觉得还不错的编程好习惯,希望对大家有帮助。
## 编程好习惯推荐
> **下面这些我都总结在了 Github 上,更多内容可以通过这个链接查看:** https://github.com/Snailclimb/programmer-advancement 。
### 正确提问
我们平时任何时候都离不开提问特别是初学的时候,但是真正知道如何正确的提问的人很少。问别人问题前不要来一句“在吗”,你说你问了在吗我是回复好还是不回复好呢 ?不要让别人给你发 32 位的JDK除非你是喜欢那个人。
更多关于如何提问的内容,详见 github 上开源版『提问的智慧』 <https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md>,抽时间看一下,我想看完之后应该会有很多收获。
更多内容可以查看我的这篇原创文章:[如何提问](docs/how-to-ask.md)
### 健康生活
我一直觉得这一方面是最重要的,我想很多人和我一样会无意识间忽略它,等到真的身体不舒服了,你才开始意识到健康生活的重要性。
1. 除非万不得已,不要熬夜了。熬夜的危害就不用多说了,秃头加内分泌失调,你懂得!
2. 看电脑45分钟之后起来走5分钟看看远方放松一下。不要觉得这5分钟浪费时间相反这5分钟可能为你带来更大的效率提升。
3. 可以考虑买一个电脑架子,保护好自己脊椎的同时,办公体验也会提升很多。
4. 可以下载一个护眼宝,感觉可以护眼模式挺棒的,非常适合我们这种需要经常盯着电脑的人使用,强烈安利。
### 高效搜索
尽量用 google 查找技术资料以及自己在学习中遇到的一些问题。
### 解决 bug
程序遇到问题先在 stackoverflow 找找大部分别人已经遇到过了。如果上面没有的话再考虑其他解决办法。实在解决不了的话再去问你觉得有能力帮你解决的人注意描述好自己的问题不要随便截一个Bug 图)。
### 善于总结
学习完任何一门知识后,你可能当时看视频感觉老师讲的挺容易懂的。但是,过几天后你发现你忘的一干二净,别人问你一个类似的问题,你一点思路都没有。所以,我推荐你学完一门知识后不光要及时复习,还要做好总结,让知识形成一个体系。另外,你可以假想自己要给别人讲这个知识点,你能不能把这个知识点讲清楚呢?如果不能,说明你对这个知识点还没有彻底了解。这也就是人们经常说的费曼学习技巧。
总结的方式:
1. 有道云笔记、OneNote......这类专门用来记录笔记的软件上;
2. 思维导图;
3. 通过写博客输出。可以考虑自己搭建一个博客(hexo+GithubPages非常简单),你也可以在简书、掘金......等等技术交流社区写博客。Markdown 格式参考:<https://github.com/sparanoid/chinese-copywriting-guidelines> 中文文案排版指北:<https://github.com/sparanoid/chinese-copywriting-guidelines>
### 写博客
写博客有哪些好处:
1. 对知识有更加深的认识,让自己的知识体系更加完整;
2. 督促自己学习;
3. 可能会带来不错的经济收入;
4. 提升个人影响力;
5. 拥有更多机会;
6. ......
**总的来说,写博客是一件利己利彼的事情。你可能会从中收获到很多东西,你写的东西也可能对别人也有很大的帮助。但是,写博客还是比较耗费自己时间的,你需要和工作做好权衡。**
**分享是一种美德,任何行业都不是靠单打独斗的,写博客、写好博客是一个程序员很好的习惯。我为人人,人人为我!**
更多内容可以查看我的这篇原创文章:[我为什么推荐你写博客?](./docs/我为什么推荐你写博客.md)
### 多用 Github
没事多去Github转转如果有能力可以参与到一些开源项目中。多看看别人开源的优秀项目看看别人的代码和设计思路看的多了你的编程思想也会慢慢得到提升。除了这些优秀的开源项目之外Github上面还有很多不错的开源文档、开源资料什么的我觉得对我们平时学习都挺有帮助。Github用得好还能装一下毕竟人家还是一个全英文网站咳咳咳。
### 实践
多去实践,将学到的东西运用到实际项目中去。很多人都找我抱怨过没有实际项目让自己去做,怎么能有项目经验呢?如果实在没有实际项目让你去做,我觉得你可以通过下面几种方式:
1. 在网上找一个符合自己能力与找工作需求的实战项目视频或者博客跟着老师一起做。做的过程中,你要有自己的思考,不要浅尝辄止,对于很多知识点,别人的讲解可能只是满足项目就够了,你自己想多点知识的话,对于重要的知识点就要自己学会去往深出学。
2. Github或者码云上面有很多实战类别项目你可以选择一个来研究为了让自己对这个项目更加理解在理解原有代码的基础上你可以对原有项目进行改进或者增加功能。
3. 自己动手去做一个自己想完成的东西,遇到不会的东西就临时去学,现学现卖。
### 注意代码规范
从学习编程的第一天起就要养成不错的编码习惯,包、类、方法的命名这些是最基本的。
推荐阅读:
- 阿里巴巴Java开发手册详尽版[https://github.com/alibaba/p3c/blob/master/阿里巴巴Java开发手册详尽版.pdf](https://github.com/alibaba/p3c/blob/master/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E8%AF%A6%E5%B0%BD%E7%89%88%EF%BC%89.pdf)
- Google Java编程风格指南<http://www.hawstein.com/posts/google-java-style.html>
- Effective Java第三版中文版: <https://legacy.gitbook.com/book/jiapengcai/effective-java>
### 沟通能力
程序员也离不开沟通。你可能需要与客户交流需求,还要和同事交流项目问题,还有可能定期需要向领导汇报项目进展情况。所以,我觉得不错的沟通能力也是一个优秀的程序员应该有的基本素质。
## 学习方法和学习路线推荐
推荐查看我的这篇文章[《可能是最适合你的Java学习方法和路线推荐》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/questions/java-learning-path-and-methods.md),文中提到的学习路线以及方法是笔主根据个人学习经历总结改进后得出,我相信照着这条学习路线来你的学习效率会非常高。

View File

@ -105,7 +105,7 @@ public String readAllCookies(HttpServletRequest request) {
**JWT 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。**
下面是 [RFC 7519](https://link.juejin.im/?target=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc7519) 对 JWT 做的较为正式的定义。
下面是 [RFC 7519](https://tools.ietf.org/html/rfc7519) 对 JWT 做的较为正式的定义。
> JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. ——[JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)
@ -140,7 +140,7 @@ OAuth 是一个行业的标准授权协议,主要用来授权第三方应用
OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。
推荐阅读:
**推荐阅读:**
- [OAuth 2.0 的一个简单解释](http://www.ruanyifeng.com/blog/2019/04/oauth_design.html)
- [10 分钟理解什么是 OAuth 2.0 协议](https://deepzz.com/post/what-is-oauth2-protocol.html)

View File

@ -28,7 +28,7 @@
### 概念一:生产者与消费者
![生产者与消费者](./../../../media/pictures/kafaka/生产者和消费者.png)
![生产者与消费者](./../../../media/pictures/kafka/生产者和消费者.png)
对于 Kafka 来说客户端有两种基本类型:
@ -41,7 +41,7 @@
### 概念二主题Topic与分区Partition
![主题Topic与分区Partition](./../../../media/pictures/kafaka/主题与分区.png)
![主题Topic与分区Partition](./../../../media/pictures/kafka/主题与分区.png)
在 Kafka 中,消息以**主题Topic**来分类,每一个主题都对应一个 **「消息队列」**,这有点儿类似于数据库中的表。但是如果我们把所有同类的消息都塞入到一个“中心”队列中,势必缺少可伸缩性,无论是生产者/消费者数目的增加,还是消息数量的增加,都可能耗尽系统的性能或存储。
@ -53,7 +53,7 @@
若干个 Broker 组成一个集群Cluster其中集群内某个 Broker 会成为集群控制器Cluster Controller它负责管理集群包括分配分区到 Broker、监控 Broker 故障等。在集群内,一个分区由一个 Broker 负责,这个 Broker 也称为这个分区的 Leader当然一个分区可以被复制到多个 Broker 上来实现冗余,这样当存在 Broker 故障时可以将其分区重新分配到其他 Broker 来负责。下图是一个样例:
![Broker和集群](./../../../media/pictures/kafaka/Broker和集群.png)
![Broker和集群](./../../../media/pictures/kafka/Broker和集群.png)
Kafka 的一个关键性质是日志保留retention我们可以配置主题的消息保留策略譬如只保留一段时间的日志或者只保留特定大小的日志。当超过这些限制时老的消息会被删除。我们也可以针对某个主题单独设置消息过期策略这样对于不同应用可以实现个性化。
@ -84,7 +84,7 @@ Kafka 的一个关键性质是日志保留retention我们可以配置
**上述的 Topic 其实是逻辑上的概念,面相消费者和生产者,物理上存储的其实是 Partition**,每一个 Partition 最终对应一个目录,里面存储所有的消息和索引文件。默认情况下,每一个 Topic 在创建时如果不指定 Partition 数量时只会创建 1 个 Partition。比如我创建了一个 Topic 名字为 test ,没有指定 Partition 的数量,那么会默认创建一个 test-0 的文件夹,这里的命名规则是:`<topic_name>-<partition_id>`
![主题Topic与分区Partition](./../../../media/pictures/kafaka/kafka存在文件系统上.png)
![主题Topic与分区Partition](./../../../media/pictures/kafka/kafka存在文件系统上.png)
任何发布到 Partition 的消息都会被追加到 Partition 数据文件的尾部,这样的顺序写磁盘操作让 Kafka 的效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是 Kafka 高吞吐率的一个很重要的保证)。
@ -122,7 +122,7 @@ Kafka 的一个关键性质是日志保留retention我们可以配置
以上面的一对 Segment File 为例,说明一下索引文件和数据文件对应关系:
![索引文件和数据文件](./../../../media/pictures/kafaka/segment是kafka文件存储的最小单位.png)
![索引文件和数据文件](./../../../media/pictures/kafka/segment是kafka文件存储的最小单位.png)
@ -150,7 +150,7 @@ Kafka 的一个关键性质是日志保留retention我们可以配置
不同的业务需要使用不同的写入方式和配置。具体的方式我们在这里不做讨论,现在先看下生产者写消息的基本流程:
![生产者设计概要](./../../../media/pictures/kafaka/生产者设计概要.png)
![生产者设计概要](./../../../media/pictures/kafka/生产者设计概要.png)
图片来源:[http://www.dengshenyu.com/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/11/12/kafka-producer.html](http://www.dengshenyu.com/分布式系统/2017/11/12/kafka-producer.html)
@ -173,24 +173,24 @@ Kafka 的一个关键性质是日志保留retention我们可以配置
Kafka消费者是**消费组**的一部分当多个消费者形成一个消费组来消费主题时每个消费者会收到不同分区的消息。假设有一个T1主题该主题有4个分区同时我们有一个消费组G1这个消费组只有一个消费者C1。那么消费者C1将会收到这4个分区的消息如下所示
![生产者设计概要](./../../../media/pictures/kafaka/消费者设计概要1.png)
![生产者设计概要](./../../../media/pictures/kafka/消费者设计概要1.png)
如果我们增加新的消费者C2到消费组G1那么每个消费者将会分别收到两个分区的消息如下所示
![生产者设计概要](./../../../media/pictures/kafaka/消费者设计概要2.png)
![生产者设计概要](./../../../media/pictures/kafka/消费者设计概要2.png)
如果增加到4个消费者那么每个消费者将会分别收到一个分区的消息如下所示
![生产者设计概要](./../../../media/pictures/kafaka/消费者设计概要3.png)
![生产者设计概要](./../../../media/pictures/kafka/消费者设计概要3.png)
但如果我们继续增加消费者到这个消费组,剩余的消费者将会空闲,不会收到任何消息:
![生产者设计概要](./../../../media/pictures/kafaka/消费者设计概要4.png)
![生产者设计概要](./../../../media/pictures/kafka/消费者设计概要4.png)
总而言之,我们可以通过增加消费组的消费者来进行水平扩展提升消费能力。这也是为什么建议创建主题时使用比较多的分区数,这样可以在消费负载高的情况下增加消费者来提升性能。另外,消费者的数量不应该比分区数多,因为多出来的消费者是空闲的,没有任何帮助。
**Kafka一个很重要的特性就是只需写入一次消息可以支持任意多的应用读取这个消息。**换句话说每个应用都可以读到全量的消息。为了使得每个应用都能读到全量消息应用需要有不同的消费组。对于上面的例子假如我们新增了一个新的消费组G2而这个消费组有两个消费者那么会是这样的
![生产者设计概要](./../../../media/pictures/kafaka/消费者设计概要5.png)
![生产者设计概要](./../../../media/pictures/kafka/消费者设计概要5.png)
在这个场景中消费组G1和消费组G2都能收到T1主题的全量消息在逻辑意义上来说它们属于不同的应用。
@ -216,7 +216,7 @@ Kafka消费者是**消费组**的一部分,当多个消费者形成一个消
无论消息是否被消费,除非消息到期 Partition 从不删除消息。例如设置保留时间为 2 天,则消息发布 2 天内任何 Group 都可以消费2 天后,消息自动被删除。
Partition 会为每个 Consumer Group 保存一个偏移量,记录 Group 消费到的位置。 如下图:
![生产者设计概要](./../../../media/pictures/kafaka/Partition与消费模型.png)
![生产者设计概要](./../../../media/pictures/kafka/Partition与消费模型.png)
@ -269,7 +269,7 @@ vi /usr/local/etc/kafka/server.properties
然后修改成下图的样子:
![启动服务](./../../../media/pictures/kafaka/启动服务.png)
![启动服务](./../../../media/pictures/kafka/启动服务.png)
依次启动 Zookeeper 和 Kafka
```shell
@ -305,7 +305,7 @@ kafka-console-producer --broker-list localhost:9092 --topic test
能通过消费者窗口观察到正确的消息:
![发送消息](./../../../media/pictures/kafaka/发送消息.png)
![发送消息](./../../../media/pictures/kafka/发送消息.png)
# 参考资料

View File

@ -0,0 +1,94 @@
## 什么是 RPC?RPC原理是什么?
### **什么是 RPC**
RPCRemote Procedure Call—远程过程调用它是一种通过网络从远程计算机程序上请求服务而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。 RPC 的出现就是为了解决这个问题。
### **RPC原理是什么**
我这里这是简单的提一下,详细内容可以查看下面这篇文章:
http://www.importnew.com/22003.html
![RPC原理图](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-6/37345851.jpg)
1. 服务消费方client调用以本地调用方式调用服务
2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体
3. client stub找到服务地址并将消息发送到服务端
4. server stub收到消息后进行解码
5. server stub根据解码结果调用本地的服务
6. 本地服务执行并将结果返回给server stub
7. server stub将返回结果打包成消息并发送至消费方
8. client stub接收到消息并进行解码
9. 服务消费方得到最终结果。
下面再贴一个网上的时序图:
![RPC原理时序图](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-6/32527396.jpg)
### RPC 解决了什么问题?
从上面对 RPC 介绍的内容中概括来讲RPC 主要解决了:**让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单。**
### 常见的 RPC 框架总结?
- **RMIJDK自带** JDK自带的RPC有很多局限性不推荐使用。
- **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。目前 Dubbo 已经成为 Spring Cloud Alibaba 中的官方组件。
- **gRPC** gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务以实现负载平衡跟踪运行状况检查和身份验证。它也适用于分布式计算的最后一英里以将设备移动应用程序和浏览器连接到后端服务。
- **Hessian** Hessian是一个轻量级的remotingonhttp工具使用简单的方法提供了RMI的功能。 相比WebServiceHessian更简单、快捷。采用的是二进制RPC协议因为采用的是二进制协议所以它很适合于发送二进制数据。
- **Thrift** Apache Thrift是Facebook开源的跨语言的RPC通信框架目前已经捐献给Apache基金会管理由于其跨语言特性和出色的性能在很多互联网公司得到应用有能力的公司甚至会基于thrift研发一套分布式服务框架增加诸如服务注册、服务发现等功能。
## 既有 HTTP ,为啥用 RPC 进行服务调用?
###RPC 只是一种设计而已
RPC 只是一种概念、一种设计,就是为了解决 **不同服务之间的调用问题**, 它一般会包含有 **传输协议****序列化协议** 这两个。
实现 RPC 的可以传输协议可以直接建立在 TCP 之上,也可以建立在 HTTP 协议之上。**大部分 RPC 框架都是使用的 TCP 连接gRPC使用了HTTP2。**
### HTTP 和 TCP
**可能现在很多对计算机网络不太熟悉的朋友已经被搞蒙了,要想真正搞懂,还需要来简单复习一下计算机网络基础知识:**
> 我们通常谈计算机网络的五层协议的体系结构是指:应用层、传输层、网络层、数据链路层、物理层。
>
> **应用层(application-layer的任务是通过应用进程间的交互来完成特定网络应用。**HTTP 属于应用层协议它会基于TCP/IP通信协议来传递数据HTML 文件, 图片文件, 查询结果等。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过 URL 向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后向客户端发送响应信息。HTTP协议建立在 TCP 协议之上。
>
> **运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务**。TCP是传输层协议主要解决数据如何在网络中传输。相比于UDP,**TCP** 提供的是**面向连接**的,**可靠的**数据传输服务。
**主要关键就在 HTTP 使用的 TCP 协议,和我们自定义的 TCP 协议在报文上的区别。**
**http1.1协议的 TCP 报文包含太多在传输过程中可能无用的信息:**
```
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
```
**使用自定义 TCP 协议进行传输就会避免上面这个问题,极大地减轻了传输数据的开销。**这也就是为什么通常会采用自定义 TCP 协议的 RPC 来进行进行服务调用的真正原因。初次之外,成熟的 RPC 框架还提供好了“服务自动注册与发现”、"智能负载均衡"、“可视化的服务治理和运维”、“运行期流量调度”等等功能,这些也算是选择 RPC 进行服务注册和发现的一方面原因吧!
**相关阅读:**
- http://www.ruanyifeng.com/blog/2016/08/http.html HTTP 协议入门- 阮一峰)
###一个常见的错误观点
很多文章中还会提到说 HTTP 协议相较于自定义 TCP 报文协议增加的开销在于连接的建立与断开但是这个观点已经被否认下面截取自知乎中一个回答原回答地址https://www.zhihu.com/question/41609070/answer/191965937。
>首先要否认一点 HTTP 协议相较于自定义 TCP 报文协议增加的开销在于连接的建立与断开。HTTP 协议是支持连接池复用的,也就是建立一定数量的连接不断开,并不会频繁的创建和销毁连接。二一要说的是 HTTP 也可以使用 Protobuf 这种二进制编码协议对内容进行编码,因此二者最大的区别还是在传输协议上。
### 题外话
初次之外,还需要注意的一点是 Spring Cloud Netflix 并没有使用 RPC 框架来进行不同服务之间的调用,而是使用 HTTP 协议进行调用的,速度虽然不比 RPC ,但是使用 HTTP 协议也会带来其他很多好处(这一点,可以自行查阅相关资料了解)。

View File

@ -1,6 +1,6 @@
> 本文由JavaGuide整理翻译自做了适当删减和修改
> 本文由JavaGuide整理翻译自做了适当删减、修改和补充
>
> - https://www.javaguides.net/2018/11/spring-boot-interview-questions-and-answers.html
> - https://www.algrim.co/posts/101-spring-boot-interview-questions
@ -37,7 +37,7 @@ Spring Boot Starters 是一系列依赖关系的集合,因为它的存在,
</dependency>
```
### 如何在Spring Boot应用程序中使用Jetty而不是Tomcat?
### 5. 如何在Spring Boot应用程序中使用Jetty而不是Tomcat?
Spring Boot Web starter使用Tomcat作为默认的嵌入式servlet容器, 如果你想使用 Jetty 的话只需要修改pom.xml(Maven)或者build.gradle(Gradle)就可以了。
@ -73,7 +73,7 @@ compile("org.springframework.boot:spring-boot-starter-jetty")
说个题外话,从上面可以看出使用 Gradle 更加简洁明了,但是国内目前还是 Maven 使用的多一点,我个人觉得 Gradle 在很多方面都要好很多。
### 介绍一下@SpringBootApplication注解
### 6. 介绍一下@SpringBootApplication注解
```java
package org.springframework.boot.autoconfigure;
@ -108,3 +108,95 @@ public @interface SpringBootConfiguration {
- `@ComponentScan` 扫描被`@Component` (`@Service`,`@Controller`)注解的bean注解默认会扫描该类所在的包下所有的类。
- `@Configuration`允许在上下文中注册额外的bean或导入其他配置类
### 7. (重要)Spring Boot 的自动配置是如何实现的?
这个是因为`@SpringBootApplication `注解的原因,在上一个问题中已经提到了这个注解。我们知道 `@SpringBootApplication `看作是 `@Configuration``@EnableAutoConfiguration``@ComponentScan ` 注解的集合。
- `@EnableAutoConfiguration`:启用 SpringBoot 的自动配置机制
- `@ComponentScan` 扫描被`@Component` (`@Service`,`@Controller`)注解的bean注解默认会扫描该类所在的包下所有的类。
- `@Configuration`允许在上下文中注册额外的bean或导入其他配置类
`@EnableAutoConfiguration`是启动自动配置的关键,源码如下(建议自己打断点调试,走一遍基本的流程)
```java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
```
`@EnableAutoConfiguration` 注解通过Spring 提供的 `@Import` 注解导入了`AutoConfigurationImportSelector`类(`@Import` 注解可以导入配置类或者Bean到当前类中
` ``AutoConfigurationImportSelector`类中`getCandidateConfigurations`方法会将所有自动配置类的信息以 List 的形式返回。这些配置信息会被 Spring 容器作 bean 来管理。
```java
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
```
自动配置信息有了,那么自动配置还差什么呢?
`@Conditional` 注解。`@ConditionalOnClass`(指定的类必须存在于类路径下),`@ConditionalOnBean`(容器中是否有指定的Bean)等等都是对`@Conditional`注解的扩展。拿 Spring Security 的自动配置举个例子:
`SecurityAutoConfiguration`中导入了`WebSecurityEnablerConfiguration`类,`WebSecurityEnablerConfiguration`源代码如下:
```java
@Configuration
@ConditionalOnBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {
}
```
`WebSecurityEnablerConfiguration`类中使用`@ConditionalOnBean`指定了容器中必须还有`WebSecurityConfigurerAdapter` 类或其实现类。所以,一般情况下 Spring Security 配置类都会去实现 `WebSecurityConfigurerAdapter`,这样自动将配置就完成了。
更多内容可以参考这篇文章https://sylvanassun.github.io/2018/01/08/2018-01-08-spring_boot_auto_configure/
### 8. Spring Boot支持哪些嵌入式web容器
Spring Boot支持以下嵌入式servlet容器:
| **Name** | **Servlet Version** |
| ------------ | ------------------- |
| Tomcat 9.0 | 4.0 |
| Jetty 9.4 | 3.1 |
| Undertow 2.0 | 4.0 |
您还可以将Spring引导应用程序部署到任何Servlet 3.1+兼容的 Web 容器中。
这就是你为什么可以通过直接像运行 普通 Java 项目一样运行 SpringBoot 项目。这样的确省事了很多,方便了我们进行开发,降低了学习难度。
### 9. 什么是Spring Security ?
Spring Security 应该属于 Spring 全家桶中学习曲线比较陡峭的几个模块之一,下面我将从起源和定义这两个方面来简单介绍一下它。
- **起源:** Spring Security 实际上起源于 Acegi Security这个框架能为基于 Spring 的企业应用提供强大而灵活安全访问控制解决方案,并且框架这个充分利用 Spring 的 IoC 和 AOP 功能,提供声明式安全访问控制的功能。后面,随着这个项目发展, Acegi Security 成为了Spring官方子项目后来被命名为 “Spring Security”。
- **定义:**Spring Security 是一个功能强大且高度可以定制的框架侧重于为Java 应用程序提供身份验证和授权。——[官方介绍](https://spring.io/projects/spring-security)。
### 10. JPA 和 Hibernate 有哪些区别JPA 可以支持动态 SQL 吗?

View File

@ -1,33 +1,8 @@
**本文只是对 Docker 的概念做了较为详细的介绍,并不涉及一些像 Docker 环境的安装以及 Docker 的一些常见操作和命令。**
<!-- TOC -->
## 一 认识容器
- [一 先从认识容器开始](#一-先从认识容器开始)
- [1.1 什么是容器?](#11-什么是容器)
- [先来看看容器较为官方的解释](#先来看看容器较为官方的解释)
- [再来看看容器较为通俗的解释](#再来看看容器较为通俗的解释)
- [1.2 图解物理机,虚拟机与容器](#12-图解物理机虚拟机与容器)
- [二 再来谈谈 Docker 的一些概念](#二-再来谈谈-docker-的一些概念)
- [2.1 什么是 Docker?](#21-什么是-docker)
- [2.2 Docker 思想](#22-docker-思想)
- [2.3 Docker 容器的特点](#23-docker-容器的特点)
- [2.4 为什么要用 Docker ?](#24-为什么要用-docker-)
- [三 容器 VS 虚拟机](#三-容器-vs-虚拟机)
- [3.1 两者对比图](#31-两者对比图)
- [3.2 容器与虚拟机总结](#32-容器与虚拟机总结)
- [3.3 容器与虚拟机两者是可以共存的](#33-容器与虚拟机两者是可以共存的)
- [四 Docker基本概念](#四-docker基本概念)
- [4.1 镜像(Image):一个特殊的文件系统](#41-镜像image一个特殊的文件系统)
- [4.2 容器(Container):镜像运行时的实体](#42-容器container镜像运行时的实体)
- [4.3仓库(Repository):集中存放镜像文件的地方](#43仓库repository集中存放镜像文件的地方)
- [五 最后谈谈:Build Ship and Run](#五-最后谈谈build-ship-and-run)
- [六 总结](#六-总结)
<!-- /TOC -->
> **Docker 是世界领先的软件容器平台**所以想要搞懂Docker的概念我们必须先从容器开始说起。
## 一 先从认识容器开始
**Docker 是世界领先的软件容器平台**,所以想要搞懂 Docker 的概念我们必须先从容器开始说起。
### 1.1 什么是容器?
@ -43,27 +18,31 @@
**如果需要通俗的描述容器的话,我觉得容器就是一个存放东西的地方,就像书包可以装各种文具、衣柜可以放各种衣服、鞋架可以放各种鞋子一样。我们现在所说的容器存放的东西可能更偏向于应用比如网站、程序甚至是系统环境。**
![认识容器](https://user-gold-cdn.xitu.io/2018/6/17/1640cae21c18e404?w=445&h=363&f=png&s=81473)
![认识容器](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/container.png)
### 1.2 图解物理机,虚拟机与容器
关于虚拟机与容器的对比在后面会详细介绍到,这里只是通过网上的图片加深大家对于物理机、虚拟机与容器这三者的理解。
关于虚拟机与容器的对比在后面会详细介绍到,这里只是通过网上的图片加深大家对于物理机、虚拟机与容器这三者的理解(下面的图片来源与网络)。
**物理机**
![物理机](https://user-gold-cdn.xitu.io/2018/6/18/1641129f0ecdf8ff?w=720&h=353&f=jpeg&s=55729)
![物理机](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/物理机图解.png)
**虚拟机:**
![虚拟机](https://user-gold-cdn.xitu.io/2018/6/18/164112a72a917f4a?w=720&h=321&f=jpeg&s=43096)
![虚拟机](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/虚拟机图解.png)
**容器:**
![容器](https://user-gold-cdn.xitu.io/2018/6/18/164112ac76e6f693?w=720&h=302&f=jpeg&s=41669)
![容器](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/ 容器图解.png)
通过上面这三张抽象图,我们可以大概可以通过类比概括出: **容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。**
---
> 相信通过上面的解释大家对于容器这个既陌生又熟悉的概念有了一个初步的认识下面我们就来谈谈Docker的一些概念。
**相信通过上面的解释大家对于容器这个既陌生又熟悉的概念有了一个初步的认识,下面我们就来谈谈 Docker 的一些概念。**
## 二 再来谈谈 Docker 的一些概念
@ -74,8 +53,7 @@
说实话关于 Docker 是什么并太好说,下面我通过四点向你说明 Docker 到底是个什么东西。
- **Docker 是世界领先的软件容器平台。**
- **Docker** 使用 Google 公司推出的 **Go 语言** 进行开发实现,基于 **Linux 内核** 的cgroupnamespace以及AUFS类的**UnionFS**等技术,**对进程进行封装隔离,属于操作系统层面的虚拟化技术。** 由于隔离的进程独立于宿主和其它的隔离的进
程,因此也称其为容器。**Docke最初实现是基于 LXC.**
- **Docker** 使用 Google 公司推出的 **Go 语言** 进行开发实现,基于 **Linux 内核** 提供的 CGroup 功能和 name space 来实现的,以及 AUFS 类的 **UnionFS** 等技术,**对进程进行封装隔离,属于操作系统层面的虚拟化技术。** 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
- **Docker 能够自动执行重复性任务,例如搭建和配置开发环境,从而解放了开发人员以便他们专注在真正重要的事情上:构建杰出的软件。**
- **用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。**
@ -92,9 +70,11 @@
- #### 轻量
在一台机器上运行的多个 Docker 容器可以共享这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的,并共享一些公共文件。这样就能尽量降低磁盘用量,并能更快地下载镜像。
- #### 标准
Docker 容器基于开放式标准,能够在所有主流 Linux 版本、Microsoft Windows 以及包括 VM、裸机服务器和云在内的任何基础设施上运行。
- #### 安全
Docker 赋予应用的隔离性不仅限于彼此隔离还独立于底层的基础设施。Docker 默认提供最强的隔离,因此应用出现问题,也只是单个容器的问题,而不会波及到整台机器。
@ -110,15 +90,15 @@
---
> 每当说起容器,我们不得不将其与虚拟机做一个比较。就我而言,对于两者无所谓谁会取代谁,而是两者可以和谐共存。
## 三 容器 VS 虚拟机
  简单来说: **容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。**
**每当说起容器,我们不得不将其与虚拟机做一个比较。就我而言,对于两者无所谓谁会取代谁,而是两者可以和谐共存。**
简单来说: **容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。**
### 3.1 两者对比图
  传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便.
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便.
![容器 VS 虚拟机](https://user-gold-cdn.xitu.io/2018/6/17/1640cb4abec9e902?w=1086&h=406&f=png&s=70264)
@ -130,7 +110,7 @@
- **虚拟机 (VM) 是一个物理硬件层抽象,用于将一台服务器变成多台服务器。** 管理程序允许多个 VM 在一台机器上运行。每个 VM 都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此 **占用大量空间** 。而且 VM **启动也十分缓慢**
  通过Docker官网我们知道了这么多Docker的优势但是大家也没有必要完全否定虚拟机技术因为两者有不同的使用场景。**虚拟机更擅长于彻底隔离整个运行环境**。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而 **Docker通常用于隔离不同的应用** ,例如前端,后端以及数据库。
通过 Docker 官网,我们知道了这么多 Docker 的优势,但是大家也没有必要完全否定虚拟机技术,因为两者有不同的使用场景。**虚拟机更擅长于彻底隔离整个运行环境**。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而 **Docker 通常用于隔离不同的应用** ,例如前端,后端以及数据库。
### 3.3 容器与虚拟机两者是可以共存的
@ -140,11 +120,9 @@
---
> Docker中非常重要的三个基本概念理解了这三个概念就理解了 Docker 的整个生命周期。
## 四 Docker 基本概念
Docker 包括三个基本概念
**Docker 中有非常重要的三个基本概念,理解了这三个概念,就理解了 Docker 的整个生命周期。**
- **镜像Image**
- **容器Container**
@ -152,52 +130,124 @@ Docker 包括三个基本概念
理解了这三个概念,就理解了 Docker 的整个生命周期
![Docker 包括三个基本概念](https://user-gold-cdn.xitu.io/2018/6/18/164109e4900357a9?w=1024&h=784&f=jpeg&s=127361)
![docker基本概念](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/docker基本概念.png)
### 4.1 镜像(Image):一个特殊的文件系统
  **操作系统分为内核和用户空间**。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而Docker 镜像Image就相当于是一个 root 文件系统。
**操作系统分为内核和用户空间**。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像Image就相当于是一个 root 文件系统。
  **Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。** 镜像不包含任何动态数据,其内容在构建之后也不会被改变。
**Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。** 镜像不包含任何动态数据,其内容在构建之后也不会被改变。
  Docker 设计时,就充分利用 **Union FS**的技术,将其设计为 **分层存储的架构** 。 镜像实际是由多层文件系统联合组成。
Docker 设计时,就充分利用 **Union FS**的技术,将其设计为 **分层存储的架构** 。 镜像实际是由多层文件系统联合组成。
  **镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。** 比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
**镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。** 比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
  分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
### 4.2 容器(Container):镜像运行时的实体
  镜像Image和容器Container的关系就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,**容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等** 。
镜像Image和容器Container的关系就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,**容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等** 。
  **容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。前面讲过镜像使用的是分层存储,容器也是如此。**
**容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。前面讲过镜像使用的是分层存储,容器也是如此。**
  **容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。**
  按照 Docker 最佳实践的要求,**容器不应该向其存储层内写入任何数据** ,容器存储层要保持无状态化。**所有的文件写入操作都应该使用数据卷Volume、或者绑定宿主目录**,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, **使用数据卷后,容器可以随意删除、重新 run ,数据却不会丢失。**
**容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。**
按照 Docker 最佳实践的要求,**容器不应该向其存储层内写入任何数据** ,容器存储层要保持无状态化。**所有的文件写入操作都应该使用数据卷Volume、或者绑定宿主目录**,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, **使用数据卷后,容器可以随意删除、重新 run ,数据却不会丢失。**
### 4.3 仓库(Repository):集中存放镜像文件的地方
  镜像构建完成后,可以很容易的在当前宿主上运行,但是, **如果需要在其它服务器上使用这个镜像我们就需要一个集中的存储、分发镜像的服务Docker Registry就是这样的服务。**
镜像构建完成后,可以很容易的在当前宿主上运行,但是, **如果需要在其它服务器上使用这个镜像我们就需要一个集中的存储、分发镜像的服务Docker Registry 就是这样的服务。**
  一个 Docker Registry中可以包含多个仓库Repository每个仓库可以包含多个标签Tag每个标签对应一个镜像。所以说**镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。**
一个 Docker Registry 中可以包含多个仓库Repository每个仓库可以包含多个标签Tag每个标签对应一个镜像。所以说**镜像仓库是 Docker 用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。**
  通常,**一个仓库会包含同一个软件不同版本的镜像**,而**标签就常用于对应该软件的各个版本** 。我们可以通过```<仓库名>:<标签>```的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。
通常,**一个仓库会包含同一个软件不同版本的镜像**,而**标签就常用于对应该软件的各个版本** 。我们可以通过`<仓库名>:<标签>`的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。
**这里补充一下 Docker Registry 公开服务和私有 Docker Registry 的概念:**
  **Docker Registry 公开服务** 是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
**Docker Registry 公开服务** 是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
  最常使用的 Registry 公开服务是官方的 **Docker Hub** ,这也是默认的 Registry并拥有大量的高质量的官方镜像网址为[https://hub.docker.com/](https://hub.docker.com/) 。在国内访问**Docker Hub** 可能会比较慢国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 [时速云镜像库](https://hub.tenxcloud.com/)、[网易云镜像服务](https://www.163yun.com/product/repo)、[DaoCloud 镜像市场](https://www.daocloud.io/)、[阿里云镜像库](https://www.aliyun.com/product/containerservice?utm_content=se_1292836)等。
最常使用的 Registry 公开服务是官方的 **Docker Hub** ,这也是默认的 Registry并拥有大量的高质量的官方镜像网址为[https://hub.docker.com/](https://hub.docker.com/ "https://hub.docker.com/") 。官方是这样介绍 Docker Hub 的:
  除了使用公开服务外,用户还可以在 **本地搭建私有 Docker Registry** 。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。
> Docker Hub 是 Docker 官方提供的一项服务,用于与您的团队查找和共享容器镜像。
比如我们想要搜索自己想要的镜像:
![利用Docker Hub 搜索镜像](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Screen Shot 2019-11-04 at 8.21.39 PM.png)
在 Docker Hub 的搜索结果中,有几项关键的信息有助于我们选择合适的镜像:
- **OFFICIAL Image** :代表镜像为 Docker 官方提供和维护,相对来说稳定性和安全性较高。
- **Stars** :和点赞差不多的意思,类似 GitHub 的 Star。
- **Dowloads** :代表镜像被拉取的次数,基本上能够表示镜像被使用的频度。
当然,除了直接通过 Docker Hub 网站搜索镜像这种方式外,我们还可以通过 `docker search` 这个命令搜索 Docker Hub 中的镜像,搜索的结果是一致的。
```bash
➜ ~ docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 8763 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3073 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 650 [OK]
```
在国内访问**Docker Hub** 可能会比较慢国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 [时速云镜像库](https://hub.tenxcloud.com/ "时速云镜像库")、[网易云镜像服务](https://www.163yun.com/product/repo "网易云镜像服务")、[DaoCloud 镜像市场](https://www.daocloud.io/ "DaoCloud 镜像市场")、[阿里云镜像库](https://www.aliyun.com/product/containerservice?utm_content=se_1292836 "阿里云镜像库")等。
除了使用公开服务外,用户还可以在 **本地搭建私有 Docker Registry** 。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。
---
> Docker的概念基本上已经讲完最后我们谈谈Build, Ship, and Run。
## 五 常见命令
### 5.1 基本命令
```bash
docker version # 查看docker版本
docker images # 查看所有已下载镜像等价于docker image ls 命令
docker container ls # 查看所有容器
docker ps #查看正在运行的容器
docker image prune # 清理临时的、没有被使用的镜像文件。-a, --all: 删除所有没有用的镜像,而不仅仅是临时文件;
```
### 5.2 拉取镜像
```bash
docker search mysql # 查看mysql相关镜像
docker pull mysql:5.7 # 拉取mysql镜像
docker image ls # 查看所有已下载镜像
```
### 5.3 删除镜像
比如我们要删除我们下载的 mysql 镜像。
通过 `docker rmi [image]` (等价于`docker image rm [image]`)删除镜像之前首先要确保这个镜像没有被容器引用(可以通过标签名称或者镜像 ID删除。通过我们前面讲的` docker ps`命令即可查看。
```shell
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4cd691d9f80 mysql:5.7 "docker-entrypoint.s…" 7 weeks ago Up 12 days 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
```
可以看到 mysql 正在被 id 为 c4cd691d9f80 的容器引用,我们需要首先通过 `docker stop c4cd691d9f80` 或者 `docker stop mysql`暂停这个容器。
然后查看 mysql 镜像的 id
```shell
➜ ~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 f6509bac4980 3 months ago 373MB
```
通过 IMAGE ID 或者 REPOSITORY 名字即可删除
```shell
docker rmi f6509bac4980 # 或者 docker rmim mysql
```
## 六 Build Ship and Run
**Docker 的概念以及常见命令基本上已经讲完我们再来谈谈Build, Ship, and Run。**
## 五 最后谈谈:Build Ship and Run
如果你搜索 Docker 官网,会发现如下的字样:**“Docker - Build, Ship, and Run Any App, Anywhere”**。那么 Build, Ship, and Run 到底是在干什么呢?
![build ship run](https://user-gold-cdn.xitu.io/2018/6/18/16411c521e79bd82?w=486&h=255&f=png&s=185903)
@ -208,13 +258,49 @@ Docker 包括三个基本概念
**Docker 运行过程也就是去仓库把镜像拉到本地,然后用一条命令把镜像运行起来变成容器。所以,我们也常常将 Docker 称为码头工人或码头装卸工,这和 Docker 的中文翻译搬运工人如出一辙。**
## 六 总结
## 七 简单了解一下 Docker 底层原理
### 7.1 虚拟化技术
首先Docker **容器虚拟化**技术为基础的软件,那么什么是虚拟化技术呢?
简单点来说,虚拟化技术可以这样定义:
> 虚拟化技术是一种资源管理技术,是将计算机的各种[实体资源](https://zh.wikipedia.org/wiki/資源_(計算機科學 "实体资源"))[CPU](https://zh.wikipedia.org/wiki/CPU "CPU")、[内存](https://zh.wikipedia.org/wiki/内存 "内存")、[磁盘空间](https://zh.wikipedia.org/wiki/磁盘空间 "磁盘空间")、[网络适配器](https://zh.wikipedia.org/wiki/網路適配器 "网络适配器")等),予以抽象、转换后呈现出来并可供分割、组合为一个或多个电脑配置环境。由此,打破实体结构间的不可切割的障碍,使用户可以比原本的配置更好的方式来应用这些电脑硬件资源。这些资源的新虚拟部分是不受现有资源的架设方式,地域或物理配置所限制。一般所指的虚拟化资源包括计算能力和数据存储。
###7.2 Docker 基于 LXC 虚拟容器技术
Docker 技术是基于 LXCLinux container- Linux 容器)虚拟容器技术的。
> LXC其名称来自 Linux 软件容器Linux Containers的缩写一种操作系统层虚拟化Operating systemlevel virtualization技术为 Linux 内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器Container内含应用软件本身的代码以及所需要的操作系统核心和库。通过统一的名字空间和共用 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易的创建和管理系统或应用容器。
LXC 技术主要是借助 Linux 内核中提供的 CGroup 功能和 name space 来实现的,通过 LXC 可以为软件提供一个独立的操作系统运行环境。
**cgroup 和 namespace 介绍:**
- **namespace 是 Linux 内核用来隔离内核资源的方式。** 通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。
(以上关于 namespace 介绍内容来自https://www.cnblogs.com/sparkdev/p/9365405.html ,更多关于 namespace 的呢内容可以查看这篇文章 )。
- **CGroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离进程组 (process groups) 所使用的物力资源 (如 cpu memory i/o 等等) 的机制。**
(以上关于 CGroup 介绍内容来自 https://www.ibm.com/developerworks/cn/linux/1506_cgroup/index.html ,更多关于 CGroup 的呢内容可以查看这篇文章 )。
**cgroup 和 namespace 两者对比:**
两者都是将进程进行分组但是两者的作用还是有本质区别。namespace 是为了隔离进程组之间的资源,而 cgroup 是为了对一组进程进行统一的资源监控和限制。
## 八 总结
本文主要把 Docker 中的一些常见概念做了详细的阐述,但是并不涉及 Docker 的安装、镜像的使用、容器的操作等内容。这部分东西希望读者自己可以通过阅读书籍与官方文档的形式掌握。如果觉得官方文档阅读起来很费力的话这里推荐一本书籍《Docker 技术入门与实战第二版》。
## 九 推荐阅读
- [10 分钟看懂 Docker 和 K8S](https://zhuanlan.zhihu.com/p/53260098 "10分钟看懂Docker和K8S")
- [从零开始入门 K8s详解 K8s 容器基本概念](https://www.infoq.cn/article/te70FlSyxhltL1Cr7gzM "从零开始入门 K8s详解 K8s 容器基本概念")
## 十 参考
- [Linux Namespace 和 Cgroup](https://segmentfault.com/a/1190000009732550 "Linux Namespace和Cgroup")
- [LXC vs Docker: Why Docker is Better](https://www.upguard.com/articles/docker-vs-lxc "LXC vs Docker: Why Docker is Better")
- [CGroup 介绍、应用实例及原理描述](https://www.ibm.com/developerworks/cn/linux/1506_cgroup/index.html "CGroup 介绍、应用实例及原理描述")

View File

@ -0,0 +1,149 @@
最近很多阿里云双 11 做活动,优惠力度还挺大的,很多朋友都买以最低的价格买到了自己的云服务器。不论是作为学习机还是部署自己的小型网站或者服务来说都是很不错的!
但是,很多朋友都不知道如何正确去使用。下面我简单分享一下自己的使用经验。
总结一下,主要涉及下面几个部分,对于新手以及没有这么使用过云服务的朋友还是比较友好的:
1. 善用阿里云镜像市场节省安装 Java 环境的时间,相关说明都在根目录下的 readme.txt. 文件里面;
2. 本地通过 SSH 连接阿里云服务器很容易,配置好 Host地址通过 root 用户加上实例密码直接连接即可。
3. 本地连接 MySQL 数据库需要简单配置一下安全组和并且允许 root 用户在任何地方进行远程登录。
4. 通过 Alibaba Cloud Toolkit 部署 Spring Boot 项目到阿里云服务器真的很方便。
**[活动地址](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** 仅限新人老用户可以考虑使用家人或者朋友账号购买推荐799/3年 2核4G 这个性价比和适用面更广)
### 善用阿里云镜像市场节省安装环境的时间
基本的购买流程这里就不多说了,另外这里需要注意的是:其实 Java 环境是不需要我们手动安装配置的,阿里云提供的镜像市场有一些常用的环境。
> 阿里云镜像市场是指阿里云建立的、由镜像服务商向用户提供其镜像及相关服务的网络平台。这些镜像在操作系统上整合了具体的软件环境和功能比如Java、PHP运行环境、控制面板等供有相关需求的用户开通实例时选用。
具体如何在购买云服务器的时候通过镜像创建实例或者已有ECS用户如何使用镜像可以查看官方详细的介绍地址
https://help.aliyun.com/knowledge_detail/41987.html?spm=a2c4g.11186631.2.1.561e2098dIdCGZ
### 当我们成功购买服务器之后如何通过 SSH 连接呢?
创建好 ECS 后,你绑定的手机会收到短信,会告知你初始密码的。你可以登录管理控制台对密码进行修改,修改密码需要在管理控制台重启服务器才能生效。
你也可以在阿里云 ECS 控制台重置实例密码,如下图所示。
![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Screen Shot 2019-10-30 at 10.51.15 AM.png)
**第一种连接方式是直接在阿里云服务器管理的网页上连接**。如上图所示, 点击远程连接,然后输入远程连接密码,这个并不是你重置实例密码得到的密码,如果忘记了直接修改远程连接密码即可。
**第二种方式是在本地通过命令或者软件连接。** 推荐使用这种方式,更加方便。
**Windows 推荐使用 Xshell 连接,具体方式如下:**
> Window电脑在家这里直接用找到的一些图片给大家展示一个。
![](https://img2018.cnblogs.com/blog/1070438/201812/1070438-20181226165727765-1335537850.png)
![](https://img2018.cnblogs.com/blog/1070438/201812/1070438-20181226170155651-1407670048.png)
接着点开输入账号root,命名输入刚才设置的密码,点ok就可以了
![](https://img2018.cnblogs.com/blog/1070438/201812/1070438-20181226170444344-411355334.png)
**Mac 或者 Linux 系统都可以直接使用 ssh 命令进行连接,非常方便。**
成功连接之后,控制台会打印出如下消息。
```shell
➜ ~ ssh root@47.107.159.12 -p 22
root@47.107.159.12's password:
Last login: Wed Oct 30 09:31:31 2019 from 220.249.123.170
Welcome to Alibaba Cloud Elastic Compute Service !
欢迎使用 Tomcat8 JDK8 Mysql5.7 环境
使用说明请参考 /root/readme.txt 文件
```
我当时选择是阿里云提供好的 Java 环境,自动就提供了 Tomcat、 JDK8 、Mysql5.7,所以不需要我们再进行安装配置了,节省了很多时间。另外,需要注意的是:**一定要看 /readme.txt Tomcat、 JDK8 、Mysql5.7相关配置以及安装路径等说明都在里面。**
### 如何连接数据库?
**如需外网远程访问mysql 请参考以上网址 设置mysql及阿里云安全组**
![开放安全组](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/开放安全组.png)
Mysql为了安全性在默认情况下用户只允许在本地登录但是可以使用 SSH 方式连接。如果我们不想通过 SSH 方式连接的话就需要对 MySQL 进行简单的配置。
```shell
#允许root用户在任何地方进行远程登录,并具有所有库任何操作权限:
# *.*代表所有库表 “%”代表所有IP地址
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY "自定义密码" WITH GRANT OPTION;
Query OK, 0 rows affected, 1 warning (0.00 sec)
#刷新权限。 
mysql>flush privileges;
#退出mysql
mysql>exit
#重启MySQL生效
[root@snailclimb]# systemctl restart mysql
```
这样的话我们就能在本地进行连接了。Windows 推荐使用Navicat或者SQLyog。
> Window电脑在家这里用 Mac 上的MySQL可视化工具Sequel Pro给大家演示一下。
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Screen Shot 2019-10-30 at 11.02.26 AM.png" style="zoom:50%;" />
### 如何把一个Spring Boot 项目部署到服务器上呢?
默认大家都是用 IDEA 进行开发。另外,你要有一个简单的 Spring Boot Web 项目。如果还不了解 Spring Boot 的话,一个简单的 Spring Boot 版 "Hello World "项目,地址如下:
https://github.com/Snailclimb/springboot-guide/blob/master/docs/start/springboot-hello-world.md 。
**1.下载一个叫做 Alibaba Cloud Toolkit 的插件。**
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Alibaba-Cloud-Toolkit.png" style="zoom:50%;" />
**2.进入 Preference 配置一个 Access Key ID 和 Access Key Secret。**
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Screen Shot 2019-10-30 at 10.10.23 AM.png" style="zoom:50%;" />
**3.部署项目到 ECS 上。**
![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/deploy-to-ecs1.png)
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/deploy-to-ecs2.png" style="zoom:50%;" />
按照上面这样填写完基本配置之后,然后点击 run 运行即可。运行成功,控制台会打印出如下信息:
```shell
[INFO] Deployment File is Uploading...
[INFO] IDE Version:IntelliJ IDEA 2019.2
[INFO] Alibaba Cloud Toolkit Version:2019.9.1
[INFO] Start upload hello-world-0.0.1-SNAPSHOT.jar
[INFO][##################################################] 100% (18609645/18609645)
[INFO] Succeed to upload, 18609645 bytes have been uploaded.
[INFO] Upload Deployment File to OSS Success
[INFO] Target Deploy ECS: { 172.18.245.148 / 47.107.159.12 }
[INFO] Command: { source /etc/profile; cd /springboot; }
Tip: The deployment package will be temporarily stored in Alibaba Cloud Security OSS and will be
deleted after the deployment is complete. Please be assured that no one can access it except you.
[INFO] Create Deploy Directory Success.
[INFO] Deployment File is Downloading...
[INFO] Download Deployment File from OSS Success
[INFO] File Upload Total time: 16.676 s
```
通过控制台答应出的信息可以看出:通过这个插件会自动把这个 Spring Boot 项目打包成一个 jar 包,然后上传到你的阿里云服务器中指定的文件夹中,你只需要登录你的阿里云服务器,然后通过 `java -jar hello-world-0.0.1-SNAPSHOT.jar`命令运行即可。
```shell
[root@snailclimb springboot]# ll
total 18176
-rw-r--r-- 1 root root 18609645 Oct 30 08:25 hello-world-0.0.1-SNAPSHOT.jar
[root@snailclimb springboot]# java -jar hello-world-0.0.1-SNAPSHOT.jar
```
然后你就可以在本地访问访问部署在你的阿里云 ECS 上的服务了。
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Screen Shot 2019-10-30 at 10.32.06 AM.png" style="zoom:50%;" />
**[推荐一下阿里云双11的活动云服务器1折起仅86元/年,限量抢购!](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** 仅限新人老用户可以考虑使用家人或者朋友账号购买推荐799/3年 2核4G 这个性价比和适用面更广)

View File

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 134 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

View File

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 496 KiB

After

Width:  |  Height:  |  Size: 496 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB