├── .DS_Store ├── Dubbo.md ├── Elasticsearch.md ├── Git.md ├── IO&NIO.md ├── JVM.md ├── Java8.md ├── Java基础.md ├── Java基础(下).md ├── Java多线程.md ├── Java集合.md ├── Jsp.md ├── Kafka.md ├── Linux.md ├── Maven.md ├── MongoDB.md ├── MySql-上卷.md ├── MySql-下卷.md ├── Mybatis.md ├── Netty.md ├── Nginx.md ├── RabbitMQ.md ├── Readme.md ├── Redis-上卷.md ├── Redis-下卷.md ├── Servlet.md ├── Spring.md ├── SpringBoot.md ├── SpringCloud.md ├── Tomcat.md ├── Web安全.md ├── Zookeeper.md ├── 异常&反射.md ├── 简历.md └── 计算机基础.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaxiaokashow/JavaFaceNotes/fae4055eafc5b7e131c8e59a110eab32ffac1f95/.DS_Store -------------------------------------------------------------------------------- /Dubbo.md: -------------------------------------------------------------------------------- 1 | ## Dubbo 2 | 3 | #### 1.什么是Dubbo? 4 | 5 | Dubbo是基于Java的高性能轻量级的RPC分布式服务框架,现已成为 Apache 基金会孵化项目。 6 | 7 | 官网:http://dubbo.apache.org/en-us/ 8 | 9 | #### 2.为什么要使用Dubbo? 10 | 11 | 背景: 12 | 13 | 随着互联网的快速发展,Web应用程序的规模不断扩大,最后我们发现传统的垂直体系结构(整体式)已无法解决。分布式服务体系结构和流计算体系结构势在必行,迫切需要一个治理系统来确保体系结构的有序发展。 14 | 15 | - 开源免费 16 | - 一些核心业务被提取并作为独立的服务提供服务,逐渐形成一个稳定的服务中心,这样前端应用程序就可以更好地响应变化多端的市场需求 17 | - 分布式框架能承受更大规模的流量 18 | - 内部基于netty性能高 19 | 20 | #### 3.Dubbo提供了哪3个关键功能? 21 | 22 | 基于接口的远程调用 23 | 24 | 容错和负载均衡 25 | 26 | 自动服务注册和发现 27 | 28 | #### 4.你知道哪些机构在用Dubbo吗? 29 | 30 | ![image-20200423105332840](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423105332840.png) 31 | 32 | #### 5.Dubbo服务的关键节点有哪些? 33 | 34 | ![image-20200423105925624](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423105925624.png) 35 | 36 | #### 6.说一下Dubbo服务注册流程? 37 | 38 | 1. 服务容器负责启动,加载,运行服务提供者。 39 | 2. 服务提供者在启动时,向注册中心注册自己提供的服务。 40 | 3. 服务消费者在启动时,向注册中心订阅自己所需的服务。 41 | 4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 42 | 5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 43 | 6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 44 | 45 | #### 7.能画一下服务注册流程图吗? 46 | 47 | ![image-20200423110344448](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423110344448.png) 48 | 49 | #### 8.Dubbo架构的特点? 50 | 51 | 连通性、健壮性、伸缩性、以及向未来架构的升级性。 52 | 53 | #### 9.对jdk的最小版本需求? 54 | 55 | jdk1.6+ 56 | 57 | #### 10.注册中心的选择? 58 | 59 | 一般来说选中Zookeeper更稳定更合适。 60 | 61 | 除了Zookeeper还有Redis注册中心、Multicast注册中心、Simple注册中心。 62 | 63 | #### 11.Dubbo的核心配置?用途? 64 | 65 | ![image-20200423111538534](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423111538534.png) 66 | 67 | #### 12.配置优先级规则? 68 | 69 | ![image-20200423112118958](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423112118958.png) 70 | 71 | 优先级从高到低: 72 | 73 | - JVM -D参数,当你部署或者启动应用时,它可以轻易地重写配置,比如,改变dubbo协议端口; 74 | - XML, XML中的当前配置会重写dubbo.properties中的; 75 | - Properties,默认配置,仅仅作用于以上两者没有配置时。 76 | 77 | #### 13.如何用代码方式绕过注册中心点对点直连? 78 | 79 | ```java 80 | … 81 | 82 | ReferenceConfig reference = new ReferenceConfig(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏 83 | // 如果点对点直连,可以用reference.setUrl()指定目标地址,设置url后将绕过注册中心, 84 | // 其中,协议对应provider.setProtocol()的值,端口对应provider.setPort()的值, 85 | // 路径对应service.setPath()的值,如果未设置path,缺省path为接口名 86 | reference.setUrl("dubbo://10.20.130.230:20880/com.xxx.XxxService"); 87 | 88 | … 89 | ``` 90 | 91 | #### 14.Dubbo配置来源有几种?分别是? 92 | 93 | 4种 94 | 95 | - JVM System Properties,-D参数 96 | - Externalized Configuration,外部化配置 97 | - ServiceConfig、ReferenceConfig等编程接口采集的配置 98 | - 本地配置文件dubbo.properties 99 | 100 | #### 15.如何禁用某个服务的启动检查? 101 | 102 | ```xml 103 | 104 | ``` 105 | 106 | #### 16.Dubbo 负载均衡策略?默认是? 107 | 108 | - 随机负载平衡(默认) 109 | 110 | - RoundRobin负载平衡 111 | 112 | - 最小活动负载平衡 113 | 114 | - 一致的哈希负载平衡 115 | 116 | #### 17.上线兼容老版本? 117 | 118 | 多版本号(version) 119 | 120 | #### 18.开发测试环境,想绕过注册中心如何配置? 121 | 122 | - xml 123 | 124 | ```xml 125 | 126 | 127 | ``` 128 | 129 | - -D 130 | 131 | ```powershell 132 | java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890 133 | ``` 134 | 135 | - .properties 136 | 137 | ```properties 138 | java -Ddubbo.resolve.file=xxx.properties 139 | ``` 140 | 141 | ```properties 142 | com.alibaba.xxx.XxxService=dubbo://localhost:20890 143 | ``` 144 | 145 | #### 19.集群容错几种方法? 146 | 147 | ![image-20200423121735540](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423121735540.png) 148 | 149 | #### 20.Dubbo有几种配置方式? 150 | 151 | 1. Spring 152 | 2. Java API 153 | 154 | #### 21.Dubbo有哪些协议?推荐? 155 | 156 | - dubbo://(推荐) 157 | - rmi:// 158 | - hessian:// 159 | - http:// 160 | - webservice:// 161 | - thrift:// 162 | - memcached:// 163 | - redis:// 164 | - rest:// 165 | 166 | #### 22.Dubbo使用什么通信框架? 167 | 168 | dubbo使用netty。 169 | 170 | #### 23.dubbo协议默认端口号?http协议默认端口?hessian?rmi? 171 | 172 | - dubbo:20880 173 | - http:80 174 | - hessian:80 175 | - rmi:80 176 | 177 | #### 24.Dubbo默认序列化框架?其他的你还知道? 178 | 179 | - dubbo协议缺省为hessian2 180 | - rmi协议缺省为java 181 | - http协议缺省为json 182 | 183 | #### 25.一个服务有多重实现时,如何处理? 184 | 185 | 可以用group分组,服务提供方和消费放都指定同一个group。 186 | 187 | #### 26.Dubbo服务调用默认是阻塞的?还有其他的? 188 | 189 | 默认是同步等待结果阻塞的,同时也支持异步调用。 190 | 191 | Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。 192 | 193 | #### 27.Dubbo服务追踪解决方案? 194 | 195 | - Zipkin 196 | - Pinpoint 197 | - SkyWalking 198 | 199 | #### 28.Dubbo不维护了吗?Dubbo和Dubbox有什么区别? 200 | 201 | 现在进入了Apache,由apache维护。 202 | 203 | Dubbox是当当的扩展项目。 204 | 205 | #### 29.Dubbox有什么新功能? 206 | 207 | - 支持REST风格远程调用(HTTP + JSON/XML) 208 | 209 | - 支持基于Kryo和FST的Java高效序列化实现 210 | 211 | - 支持基于嵌入式Tomcat的HTTP remoting体系 212 | - 升级Spring 213 | - 升级ZooKeeper客户端 214 | 215 | #### 30.io线程池大小默认? 216 | 217 | cpu个数 + 1 218 | 219 | #### 31.dubbo://协议适合什么样的服务调用? 220 | 221 | 采用单一长链接和NIO异步通讯,适用于小数量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。 222 | 223 | 不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。 224 | 225 | ![image-20200423154308365](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423154308365.png) 226 | 227 | #### 32.自动剔除服务什么原理? 228 | 229 | zookeeper临时节点,会话保持原理。 230 | 231 | #### 33.从 `2.0.5` 版本开始,dubbo支持通过x命令来进行服务治理? 232 | 233 | telnet 234 | 235 | #### 34.如何用命令查看服务列表? 236 | 237 | ```powershell 238 | telnet localhost 20880 239 | ``` 240 | 241 | 进入命令行。然后执行 ls相关命令: 242 | 243 | - `ls`: 显示服务列表 244 | - `ls -l`: 显示服务详细信息列表 245 | - `ls XxxService`: 显示服务的方法列表 246 | - `ls -l XxxService`: 显示服务的方法详细信息列表 247 | 248 | #### 35.Dubbo框架设计是怎样的? 249 | 250 | ![image-20200423162348971](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200423162348971.png) 251 | 252 | 各层说明: 253 | 254 | - **config 配置层**:对外配置接口,以 `ServiceConfig`, `ReferenceConfig` 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类 255 | - **proxy 服务代理层**:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 `ServiceProxy` 为中心,扩展接口为 `ProxyFactory` 256 | - **registry 注册中心层**:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 `RegistryFactory`, `Registry`, `RegistryService` 257 | - **cluster 路由层**:封装多个提供者的路由及负载均衡,并桥接注册中心,以 `Invoker` 为中心,扩展接口为 `Cluster`, `Directory`, `Router`, `LoadBalance` 258 | - **monitor 监控层**:RPC 调用次数和调用时间监控,以 `Statistics` 为中心,扩展接口为 `MonitorFactory`, `Monitor`, `MonitorService` 259 | - **protocol 远程调用层**:封装 RPC 调用,以 `Invocation`, `Result` 为中心,扩展接口为 `Protocol`, `Invoker`, `Exporter` 260 | - **exchange 信息交换层**:封装请求响应模式,同步转异步,以 `Request`, `Response` 为中心,扩展接口为 `Exchanger`, `ExchangeChannel`, `ExchangeClient`, `ExchangeServer` 261 | - **transport 网络传输层**:抽象 mina 和 netty 为统一接口,以 `Message` 为中心,扩展接口为 `Channel`, `Transporter`, `Client`, `Server`, `Codec` 262 | - **serialize 数据序列化层**:可复用的一些工具,扩展接口为 `Serialization`, `ObjectInput`, `ObjectOutput`, `ThreadPool` 263 | 264 | #### 36.你读过Dubbo的源码吗? 265 | 266 | 这个问题其实面试中如果问dubbo的话,基本就会带这个问题。有时间的话,大家可以下载源码,读一读,如果大家有兴趣的话,我会出后续文章。 267 | 268 | 参考:http://dubbo.apache.org/en-us/ 269 | 270 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 271 | 272 | -------------------------------------------------------------------------------- /Elasticsearch.md: -------------------------------------------------------------------------------- 1 | ## Elasticsearch 2 | 3 | #### 1.简单介绍下ES? 4 | 5 | ES是一种存储和管理基于文档和半结构化数据的数据库(搜索引擎)。它提供实时搜索(ES最近几个版本才提供实时搜索,以前都是准实时)和分析结构化、半结构化文档、数据和地理空间信息数据。 6 | 7 | #### 2.简单介绍当前可以下载的ES稳定版本? 8 | 9 | 最新的稳定版本是7.10.0 10 | 11 | #### 3.安装ES前需要安装哪种软件? 12 | 13 | JDK 8或者 Java 1.8.0 14 | 15 | #### 4.请介绍启动ES服务的步骤? 16 | 17 | **A:**启动步骤如下 18 | 19 | Windows下进入ES文件夹的bin目录下,点击ElasticSearch.bat开始运行 20 | 21 | 打开本地9200端口http://localhost:9200, 就可以使用ES了 22 | 23 | #### 5.ES中的倒排索引是什么? 24 | 25 | 传统的检索方式是通过文章,逐个遍历找到对应关键词的位置。 26 | 倒排索引,是通过分词策略,形成了词和文章的映射关系表,也称倒排表,这种词典 + 映射表即为**倒排索引**。 27 | 28 | 其中词典中存储词元,倒排表中存储该词元在哪些文中出现的位置。 29 | 有了倒排索引,就能实现 O(1) 时间复杂度的效率检索文章了,极大的提高了检索效率。 30 | 31 | 加分项: 32 | 倒排索引的底层实现是基于:FST(Finite State Transducer)数据结构。 33 | 34 | Lucene 从 4+ 版本后开始大量使用的数据结构是 FST。FST 有两个优点: 35 | 1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间; 36 | 2)查询速度快。O(len(str)) 的查询时间复杂度。 37 | 38 | #### 6. ES是如何实现master选举的? 39 | 40 | 前置条件: 41 | 1)只有是候选主节点(master:true)的节点才能成为主节点。 42 | 2)最小主节点数(min_master_nodes)的目的是防止脑裂。 43 | 44 | Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含 Ping(节点之间通过这个RPC来发现彼此)和 Unicast(单播模块包含一个主机列表以控制哪些节点需要 ping 通)这两部分; 45 | 获取主节点的核心入口为 findMaster,选择主节点成功返回对应 Master,否则返回 null。 46 | 47 | 选举流程大致描述如下: 48 | 第一步:确认候选主节点数达标,elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes; 49 | 第二步:对所有候选主节点根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。 50 | 第三步:如果对某个节点的投票数达到一定的值(候选主节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。 51 | 52 | - 补充: 53 | - 这里的 id 为 string 类型。 54 | - master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能。 55 | 56 | #### 7. 如何解决ES集群的脑裂问题 57 | 58 | 所谓集群脑裂,是指 Elasticsearch 集群中的节点(比如共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master 的情况。 59 | 60 | 当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题; 61 | 当候选数量为两个时,只能修改为唯一的一个 master 候选,其他作为 data 节点,避免脑裂问题。 62 | 63 | #### 8. 详细描述一下ES索引文档的过程? 64 | 65 | 这里的索引文档应该理解为文档写入 ES,创建索引的过程。 66 | 67 | 第一步:客户端向集群某节点写入数据,发送请求。(如果没有指定路由/协调节点,请求的节点扮演协调节点的角色。) 68 | 第二步:协调节点接受到请求后,默认使用文档 ID 参与计算(也支持通过 routing),得到该文档属于哪个分片。随后请求会被转到另外的节点。 69 | 70 | ```java 71 | bash# 路由算法:根据文档id或路由计算目标的分片id 72 | shard = hash(document_id) % (num_of_primary_shards) 73 | ``` 74 | 75 | 第三步:当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 Memory Buffer,然后定时(默认是每隔 1 秒)写入到F ilesystem Cache,这个从 Momery Buffer 到 Filesystem Cache 的过程就叫做 refresh; 76 | 第四步:当然在某些情况下,存在 Memery Buffer 和 Filesystem Cache 的数据可能会丢失,ES 是通过 translog 的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystem cache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush; 77 | 第五步:在 flush 过程中,内存中的缓冲将被清除,内容被写入一个新段,段的 fsync 将创建一个新的提交点,并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog。 78 | 第六步:flush 触发的时机是定时触发(默认 30 分钟)或者 translog 变得太大(默认为 512 M)时。 79 | 80 | ![elasticsearch_index_process.jpg](https://www.wenyuanblog.com/medias/blogimages/elasticsearch_index_process.jpg) 81 | 82 | 83 | 84 | - 补充:关于 Lucene 的 Segement 85 | - Lucene 索引是由多个段组成,段本身是一个功能齐全的倒排索引。 86 | - 段是不可变的,允许 Lucene 将新的文档增量地添加到索引中,而不用从头重建索引。 87 | - 对于每一个搜索请求而言,索引中的所有段都会被搜索,并且每个段会消耗 CPU 的时钟周、文件句柄和内存。这意味着段的数量越多,搜索性能会越低。 88 | - 为了解决这个问题,Elasticsearch 会合并小段到一个较大的段,提交新的合并段到磁盘,并删除那些旧的小段。(段合并) 89 | 90 | #### 9. 详细描述一下ES更新和删除文档的过程? 91 | 92 | 删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更。 93 | 94 | 磁盘上的每个段都有一个相应的 .del 文件。当删除请求发送后,文档并没有真的被删除,而是在 .del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在 .del 文件中被标记为删除的文档将不会被写入新段。 95 | 96 | 在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在 .del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。 97 | 98 | #### 10. 详细描述一下ES搜索的过程? 99 | 100 | 搜索被执行成一个两阶段过程,即 Query Then Fetch; 101 | Query阶段: 102 | 查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜索的时候是会查询Filesystem Cache的,但是有部分数据还在Memory Buffer,所以搜索是近实时的。 103 | 每个分片返回各自优先队列中 **所有文档的 ID 和排序值** 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。 104 | Fetch阶段: 105 | 协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。 106 | 107 | #### 11.索引是什么? 108 | 109 | ES集群包含多个索引,每个索引包含一种表,表包含多个文档,并且每个文档包含不同的属性。 110 | 111 | #### 12.请解释什么是分片(SHARDs)? 112 | 113 | 随着索引文件的增加,磁盘容量、处理能力都会变得不够,在这种情况下,将索引数据切分成小段,这就叫分片(SHARDS)。它的出现大大改进了数据查询的效率。 114 | 115 | #### 13.什么是副本(REPLICA), 他的作用是什么? 116 | 117 | 副本是分片的完整拷贝,副本的作用是增加了查询的吞吐率和在极端负载情况下获得高可用的能力。副本有效的帮助处理用户请求。 118 | 119 | #### 14.在ES集群中增加和创建索引的步骤是什么? 120 | 121 | 可以在Kibana中配置新的索引,进行Fields Mapping,设置索引别名。也可以通过HTTP请求来创建索引。 122 | 123 | #### 15.ES支持哪些类型的查询? 124 | 125 | 主要分为匹配(文本)查询和基于Term的查询。 126 | 127 | 文本查询包括基本匹配,match phrase, multi-match, match phrase prefix, common terms, query-string, simple query string. 128 | 129 | Term查询,比如term exists, type, term set, range, prefix, ids, wildcard, regexp, and fuzzy。 130 | 131 | #### 16.Elasticsearch在部署时,对Linux的设置有哪些优化方法 132 | 133 | `面试官`:想了解对ES集群的运维能力。 `解答`: 134 | 135 | - 1)关闭缓存swap; 136 | - 2)堆内存设置为:Min(节点内存/2, 32GB); 137 | - 3)设置最大文件句柄数; 138 | - 4)线程池+队列大小根据业务需要做调整; 139 | - 5)磁盘存储raid方式——存储有条件使用RAID10,增加单节点性能以及避免单节点存储故障。 140 | 141 | #### 17.什么是ElasticSearch中的编译器? 142 | 143 | 编译器用于将字符串分解为术语或标记流。一个简单的编译器可能会将字符串拆分为任何遇到空格或标点的地方。Elasticsearch有许多内置标记器,可用于构建自定义分析器。 144 | 145 | #### 18.拼写纠错是如何实现的? 146 | 147 | 1、拼写纠错是基于编辑距离来实现;编辑距离是一种标准的方法,它用来表示经过插入、删除和替换操作从一个字符串转换到另外一个字符串的最小操作步数; 148 | 149 | 150 | 151 | 2、编辑距离的计算过程:比如要计算 batyu 和 beauty 的编辑距离,先创建一个7×8 的表(batyu 长度为 5,coffee 长度为 6,各加 2),接着,在如下位置填入黑色数字。其他格的计算过程是取以下三个值的最小值: 152 | 153 | 154 | 155 | 如果最上方的字符等于最左方的字符,则为左上方的数字。否则为左上方的数字+1。(对于 3,3 来说为 0) 156 | 157 | 左方数字+1(对于 3,3 格来说为 2) 158 | 159 | 上方数字+1(对于 3,3 格来说为 2) 160 | 161 | 162 | 163 | 最终取右下角的值即为编辑距离的值 3。 164 | 165 | 166 | 167 | ![img](http://res.mianshigee.com/upload/article/20200307/v2-1f5084b94e47d417b3cebd615ef04647_1440w.jpg) 168 | 169 | 170 | 171 | 对于拼写纠错,我们考虑构造一个度量空间(Metric Space),该空间内任何关 172 | 173 | 系满足以下三条基本条件: 174 | 175 | 176 | 177 | d(x,y) = 0 -- 假如 x 与 y 的距离为 0,则 x=y 178 | 179 | d(x,y) = d(y,x) -- x 到 y 的距离等同于 y 到 x 的距离 180 | 181 | d(x,y) + d(y,z) >= d(x,z) -- 三角不等式 182 | 183 | 184 | 185 | 1、根据三角不等式,则满足与 query 距离在 n 范围内的另一个字符转 B,其与 A 186 | 187 | 的距离最大为 d+n,最小为 d-n。 188 | 189 | 190 | 191 | 2、BK 树的构造就过程如下:每个节点有任意个子节点,每条边有个值表示编辑距离。所有子节点到父节点的边上标注 n 表示编辑距离恰好为 n。比如,我们有棵树父节点是”book”和两个子节点”cake”和”books”,”book”到”books”的边标号 1,”book”到”cake”的边上标号 4。从字典里构造好树后,无论何 192 | 193 | 时你想插入新单词时,计算该单词与根节点的编辑距离,并且查找数值为d(neweord, root)的边。递归得与各子节点进行比较,直到没有子节点,你就可以创建新的子节点并将新单词保存在那。比如,插入”boo”到刚才上述例子的树中,我们先检查根节点,查找 d(“book”, “boo”) = 1 的边,然后检查标号为1 的边的子节点,得到单词”books”。我们再计算距离 d(“books”, “boo”)=2,则将新单词插在”books”之后,边标号为 2。 194 | 195 | 196 | 197 | 3、查询相似词如下:计算单词与根节点的编辑距离 d,然后递归查找每个子节点标号为 d-n 到 d+n(包含)的边。假如被检查的节点与搜索单词的距离 d 小于 n,则返回该节点并继续查询。比如输入 cape 且最大容忍距离为 1,则先计算和根的编辑距离 d(“book”, “cape”)=4,然后接着找和根节点之间编辑距离为 3 到5 的,这 198 | 199 | 个就找到了 cake 这个节点,计算 d(“cake”, “cape”)=1,满足条件所以返回 **cake**,然后再找和 cake 节点编辑距离是 0 到 2 的,分别找到 cape 和cart 节点,这样就得到 **cape** 这个满足条件的结果。 200 | 201 | 202 | 203 | 204 | 205 | ![img](http://res.mianshigee.com/upload/article/20200307/v2-d5426155b3c3c0a7e49123954f96e347_1440w.jpg) 206 | 207 | 208 | 209 | #### 19.ElasticSearch中的分析器是什么? 210 | 211 | 在ElasticSearch中索引数据时,数据由为索引定义的Analyzer在内部进行转换。 分析器由一个Tokenizer和零个或多个TokenFilter组成。编译器可以在一个或多个CharFilter之前。分析模块允许您在逻辑名称下注册分析器,然后可以在映射定义或某些API中引用它们。 212 | 213 | Elasticsearch附带了许多可以随时使用的预建分析器。或者,您可以组合内置的字符过滤器,编译器和过滤器器来创建自定义分析器。 214 | 215 | #### 20.是否了解字典树? 216 | 217 | 常用字典数据结构如下所示: 218 | 219 | 220 | 221 | ![img](http://res.mianshigee.com/upload/article/20200307/v2-aa1a57bbbcbbf04ef089d6681d662ffe_1440w.jpg) 222 | 223 | 224 | 225 | Trie 的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。它有 3 个基本性质: 226 | 227 | 1、根节点不包含字符,除根节点外每一个节点都只包含一个字符。 228 | 229 | 2、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 230 | 231 | 3、每个节点的所有子节点包含的字符都不相同。 232 | 233 | 234 | 235 | ![img](http://res.mianshigee.com/upload/article/20200307/v2-df4c8cd2e2b1dad444a50bab3f6d9bb2_1440w.jpg) 236 | 237 | 1、可以看到,trie 树每一层的节点数是 26^i 级别的。所以为了节省空间,我们还可以用动态链表,或者用数组来模拟动态。而空间的花费,不会超过单词数×单词长度。 238 | 239 | 2、实现:对每个结点开一个字母集大小的数组,每个结点挂一个链表,使用左儿子右兄弟表示法记录这棵树; 240 | 241 | 3、对于中文的字典树,每个节点的子节点用一个哈希表存储,这样就不用浪费太大的空间,而且查询速度上可以保留哈希的复杂度 O(1)。 242 | 243 | #### 21. 在并发情况下,ES如果保证读写一致? 244 | 245 | 可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突; 246 | 另外对于写操作,一致性级别支持quorum/one/all,默认为quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。 247 | 对于读操作,可以设置replication为sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置replication为async时,也可以通过设置搜索请求参数_preference为primary来查询主分片,确保文档是最新版本。 248 | 249 | #### 22. ES对于大数据量(上亿量级)的聚合如何实现? 250 | 251 | Elasticsearch 提供的首个近似聚合是cardinality 度量。它提供一个字段的基数,即该字段的distinct或者unique值的数目。它是基于HLL算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关。 252 | 253 | #### 23. 对于GC方面,在使用ES时要注意什么? 254 | 255 | 1)倒排词典的索引需要常驻内存,无法GC,需要监控data node上segment memory增长趋势。 256 | 2)各类缓存,field cache, filter cache, indexing cache, bulk queue等等,要设置合理的大小,并且要应该根据最坏的情况来看heap是否够用,也就是各类缓存全部占满的时候,还有heap空间可以分配给其他任务吗?避免采用clear cache等“自欺欺人”的方式来释放内存。 257 | 3)避免返回大量结果集的搜索与聚合。确实需要大量拉取数据的场景,可以采用scan & scroll api来实现。 258 | 4)cluster stats驻留内存并无法水平扩展,超大规模集群可以考虑分拆成多个集群通过tribe node连接。 259 | 5)想知道heap够不够,必须结合实际应用场景,并对集群的heap使用情况做持续的监控。 260 | 261 | #### 24. 说说你们公司ES的集群架构,索引数据大小,分片有多少,以及一些调优手段? 262 | 263 | 根据实际情况回答即可,如果是我的话会这么回答: 264 | 我司有多个ES集群,下面列举其中一个。该集群有20个节点,根据数据类型和日期分库,每个索引根据数据量分片,比如日均1亿+数据的,控制单索引大小在200GB以内。  265 | 下面重点列举一些调优策略,仅是我做过的,不一定全面,如有其它建议或者补充欢迎留言。 266 | 部署层面: 267 | 1)最好是64GB内存的物理机器,但实际上32GB和16GB机器用的比较多,但绝对不能少于8G,除非数据量特别少,这点需要和客户方面沟通并合理说服对方。 268 | 2)多个内核提供的额外并发远胜过稍微快一点点的时钟频率。 269 | 3)尽量使用SSD,因为查询和索引性能将会得到显著提升。 270 | 4)避免集群跨越大的地理距离,一般一个集群的所有节点位于一个数据中心中。 271 | 5)设置堆内存:节点内存/2,不要超过32GB。一般来说设置export ES_HEAP_SIZE=32g环境变量,比直接写-Xmx32g -Xms32g更好一点。 272 | 6)关闭缓存swap。内存交换到磁盘对服务器性能来说是致命的。如果内存交换到磁盘上,一个100微秒的操作可能变成10毫秒。 再想想那么多10微秒的操作时延累加起来。不难看出swapping对于性能是多么可怕。 273 | 7)增加文件描述符,设置一个很大的值,如65535。Lucene使用了大量的文件,同时,Elasticsearch在节点和HTTP客户端之间进行通信也使用了大量的套接字。所有这一切都需要足够的文件描述符。 274 | 8)不要随意修改垃圾回收器(CMS)和各个线程池的大小。 275 | 9)通过设置gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time可以在集群重启的时候避免过多的分片交换,这可能会让数据恢复从数个小时缩短为几秒钟。 276 | 索引层面: 277 | 1)使用批量请求并调整其大小:每次批量数据 5–15 MB 大是个不错的起始点。 278 | 2)段合并:Elasticsearch默认值是20MB/s,对机械磁盘应该是个不错的设置。如果你用的是SSD,可以考虑提高到100-200MB/s。如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。另外还可以增加 index.translog.flush_threshold_size 设置,从默认的512MB到更大一些的值,比如1GB,这可以在一次清空触发的时候在事务日志里积累出更大的段。 279 | 3)如果你的搜索结果不需要近实时的准确度,考虑把每个索引的index.refresh_interval 改到30s。 280 | 4)如果你在做大批量导入,考虑通过设置index.number_of_replicas: 0 关闭副本。 281 | 5)需要大量拉取数据的场景,可以采用scan & scroll api来实现,而不是from/size一个大范围。 282 | 存储层面: 283 | 1)基于数据+时间滚动创建索引,每天递增数据。控制单个索引的量,一旦单个索引很大,存储等各种风险也随之而来,所以要提前考虑+及早避免。 284 | 2)冷热数据分离存储,热数据(比如最近3天或者一周的数据),其余为冷数据。对于冷数据不会再写入新数据,可以考虑定期force_merge加shrink压缩操作,节省存储空间和检索效率。 285 | 286 | 287 | 288 | #### 参考 289 | 290 | https://zhuanlan.zhihu.com/p/265399976 291 | 292 | https://www.wenyuanblog.com/blogs/elasticsearch-interview-questions.html 293 | 294 | http://www.mianshigee.com/question -------------------------------------------------------------------------------- /Git.md: -------------------------------------------------------------------------------- 1 | ## Git 2 | 3 | #### 1.什么是Git? 4 | 5 | 我建议你先通过了解 git 的架构再来回答这个问题,如下图所示,试着解释一下这个图: 6 | 7 | - Git 是分布式版本控制系统(DVCS)。它可以跟踪文件的更改,并允许你恢复到任何特定版本的更改。 8 | - 与 SVN 等其他版本控制系统(VCS)相比,其分布式架构具有许多优势,一个主要优点是它不依赖于中央服务器来存储项目文件的所有版本。 9 | - 每个开发人员都可以“克隆”我在图中用“Local repository”标注的存储库的副本,并且在他的硬盘驱动器上具有项目的完整历史记录,因此当服务器中断时,你需要的所有恢复数据都在你队友的本地 Git 存储库中。 10 | - 还有一个中央云存储库,开发人员可以向其提交更改,并与其他团队成员进行共享,如图所示,所有协作者都在提交更改“远程存储库”。 11 | 12 | #### 2.Git 工作流程 13 | 14 | 本章节我们将为大家介绍 Git 的工作流程。 15 | 16 | 一般工作流程如下: 17 | 18 | - 克隆 Git 资源作为工作目录。 19 | - 在克隆的资源上添加或修改文件。 20 | - 如果其他人修改了,你可以更新资源。 21 | - 在提交前查看修改。 22 | - 提交修改。 23 | - 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。 24 | 25 | 下图展示了 Git 的工作流程: 26 | 27 | ![img](https://www.runoob.com/wp-content/uploads/2015/02/git-process.png) 28 | 29 | #### 3.在 Git 中提交的命令是什么? 30 | 31 | 用于写入提交的命令是 **`git commit -a`**。 32 | 33 | 现在解释一下 `-a` 标志, 通过在命令行上加 `-a` 指示 git 提交已修改的所有被跟踪文件的新内容。还要提一下,如果你是第一次需要提交新文件,可以在在 `git commit -a` 之前先 **`git add `**。 34 | 35 | #### 4.什么是 Git 中的“裸存储库”? 36 | 37 | 你应该说明 “工作目录” 和 “裸存储库” 之间的区别。 38 | 39 | Git 中的 “裸” 存储库只包含版本控制信息而没有工作文件(没有工作树),并且它不包含特殊的 `.git` 子目录。相反,它直接在主目录本身包含 `.git` 子目录中的所有内容,其中工作目录包括: 40 | 41 | 1. 一个 `.git` 子目录,其中包含你的仓库所有相关的 Git 修订历史记录。 42 | 2. 工作树,或签出的项目文件的副本。 43 | 44 | #### 5.Git 是用什么语言编写的? 45 | 46 | 你需要说明使用它的原因,而不仅仅是说出语言的名称。我建议你这样回答: 47 | 48 | Git使用 C 语言编写。 GIT 很快,C 语言通过减少运行时的开销来做到这一点。 49 | 50 | #### 6.在Git中,你如何还原已经 push 并公开的提交? 51 | 52 | There can be two answers to this question and make sure that you include both because any of the below options can be used depending on the situation: 1 53 | 这个问题可以有两个答案,你回答时也要保包含这两个答案,因为根据具体情况可以使用以下选项: 54 | 55 | - 删除或修复新提交中的错误文件,并将其推送到远程存储库。这是修复错误的最自然方式。对文件进行必要的修改后,将其提交到我将使用的远程存储库 56 | 57 | ``` 58 | git commit -m "commit message" 59 | ``` 60 | 61 | - 创建一个新的提交,撤消在错误提交中所做的所有更改。可以使用命令: 62 | 63 | ``` 64 | git revert 65 | ``` 66 | 67 | 68 | 69 | #### 7.git pull 和 git fetch 有什么区别? 70 | 71 | `git pull` 命令从中央存储库中提取特定分支的新更改或提交,并更新本地存储库中的目标分支。 72 | 73 | `git fetch` 也用于相同的目的,但它的工作方式略有不同。当你执行 `git fetch` 时,它会从所需的分支中提取所有新提交,并将其存储在本地存储库中的新分支中。如果要在目标分支中反映这些更改,必须在 `git fetch` 之后执行`git merge`。只有在对目标分支和获取的分支进行合并后才会更新目标分支。为了方便起见,请记住以下等式: 74 | 75 |
git pull = git fetch + git merge
76 | 77 | 78 | 79 | #### 8.git中的“staging area”或“index”是什么? 80 | 81 | For this answer try to explain the below diagram as you can see: 82 | 可以通过下图进行解释: 83 | 84 | 在完成提交之前,可以在称为“staging area”或“index”的中间区域中对其进行格式化和审查。从图中可以看出,每个更改首先在暂存区域中进行验证,我将其称为“stage file”,然后将更改提交到存储库。 85 | 86 | ![clipboard.png](https://segmentfault.com/img/bVbtc0c?w=655&h=645) 87 | 88 | ### 9.什么是 git stash? 89 | 90 | 首先应该解释 git stash 的必要性。 91 | 92 | 通常情况下,当你一直在处理项目的某一部分时,如果你想要在某个时候切换分支去处理其他事情,事情会处于混乱的状态。问题是,你不想把完成了一半的工作的提交,以便你以后就可以回到当前的工作。解决这个问题的答案是 git stash。 93 | 94 | 再解释什么是git stash。 95 | 96 | stash 会将你的工作目录,即修改后的跟踪文件和暂存的更改保存在一堆未完成的更改中,你可以随时重新应用这些更改。 97 | 98 | #### 10.什么是git stash drop? 99 | 100 | 通过说明我们使用 `git stash drop` 的目的来回答这个问题。 101 | 102 | `git stash drop` 命令用于删除隐藏的项目。默认情况下,它将删除最后添加的存储项,如果提供参数的话,它还可以删除特定项。 103 | 104 | 下面举个例子。 105 | 106 | 如果要从隐藏项目列表中删除特定的存储项目,可以使用以下命令: 107 | 108 | **git stash list:**它将显示隐藏项目列表,如: 109 | 110 | stash@{0}: WIP on master: 049d078 added the index file 111 | stash@{1}: WIP on master: c264051 Revert “added file_size” 112 | stash@{2}: WIP on master: 21d80a5 added number to log 113 | 114 | 如果要删除名为 stash@{0} 的项目,请使用命令 **git stash drop stash@{0}**。 115 | 116 | #### 11.如何找到特定提交中已更改的文件列表? 117 | 118 | 对于这个问题,不能仅仅是提供命令,还要解释这个命令究竟做了些什么。 119 | 120 | 要获取特定提交中已更改的列表文件,请使用以下命令: 121 | 122 | **git diff-tree -r {hash}** 123 | 124 | 给定提交哈希,这将列出在该提交中更改或添加的所有文件。 `-r` 标志使命令列出单个文件,而不是仅将它们折叠到根目录名称中。 125 | 126 | 你还可以包括下面提到的内容,虽然它是可选的,但有助于给面试官留下深刻印象。 127 | 128 | 输出还将包含一些额外信息,可以通过包含两个标志把它们轻松的屏蔽掉: 129 | 130 | **git diff-tree –no-commit-id –name-only -r {hash}** 131 | 132 | 这里 `-no-commit-id` 将禁止提交哈希值出现在输出中,而 `-name-only` 只会打印文件名而不是它们的路径。 133 | 134 | #### 12.git config 的功能是什么? 135 | 136 | 首先说明为什么我们需要 `git config`。 137 | 138 | git 使用你的用户名将提交与身份相关联。 `git config` 命令可用来更改你的 git 配置,包括你的用户名。 139 | 140 | 下面用一个例子来解释。 141 | 142 | 假设你要提供用户名和电子邮件 ID 用来将提交与身份相关联,以便你可以知道是谁进行了特定提交。为此,我将使用: 143 | 144 | **git config –global user.name "Your Name":** 此命令将添加用户名。 145 | 146 | **git config –global user.email "Your E-mail Address":** 此命令将添加电子邮件ID。 147 | 148 | #### 13.提交对象包含什么? 149 | 150 | Commit 对象包含以下组件,你应该提到以下这三点: 151 | 152 | - 一组文件,表示给定时间点的项目状态 153 | - 引用父提交对象 154 | - SHAI 名称,一个40个字符的字符串,提交对象的唯一标识。 155 | 156 | #### 14.Git的工作区域 157 | 158 | 对于任何一个文件,在 Git 内都只有三种区域:工作区,暂存区和本地仓库。 159 | 160 | `工作区:表示新增或修改了某个文件,但还没有提交保存;` 161 | 162 | `暂存区:表示把已新增或修改的文件,放在下次提交时要保存的清单中;` 163 | 164 | `本地仓库:文件已经被安全地保存在本地仓库中了。` 165 | 166 | #### 15.如果分支是否已合并为master,你可以通过什么手段知道? 167 | 168 | 要知道某个分支是否已合并为master,你可以使用以下命令: 169 | 170 | `git branch –merged` 它列出了已合并到当前分支的分支。 171 | 172 | `git branch –no-merged` 它列出了尚未合并的分支。 173 | 174 | #### 16.什么是SubGit? 175 | 176 | SubGit 是将 SVN 到 Git迁移的工具。它创建了一个可写的本地或远程 Subversion 存储库的 Git 镜像,并且只要你愿意,可以随意使用 Subversion 和 Git。 177 | 178 | 这样做有很多优点,比如你可以从 Subversion 快速一次性导入到 Git 或者在 Atlassian Bitbucket Server 中使用SubGit。我们可以用 SubGit 创建现有 Subversion 存储库的双向 Git-SVN 镜像。你可以在方便时 push 到 Git 或提交 Subversion。同步由 SubGit 完成。 179 | 180 | #### 17. 如何把本地仓库的内容推向一个空的远程仓库? 181 | 182 | 首先确保本地仓库与远程之间是连同的。如果提交失败,则需要进行下面的命令进行连通: 183 | 184 | ``` 185 | git remote add origin XXXX 186 | ``` 187 | 188 | 注意:XXXX是你的远程仓库地址。 如果是第一次推送,则进行下面命令: 189 | 190 | ``` 191 | git push -u origin master 192 | ``` 193 | 194 | 注意:-u 是指定origin为默认主分支 之后的提交,只需要下面的命令: 195 | 196 | ``` 197 | git push origin master 198 | ``` 199 | 200 | #### 18.描述一下你所使用的分支策略? 201 | 202 | 这个问题被要求用Git来测试你的分支经验,告诉他们你在以前的工作中如何使用分支以及它的用途是什么,你可以参考以下提到的要点: 203 | 204 | - 功能分支(Feature branching) 205 | 206 | 要素分支模型将特定要素的所有更改保留在分支内。当通过自动化测试对功能进行全面测试和验证时,该分支将合并到主服务器中。 207 | 208 | - 任务分支(Task branching) 209 | 210 | 在此模型中,每个任务都在其自己的分支上实现,任务键包含在分支名称中。很容易看出哪个代码实现了哪个任务,只需在分支名称中查找任务键。 211 | 212 | - 发布分支(Release branching) 213 | 214 | 一旦开发分支获得了足够的发布功能,你就可以克隆该分支来形成发布分支。创建该分支将会启动下一个发布周期,所以在此之后不能再添加任何新功能,只有错误修复,文档生成和其他面向发布的任务应该包含在此分支中。一旦准备好发布,该版本将合并到主服务器并标记版本号。此外,它还应该再将自发布以来已经取得的进展合并回开发分支。 215 | 216 | 最后告诉他们分支策略因团队而异,所以我知道基本的分支操作,如删除、合并、检查分支等。 217 | 218 | #### 19.Git 工作区、暂存区和版本库 219 | 220 | 我们先来理解下 Git 工作区、暂存区和版本库概念: 221 | 222 | - **工作区:**就是你在电脑里能看到的目录。 223 | - **暂存区:**英文叫 stage 或 index。一般存放在 **.git** 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。 224 | - **版本库:**工作区有一个隐藏目录 **.git**,这个不算工作区,而是 Git 的版本库。 225 | 226 | 下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系: 227 | 228 | ![img](https://www.runoob.com/wp-content/uploads/2015/02/1352126739_7909.jpg) 229 | 230 | - 图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage/index),标记为 "master" 的是 master 分支所代表的目录树。 231 | - 图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。 232 | - 图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。 233 | - 当对工作区修改(或新增)的文件执行 **git add** 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。 234 | - 当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。 235 | - 当执行 **git reset HEAD** 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。 236 | - 当执行 **git rm --cached ** 命令时,会直接从暂存区删除文件,工作区则不做出改变。 237 | - 当执行 **git checkout .** 或者 **git checkout -- ** 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。 238 | - 当执行 **git checkout HEAD .** 或者 **git checkout HEAD ** 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。 239 | 240 | #### 20.打标签 241 | 242 | git tag -a 2.27 -m "release version 201606" 243 | git push origin --tags 244 | 详解:git tag 是命令 245 | -a 0.1.3是增加 名为0.1.3的标签 246 | -m 后面跟着的是标签的注释 247 | 248 | 打标签的操作发生在我们commit修改到本地仓库之后。完整的例子 249 | git add . 250 | git commit -m “fixed some bugs” 251 | git tag -a 0.1.3 -m “Release version 0.1.3″ 252 | 253 | 分享提交标签到远程服务器上 254 | git push origin master 255 | git push origin --tags 256 | –tags参数表示提交所有tag至服务器端,普通的git push origin master操作不会推送标签到服务器端。 257 | 258 | 删除标签的命令 259 | git push origin local_branch:remote_branch 260 | #### 参考 261 | 262 | https://segmentfault.com/a/1190000019315509 263 | 264 | https://www.runoob.com/git/ 265 | 266 | https://www.cnblogs.com/rebackl/p/12990881.html 267 | 268 | https://blog.csdn.net/junwua/article/details/82906002 -------------------------------------------------------------------------------- /IO&NIO.md: -------------------------------------------------------------------------------- 1 | ## IO&NIO 2 | 3 | 4 | 5 | ![image-20200414192748596](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200414192748596.png) 6 | 7 | #### 1.**什么是IO流?** 8 | 9 | 它是一种数据的流从源头流到目的地。比如文件拷贝,输入流和输出流都包括了。输入流从文件中读取数据存储到进程(process)中,输出流从进程中读取数据然后写入到目标文件。 10 | 11 | #### 2.java中有几种类型的流? 12 | 13 | 按照单位大小:字符流、字节流。按照流的方向:输出流、输入流。 14 | 15 | #### 3.字节流和字符流哪个好?怎么选择? 16 | 17 | 1. 缓大多数情况下使用字节流会更好,因为字节流是字符流的包装,而大多数时候 IO 操作都是直接操作磁盘文件,所以这些流在传输时都是以字节的方式进行的(图片等都是按字节存储的) 18 | 2. 如果对于操作需要通过 IO 在内存中频繁处理字符串的情况使用字符流会好些,因为字符流具备缓冲区,提高了性能 19 | 20 | #### 4.读取数据量大的文件时,速度会很慢,如何选择流? 21 | 22 | 字节流时,选择BufferedInputStream和BufferedOutputStream。 23 | 字符流时,选择BufferedReader 和 BufferedWriter 24 | 25 | #### 5. IO模型有几种? 26 | 27 | 阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。 28 | 29 | #### 6.阻塞IO**(blocking IO)** 30 | 31 | 应用程序调用一个IO函数,导致应用程序阻塞,如果数据已经准备好,从内核拷贝到用户空间,否则一直等待下去。一个典型的读操作流程大致如下图,当用户进程调用recvfrom这个系统调用时,kernel就开始了IO的第一个阶段:准备数据,就是数据被拷贝到内核缓冲区中的一个过程(很多网络IO数据不会那么快到达,如没收一个完整的UDP包),等数据到操作系统内核缓冲区了,就到了第二阶段:将数据从内核缓冲区拷贝到用户内存,然后kernel返回结果,用户进程才会解除block状态,重新运行起来。**blocking IO的特点就是在IO执行的两个阶段用户进程都会block住;** 32 | 33 | ![image-20200416135005801](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416135005801.png) 34 | 35 | #### 7.**非阻塞I/O(nonblocking IO)** 36 | 37 | 非阻塞I/O模型,我们把一个套接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,**会大量的占用CPU的时间**。 38 | 39 | ​ 当用户进程发出read操作时,如果kernel中数据还没准备好,那么并不会block用户进程,而是立即返回error,用户进程判断结果是error,就知道数据还没准备好,用户可以再次发read,直到kernel中数据准备好,并且用户再一次发read操作,产生system call,那么kernel 马上将数据拷贝到用户内存,然后返回;所以**nonblocking IO的特点是用户进程需要不断的主动询问kernel数据好了没有。** 40 | 41 |   阻塞IO一个线程只能处理一个IO流事件,要想同时处理多个IO流事件要么多线程要么多进程,这样做效率显然不会高,而非阻塞IO可以一个线程处理多个流事件,只要不停地询所有流事件即可,当然这个方式也不好,当大多数流没数据时,也是会大量浪费CPU资源;为了避免CPU空转,引进代理(select和poll,两种方式相差不大),代理可以观察多个流I/O事件,空闲时会把当前线程阻塞掉,当有一个或多个I/O事件时,就从阻塞态醒过来,把所有IO流都轮询一遍,于是没有IO事件我们的程序就阻塞在select方法处,即便这样依然存在问题,我们从select出只是知道有IO事件发生,却不知道是哪几个流,还是只能轮询所有流,**epoll**这样的代理就可以把哪个流发生怎样的IO事件通知我们;  42 | 43 | ![image-20200416135208788](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416135208788.png) 44 | 45 | #### 8.**I/O多路复用模型(IO multiplexing)** 46 | 47 | I/O多路复用就在于单个进程可以同时处理多个网络连接IO,基本原理就是select,poll,epoll这些个函数会不断轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程,这三个functon会阻塞进程,但和IO阻塞不同,这些函数可以同时阻塞多个IO操作,而且可以同时对多个读操作,写操作IO进行检验,直到有数据到达,才真正调用IO操作函数,调用过程如下图;**所以IO多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中任意一个进入就绪状态,select函数就可以返回。** 48 | 49 |   IO多路复用的优势在于并发数比较高的IO操作情况,可以同时处理多个连接,和bloking IO一样socket是被阻塞的,只不过在多路复用中socket是被select阻塞,而在阻塞IO中是被socket IO给阻塞。 50 | 51 | ![image-20200416135308008](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416135308008.png) 52 | 53 | #### 9.信号驱动I/O模型 54 | 55 | 可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们,通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程继续工作,也就是说它没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们随后既可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已经准备好待处理。**特点:等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等待来自信号处理函数的通知:既可以是数据已准备好被处理,也可以是数据报已准备好被读取** 56 | 57 | ![image-20200416140944940](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416140944940.png) 58 | 59 | #### 10.异步 I/O(asynchronous IO) 60 | 61 | 异步IO告知内核启动某个操作,并让内核在整个操作(包括将内核数据复制到我们自己的缓冲区)完成后通知我们,调用aio_read(Posix异步I/O函数以aio_或lio_开头)函数,给内核传递描述字、缓冲区指针、缓冲区大小(与read相同的3个参数)、文件偏移以及通知的方式,然后系统立即返回。我们的进程不阻塞于等待I/0操作的完成。当内核将数据拷贝到缓冲区后,再通知应用程序。 62 | 63 | 用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了 64 | 65 | ![image-20200416141152742](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416141152742.png) 66 | 67 | #### 11.NIO与IO的区别? 68 | 69 |  NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。 70 | 71 | ![image-20200416143304767](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416143304767.png) 72 | 73 | #### 12.NIO和IO适用场景 74 | 75 |  NIO是为弥补传统IO的不足而诞生的,但是尺有所短寸有所长,**NIO也有缺点,因为NIO是面向缓冲区的操作,每一次的数据处理都是对缓冲区进行的,那么就会有一个问题,在数据处理之前必须要判断缓冲区的数据是否完整或者已经读取完毕,如果没有,假设数据只读取了一部分,那么对不完整的数据处理没有任何意义。**所以每次数据处理之前都要检测缓冲区数据。 76 |   那么NIO和IO各适用的场景是什么呢? 77 |   如果需要管理同时打开的成千上万个连接,这些**连接每次只是发送少量的数据**,例如聊天服务器,这时候用NIO处理数据可能是个很好的选择。 78 |   而如果只**有少量的连接**,而这些连接每次要发送大量的数据,这时候传统的IO更合适。使用哪种处理数据,需要在数据的响应等待时间和检查缓冲区数据的时间上作比较来权衡选择。 79 | 80 | #### 13.NIO核心组件 81 | 82 | channel、buffer、selector 83 | 84 | #### 14.什么是channel 85 | 86 | 一个Channel(通道)代表和某一实体的连接,这个实体可以是文件、网络套接字等。也就是说,通道是Java NIO提供的一座桥梁,用于我们的程序和操作系统底层I/O服务进行交互。 87 | 88 | 通道是一种很基本很抽象的描述,和不同的I/O服务交互,执行不同的I/O操作,实现不一样,因此具体的有FileChannel、SocketChannel等。 89 | 90 | 通道使用起来跟Stream比较像,可以读取数据到Buffer中,也可以把Buffer中的数据写入通道。 91 | 92 | ![image-20200416150623938](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416150623938.png) 93 | 94 | 当然,也有区别,主要体现在如下两点: 95 | 96 | - 一个通道,既可以读又可以写,而一个Stream是单向的(所以分 InputStream 和 OutputStream) 97 | - 通道有非阻塞I/O模式 98 | 99 | #### 15.Java NIO中最常用的通道实现? 100 | 101 | - FileChannel:读写文件 102 | - DatagramChannel: UDP协议网络通信 103 | - SocketChannel:TCP协议网络通信 104 | - ServerSocketChannel:监听TCP连接 105 | 106 | #### 16.Buffer是什么? 107 | 108 | NIO中所使用的缓冲区不是一个简单的byte数组,而是封装过的Buffer类,通过它提供的API,我们可以灵活的操纵数据。 109 | 110 | 与Java基本类型相对应,NIO提供了多种 Buffer 类型,如ByteBuffer、CharBuffer、IntBuffer等,区别就是读写缓冲区时的单位长度不一样(以对应类型的变量为单位进行读写)。 111 | 112 | #### 17.核心Buffer实现有哪些? 113 | 114 | 核心的buffer实现有这些:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer,涵盖了所有的基本数据类型(4类8种,除了Boolean)。也有其他的buffer如MappedByteBuffer。 115 | 116 | #### 18.buffer读写数据基本操作 117 | 118 | 1)、将数据写入buffer 119 | 2)、调用buffer.flip() 120 | 3)、将数据从buffer中读取出来 121 | 4)、调用buffer.clear()或者buffer.compact() 122 | 123 | 在写buffer的时候,buffer会跟踪写入了多少数据,需要读buffer的时候,需要调用flip()来将buffer从写模式切换成读模式,读模式中只能读取写入的数据,而非整个buffer。 124 |   当数据都读完了,你需要清空buffer以供下次使用,可以有2种方法来操作:调用clear() 或者 调用compact()。 125 |   区别:clear方法清空整个buffer,compact方法只清除你已经读取的数据,未读取的数据会被移到buffer的开头,此时写入数据会从当前数据的末尾开始。 126 | 127 | ```java 128 | // 创建一个容量为48的ByteBuffer 129 | ByteBuffer buf = ByteBuffer.allocate(48); 130 | // 从channel中读(取数据然后写)入buffer 131 | int bytesRead = inChannel.read(buf); 132 | // 下面是读取buffer 133 | while (bytesRead != -1) { 134 | buf.flip(); // 转换buffer为读模式 135 | System.out.print((char) buf.get()); // 一次读取一个byte 136 | buf.clear(); //清空buffer准备下一次写入 137 | } 138 | 139 | ``` 140 | 141 | #### 19.Selector是什么? 142 | 143 | Selector(选择器)是一个特殊的组件,用于采集各个通道的状态(或者说事件)。我们先将通道注册到选择器,并设置好关心的事件,然后就可以通过调用select()方法,静静地等待事件发生。 144 | 145 | #### 20.通道可以监听那几个事件? 146 | 147 | 通道有如下4个事件可供我们监听: 148 | 149 | - Accept:有可以接受的连接 150 | - Connect:连接成功 151 | - Read:有数据可读 152 | - Write:可以写入数据了 153 | 154 | #### 21.为什么要用Selector? 155 | 156 | 如果用阻塞I/O,需要多线程(浪费内存),如果用非阻塞I/O,需要不断重试(耗费CPU)。Selector的出现解决了这尴尬的问题,非阻塞模式下,通过Selector,我们的线程只为已就绪的通道工作,不用盲目的重试了。比如,当所有通道都没有数据到达时,也就没有Read事件发生,我们的线程会在select()方法处被挂起,从而让出了CPU资源。 157 | 158 | #### 22.Selector处理多Channel图文说明 159 | 160 | ![image-20200416161430793](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200416161430793.png) 161 | 162 | 163 | 164 | 要使用一个Selector,你要先注册这个Selector的Channels。然后你调用Selector的select()方法。这个方法会阻塞,直到它注册的Channels当中有一个准备好了的事件发生了。当select()方法返回的时候,线程可以处理这些事件,如新的连接的到来,数据收到了等。 165 | 166 | #### 23.代码示例:如何使用流的基本接口来读写文件内容 167 | 168 | ``` 169 | try { 170 | 171 | DataInputStream in = 172 | 173 | new DataInputStream( 174 | 175 | new BufferedInputStream( 176 | 177 | new FileInputStream("Test.java") 178 | 179 | ) 180 | 181 | ); 182 | 183 | while ((currentLine = in.readLine()) != null){ 184 | 185 | System.out.println(currentLine); 186 | 187 | } 188 | 189 | } catch (IOException e){ 190 | 191 | System.err.println("Error: " + e); 192 | 193 | } 194 | ``` 195 | 196 | 197 | 198 | #### 参考: 199 | 200 | https://www.cnblogs.com/sharing-java/p/10791802.html 201 | 202 | https://blog.csdn.net/zengxiantao1994/article/details/88094910 203 | 204 | https://www.cnblogs.com/xueSpring/p/9513266.html 205 | 206 | https://zhuanlan.zhihu.com/p/163506337 207 | 208 | 209 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) -------------------------------------------------------------------------------- /JVM.md: -------------------------------------------------------------------------------- 1 | ## JVM 2 | 3 | 4 | 5 | #### 1.JDK、JRE、JVM关系? 6 | 7 | Jdk (Java Development Kit) : java语言的软件开发包。包括Java运行时环境Jre。 8 | 9 | Jre (Java Runtime Environment) :Java运行时环境,包括Jvm。 10 | 11 | Jvm (Java Virtual Machine) : 12 | 13 | - 一种用于计算机设备的规范。 14 | - Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。 15 | 16 | Jdk包括Jre,Jre包括jvm。 17 | 18 | #### 2.启动程序如何查看加载了哪些类,以及加载顺序? 19 | 20 | java -XX:+TraceClassLoading 具体类 21 | 22 | Java -verbose 具体类 23 | 24 | #### 3. class字节码文件10个主要组成部分? 25 | 26 | - MagicNumber 27 | - Version 28 | - Constant_pool 29 | - Access_flag 30 | - This_class 31 | - Super_class 32 | - Interfaces 33 | - Fields 34 | - Methods 35 | - Attributes 36 | 37 | #### 4.画一下jvm内存结构图? 38 | 39 | ![image-20200424132830267](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200424132830267.png) 40 | 41 | #### 5.程序计数器 42 | 43 | 属于线程私有内存。占用一块非常小的空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的指令的字节码,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器来完成。 44 | 45 | #### 6.Java虚拟机栈 46 | 47 | 属于线程私有内存。它的生命周期与线程相同,虚拟机栈描述的是Java方法执行内存模型;每个方法被执行的时候都会同时创建一个栈桢用于存储局部变量表、操作栈、动态链接、方法出口信息等。每一个方法被调用直至执行完成的过程,就对应着一个栈帧再虚拟机中从入栈到出栈的过程。 48 | 49 | #### 7.本地方法栈 50 | 51 | 本地方法栈与虚拟机栈所发挥的作用是非常相似的,只不过虚拟机栈对虚拟机执行Java方法服务,而本地栈是为虚拟机使用到Native方法服务。 52 | 53 | #### 8.Java堆 54 | 55 | 是Java虚拟机所管理的内存中最大的一块。Java堆事被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 56 | 57 | Tips:但随着JIT编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标亮替换优化技术将会导师一些微妙的变化发生,所有的对象都分配在堆上就不那么绝对了。 58 | 59 | #### 9.方法区 60 | 61 | 是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 62 | 63 | #### 10.运行时常量池? 64 | 65 | 是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息,还有一项是常量池(Constant PoolTable)用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放道方法区的运行时常量池中。 66 | 67 | #### 11.什么时候抛出StackOverflowError? 68 | 69 | 如果线程请求的栈深度大于虚拟机所允许的深度,则抛出StackOverflowError。 70 | 71 | #### 12.Java7和Java8在内存模型上有什么区别? 72 | 73 | Java8取消了永久代,用元空间(Metaspace)代替了,元空间是存在本地内存(Native memory)中。 74 | 75 | #### 13.程序员最关注的两个内存区域? 76 | 77 | 堆(Heap)和栈(Stack),一般大家会把Java内存分为堆内存和栈内存,这是一种比较粗糙的划分方式,但实际上Java内存区域是很复杂的。 78 | 79 | #### 14.直接内存是什么? 80 | 81 | 直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但这部分内存也频繁被实用,也有OutOfMemoryError异常的出现的可能。 82 | 83 | Tips:JDK1.4中加入了NIO(new input/output)类,引入了一种基于通道(Channe)与缓冲区(Buffer)的I/O方式,也可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer的对象作为这块内存的引用进行操作。 84 | 85 | #### 15.除了哪个区域外,虚拟机内存其他运行时区域都会发生OutOfMemoryError? 86 | 87 | 程序计数器。 88 | 89 | #### 16.什么情况下会出现堆内存溢出? 90 | 91 | 堆内存存储对象实例。我们只要不断地创建对象。并保证gc roots到对象之间有可达路径来避免垃圾回收机制清除这些对象。就会在对象数量到达最大。堆容量限制后,产生内存溢出异常。 92 | 93 | #### 17.如何实现一个堆内存溢出? 94 | 95 | ```java 96 | public class Cat { 97 | 98 | public static void main(String[] args) { 99 | List list = new ArrayList(); 100 | while (true) { 101 | list.add(new Cat()); 102 | } 103 | } 104 | 105 | } 106 | ``` 107 | 108 | 109 | 110 | #### 18.空间什么情况下会抛出OutOfMemoryError? 111 | 112 | 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError。 113 | 114 | #### 19.如何实现StrackOverflowError? 115 | 116 | ```java 117 | public static void main(String[] args) { 118 | eat(); 119 | } 120 | 121 | public static void eat () { 122 | eat(); 123 | } 124 | ``` 125 | 126 | #### 20.如何设置直接内存容量? 127 | 128 | 通过 -XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆的最大值一样。 129 | 130 | #### 21.Java堆内存组成? 131 | 132 | ![image-20200424170643045](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200424170643045.png) 133 | 134 | 堆大小 = 新生代 + 老年代。如果是Java8则没有Permanent Generation。 135 | 136 | 其中新生代(Young) 被分为 Eden和S0(from)和S1(to)。 137 | 138 | #### 22.Edem : from : to默认比例是? 139 | 140 | Edem : from : to = 8 : 1 : 1 141 | 142 | 此比例可以通过 –XX:SurvivorRatio 来设定 143 | 144 | #### 23.垃圾标记阶段? 145 | 146 | 在GC执行垃圾回收之前,为了区分对象存活与否,当对象被标记为死亡时,GC才回执行垃圾回收,这个过程就是垃圾标记阶段。 147 | 148 | #### 24.引用计数法? 149 | 150 | 比如对象a,只要任何一个对象引用了a,则a的引用计数器就加1,当引用失效时,引用计数器就减1,当计数器为0时,就可以对其回收。 151 | 152 | 但是无法解决循环引用的问题。 153 | 154 | #### 25.根搜索算法? 155 | 156 | 跟搜索算法是以跟为起始点,按照从上到下的方式搜索被根对象集合所连接的目标对象是否可达(使用根搜索算法后,内存中 的存活对象都会被根对象集合直接或间接连接着),如果目标对象不可达,就意味着该对象己经死亡,便可以在 instanceOopDesc的 Mark World 中将其标记为垃圾对象。 157 | 158 | 在根搜索算法中, 只有能够被根对象集合直接或者间接连接的对象才是存活对象。 159 | 160 | #### 26.JVM中三种常见的垃圾收集算法? 161 | 162 | 标记-清除算法(Mark_Sweep) 163 | 164 | 复制算法(Copying) 165 | 166 | 标记-压缩算法(Mark-Compact) 167 | 168 | #### 27.标记-清除算法? 169 | 170 | 首先标记出所有需要回收的对象,在标记完成后统一回收掉所有的被标记对象。 171 | 172 | ![image-20200424181634238](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200424181634238.png) 173 | 174 | 缺点: 175 | 176 | - 标记和清除的效率都不高。 177 | - 空间问题,清除后产生大量不连续的内存随便。如果有大对象会出现空间不够的现象从而不得不提前触发另一次垃圾收集动作。 178 | 179 | #### 28.复制算法? 180 | 181 | 他将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。 182 | 183 | ![image-20200424183117930](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200424183117930.png) 184 | 185 | 优点: 186 | 187 | 解决了内存碎片问题。 188 | 189 | 缺点: 190 | 191 | 将原来的内存缩小为原来的一半,存活对象越多效率越低。 192 | 193 | #### 29.标记-整理算法? 194 | 195 | 先标记出要被回收的对象,然后让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。解决了复制算法和标记清理算法的问题。 196 | 197 | ![image-20200424184054165](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200424184054165.png) 198 | 199 | #### 30.分代收集算法? 200 | 201 | 当前商业虚拟机的垃圾收集都采用“分代手机算法”,其实就根据对象存活周期的不同将内存划分为几块,一般是新老年代。根据各个年代的特点采用最适当的收集算法。 202 | 203 | #### 31.垃圾收集器? 204 | 205 | 如果说垃圾收集算法是方法论,那么垃圾收集器就是具体实现。连线代表可以搭配使用。 206 | 207 | ![image-20200424191253710](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200424191253710.png) 208 | 209 | 210 | 211 | #### 32.Stop The World? 212 | 213 | 进行垃圾收集时,必须暂停其他所有工作线程,Sun将这种事情叫做"Stop The World"。 214 | 215 | #### 33.Serial收集器? 216 | 217 | 单线程收集器,单线程的含义在于它会 stop the world。垃圾回收时需要stop the world ,直到它收集结束。所以这种收集器体验比较差。 218 | 219 | #### 34.PartNew收集器? 220 | 221 | Serial收集器的多线程版本,除了使用采用并行收回的方式回收内存外,其他行为几乎和Serial没区别。 222 | 223 | 可以通过选项“-XX:+UseParNewGC”手动指定使用 ParNew收集器执行内存回收任务。 224 | 225 | #### 36.Parallel Scavenge? 226 | 227 | 是一个新生代收集器,也是复制算法的收集器,同时也是多线程并行收集器,与PartNew 不同是,它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码 的时间/CPU 总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)), 高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。 228 | 229 | 他可以通过2个参数精确的控制吞吐量,更高效的利用cpu。 230 | 231 | 分别是: -XX:MaxCcPauseMillis 和 -XX:GCTimeRatio 232 | 233 | #### 37.Parallel Old收集器? 234 | 235 | Parallel Scavenge收集器的老年代版本,使用多线程和标记-整理算法。JDK 1.6中才开始提供。 236 | 237 | #### 38.CMS 收集器? 238 | 239 | Concurrent Mar Sweep 收集器是一种以获取最短回收停顿时间为目标的收集器。重视服务的响应速度,希望系统停顿时间最短。采用标记-清除的算法来进行垃圾回收。 240 | 241 | #### 39.CMS垃圾回收的步骤? 242 | 243 | 1. 初始标记 (stop the world) 244 | 245 | 2. 并发标记 246 | 247 | 3. 重新标记 (stop the world) 248 | 249 | 4. 并发清除 250 | 251 | 初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快。 252 | 253 | 并发标记就是进行Gc Roots Tracing的过程。 254 | 255 | 重新标记则是为了修正并发标记期间,因用户程序继续运行而导致的标记产生变动的那一部分对象的标记记录,这个阶段停顿时间一般比初始标记时间长,但是远比并发标记时间短。 256 | 257 | 整个过程中并发标记时间最长,但此时可以和用户线程一起工作。 258 | 259 | #### 41.CMS收集器优点?缺点? 260 | 261 | 优点: 262 | 263 | 并发收集、低停顿 264 | 265 | 缺点: 266 | 267 | - 对cpu资源非常敏感。 268 | - 无法处理浮动垃圾。 269 | - 内存碎片问题。 270 | 271 | #### 42.G1收集器? 272 | 273 | Garbage First 收集器是当前收集器技术发展的最前沿成果。jdk 1.6_update14中提供了 g1收集器。 274 | 275 | G1收集器是基于标记-整理算法的收集器,它避免了内存碎片的问题。 276 | 277 | 可以非常精确控制停顿时间,既能让使用者明确指定一个长度为 M毫秒的时间片段内,消耗在垃圾收集上的时间不多超过N毫秒,这几乎已经是实时java(rtsj)的垃圾收集器特征了。 278 | 279 | #### 42. G1收集器是如何改进收集方式的? 280 | 281 | 极力避免全区域垃圾收集,之前的收集器进行收集的范围都是整个新生代或者老年代。而g1将整个Java堆(包括新生代、老年代)划分为多个大小固定的独立区域,并且跟踪这些区域垃圾堆积程度,维护一个优先级李彪,每次根据允许的收集时间,优先回收垃圾最多的区域。从而获得更高的效率。 282 | 283 | #### 43.虚拟机进程状况工具? 284 | 285 | jps (Jvm process status tool ),他的功能与ps类似。 286 | 287 | 可以列出正在运行的虚拟机进程,并显示执行主类(Main Class,main()函数所在的类)的名称,以及浙西进程的本地虚拟机的唯一ID。 288 | 289 | 语法 : jps [options] [hostid] 290 | 291 | -q 主输出lvmid,省略主类的名称 292 | 293 | -m 输出虚拟机进程启动时传递给主类main()函数的参数 294 | 295 | -l 输出主类全名,如果进程执行是Jar包,输出Jar路径 296 | 297 | -v 输出虚拟机进程启动时JVM参数 298 | 299 | #### 44.虚拟机统计信息工具? 300 | 301 | jstat(JVM Statistics Montoring Tool)是用于监视虚拟机各种运行状态信息命令行工机具。他可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、jit编译等运行数据。 302 | 303 | jstat [option vmid [interval[s|ms] [count]] ] 304 | 305 | interval 查询间隔 306 | 307 | count 查询次数 308 | 309 | 如果不用这两个参数,就默认查询一次。 310 | 311 | option代表用户希望查询的虚拟机信息,主要分3类: 312 | 313 | - 类装载 314 | - 垃圾收集 315 | - 运行期编译状况 316 | 317 | #### 45.jstat 工具主要选项? 318 | 319 | -class 监视类装载、卸载数量、总空间及类装载锁消耗的时间 320 | 321 | -gc 监视Java堆状况,包括Eden区,2个survivor区、老年代 322 | 323 | -gccapacity 监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用的最大和最小空间 324 | 325 | -gcutil 监视内容与-gc基本相同,主要关注已经使用空间站空间百分比 326 | 327 | -gccause 与-gcutil 功能一样,但是会额外输出导致上一次GC产生的原因 328 | 329 | -gcnew 监视新生代的GC的状况 330 | 331 | -gcnewcapacity 监视内容与 -gcnew基本相同,输出主要关注使用到的最大最小空间 332 | 333 | -gcold 监视老年代的GC情况 334 | 335 | -gcoldcapacity 监控内容与 -gcold基本相同,主要关注使用到的最大最小空间 336 | 337 | -compiler 输出jit 编译器编译过的方法、耗时等信息 338 | 339 | #### 45.配置信息工具? 340 | 341 | jinfo(Configuration Info for Java)的作用是实时地查看和调整虚拟机的各项参数。 342 | 343 | 使用jps 命令的 -v 参数可以查看虚拟机启动时显示指定的参数列表。 344 | 345 | jinfo 语法: jinfo [option] pid 346 | 347 | #### 46.内存映像工具? 348 | 349 | jmap(Memory Map for Java) 命令用于生成堆转储快照(一般称为heapdump或dump文件)。 350 | 351 | 语法 :jmap [option] vmid 352 | 353 | 它还可以查询finalize执行队列,Java堆和永久代的详细信息,如果空间使用率、当前用的是哪种收集器等。 354 | 355 | - -dump 生成Java堆转储快照,其中live自参数说明是否只dump出存活对象 356 | - -finalizerinfo 显示在F -Queue 中等待Finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效 357 | - -heap 显示Java堆详细信息,如使用哪种回收器、参数配置、分代状况。 358 | - -histo 显示堆中对象统计信息、包括类、实例数量和合计容量。 359 | - -F 当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照。 360 | 361 | #### 47.虚拟机堆转存储快照分析工具? 362 | 363 | jhat ( JVM Heap Analysis Tool) 用来分析jmap生成的堆转储快照。 364 | 365 | #### 48.堆栈跟踪工具? 366 | 367 | jstack(Stack Trace for Java) 命令用于生成虚拟机当前时刻的线程快照(一般称为thread dump 或javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因。 368 | 369 | jstack [option] vmid 370 | 371 | -F 当正常输出的请求不被响应时,强制输出线程堆栈 372 | 373 | -l 除堆栈外,显示关于锁的附加信息 374 | 375 | -m 如果调用本地方法的花,可以显示C/C++ 的堆栈 376 | 377 | #### 49.除了命令行,还有什么可视化工具? 378 | 379 | JConsole 和 VisualVM,这两个工具是JDK的正式成员。 380 | 381 | #### 50.类加载过程? 382 | 383 | 加载-》验证-》准备-》解析-》初始化-》使用-》卸载 384 | 385 | 参考: 386 | 387 | - 《深入理解JVM & G1 GC》 388 | 389 | - 《深入理解Java虚拟机:JVM高级特性与最佳实践》 390 | 391 | - 《实战Java虚拟机:JVM故障诊断与性能优化》 392 | 393 | 394 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 395 | 396 | -------------------------------------------------------------------------------- /Java8.md: -------------------------------------------------------------------------------- 1 | #### Java8 2 | 3 | #### 1.阐述 Java 7 和 Java 8 的区别 4 | 5 | 实话说,两者有很多不同。如果你能列出最重要的,应该就足够了。你应该解释 Java 8 中的新功能。想要获得完整清单,请访问官网:Java 8 JDK。 6 | 7 | 你应该知道以下几个重点: 8 | 9 | - **lambda 表达式**,Java 8 版本引入的一个新特性。lambda 表达式允许你将功能当作方法参数或将代码当作数据。lambda 表达式还能让你以更简洁的方式表示只有一个方法的接口 (称为函数式接口) 的实例。 10 | - **方法引用**,为已命名方法提供了易于阅读的 lambda 表达式。 11 | - 默认方法,支持将新功能添加到类库中的接口,并确保与基于这些接口的旧版本的代码的二进制兼容性。 12 | - **重复注解**,支持在同一声明或类型上多次应用同一注解类型。 13 | - **类型注解**,支持在任何使用类型的地方应用注解,而不仅限于声明。此特性与可插入型系统一起使用时,可增强对代码的类型检查。 14 | 15 | #### 2.Java SE 8中最流行和最著名的最新功能是什么? 16 | 17 | Java SE 8最受欢迎和最著名的最新功能包括以下内容: 18 | 19 | 功能接口。集合API增强功能。Lambda表达式。分流器。流API等。 20 | 21 | #### 3.是什么使Java SE 8优于其他? 22 | 23 | Java SE 8具有以下功能,使其优于其他功能: 24 | 25 | 它编写并行代码。它提供了更多可用的代码。它具有改进的性能应用程序。它具有更易读和简洁的代码。它支持编写包含促销的数据库。 26 | 27 | #### 4.在Java SE 8中定义Lambda表达式? 28 | 29 | Lambda表达式是Java SE 8,是匿名函数的名称,该匿名函数有助于接受一组不同的输入参数,并提供各种结果结果。 30 | 31 | #### 5.为什么将Lambda Expression创造为代码块? 32 | 33 | Lambda表达式是作为代码块创造的,因为它没有名称,可以带有或不带有参数和结果。 34 | 35 | #### 6.Lambda表达式和功能接口之间有什么联系? 36 | 37 | 当我们使用Lambda表达式时,这意味着我们正在使用功能接口。因此,它们都是相互关联的。这意味着Lambda表达式是Functional接口的一部分,Functional接口是一个承载各种其他功能和表达式的更大平台。 38 | 39 | #### 7.在Java SE 8中定义Nashorn? 40 | 41 | Nashorn是在Java SE 8的Java平台上使用的最新Javascript处理引擎。 42 | 43 | #### 8.Map和FlatMap流操作之间的主要区别是什么? 44 | 45 | Map和FlatMap流操作之间的主要区别在于,前者将返回值包装在其序数类型内,而后者则没有。 46 | 47 | #### 9.Map和Flat map流操作之间的相似之处是什么? 48 | 49 | Map和FlatMap流操作都是中间流操作,它们接收一个函数并将这些函数应用于流的不同元素。 50 | 51 | #### 10.定义流管道? 52 | 53 | Java SE 8中的流管道用于通过拆分可能在一个流上发生的操作来将操作链接在一起。 54 | 55 | #### 11.什么是使用Stream Pipeline的强制性? 56 | 57 | 使用Stream Pipeline的强制性在于存在终端操作,该操作有助于返回最终值并支持管道的终止。 58 | 59 | #### 12.新日期和时间API的作用是什么? 60 | 61 | 新的日期和时间API是在Java SE 8中的java time软件包下设计的,因此可以避免与JDK或Java.util.date相关的问题。 62 | 63 | #### 13.Java SE 8的核心API类是什么? 64 | 65 | Java SE 8的核心API类包括LocalDate,LocalTime和LocalDateTime。 66 | 67 | #### 14.Metaspace与PermGen相比有什么优势? 68 | 69 | PerGen的大小是固定的,不能动态增长,而Metaspace可以动态增长,并且确实具有任何类型的大小约束。 70 | 71 | #### 15.功能接口和SAM接口之间有什么区别吗? 72 | 73 | 不,功能接口和SAM接口之间没有区别。 SAM接口或单一抽象方法接口是Java SE 8 API中定义的一种功能接口。 74 | 75 | #### 16.接口默认方法和静态方法 76 | 77 | interface IDefaultFunction{ 78 | default void study(){ 79 | System.out.println("什么时候能找到工作"); 80 | } 81 | static void finJob(){ 82 | System.out.println("开始找工作"); 83 | } 84 | } 85 | 86 | 87 | class DefaultFunction implements IDefaultFunction{ 88 | 89 | } 90 | 91 | Java 8用默认方法与静态方法这两个新概念来扩展接口的声明。默认方法与抽象方法不同之处在于抽象方法必须要求实现,但是默认方法则没有这个要求,就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个default关键字即可实现默认方法。为什么要有这个特性?以前当需要修改接口的时候,需要修改全部实现该接口的类。而引进的默认方法的目的是为了解决接口的修改与现有的实现不兼容的问题。 92 | 93 | #### 17.引入了流Stream 94 | 95 | Stream可以链式书写代码,需要几行搞定的代码,Stream可以一行搞定,Stream是使用内部迭代,而且Stream支持并行操作 96 | 97 | @Test 98 | public void streamTest(){ 99 | Listlist = new ArrayList<>(); 100 | list.add(2); 101 | list.add(4); 102 | list.add(5); 103 | list.forEach(integer -> { 104 | System.out.println(integer); 105 | }); 106 | System.out.println("=======分割线========="); 107 | List list2 = list.stream().filter((i)-> i>2).collect(Collectors.toList()); 108 | list2.forEach(i-> System.out.println(i)); 109 | } 110 | 输出 111 | 112 | ``` 113 | 2 114 | 4 115 | 5 116 | =======分割线========= 117 | 4 118 | 5 119 | ``` 120 | 121 | filter:接受lamada表达式,从中截取一符合条件的元素 122 | limit:截流limit(5),表示截取五个元素 123 | skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补 124 | distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素 125 | map--接收Lambda,将元素转换成其他形式或提取信息 126 | 127 | #### 18.可以重复注解 128 | 129 | @Repeatable注解 130 | 131 | #### 19.集合引入了很多parallel开头的并行操作的方法 132 | 133 | 特别是parallelSort,这个将排序拆分很多小的集合,运用多线程进行排序,最后合并,得到最终想要的结果。 134 | 135 | #### 20.日期时间 136 | 137 | Clock 138 | 139 | LocalDate 只保存有ISO-8601日期系统的日期部分,有时区信息 140 | 141 | LocalTime 只保存ISO-8601日期系统的时间部分,没有时区信息 142 | 143 | LocalDateTime类合并了LocalDate和LocalTime,它保存有ISO-8601日期系统的日期和时间,但是没有时区信息 144 | 145 | ZonedDateTime,它保存有ISO-8601日期系统的日期和时间,而且有时区信息 146 | 147 | Duration类,Duration持有的时间精确到纳秒。它让我们很容易计算两个日期中间的差异 148 | 149 | #### 21.Nashorn javascript 引擎 150 | 151 | Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用 152 | 153 | #### 22.Base64 154 | 155 | 新的Base64API也支持URL和MINE的编码解码 156 | 157 | #### 23.并行数组 158 | 159 | Java 8新增加了很多方法支持并行的数组处理**parallelSort()** 160 | 161 | #### 24.并发 162 | 163 | java.util.concurrent.ConcurrentHashMap中加入了一些新方法来支持聚集操作 164 | 165 | java.util.concurrent.ForkJoinPool类中加入了一些新方法来支持共有资源池 166 | 167 | java.util.concurrent.locks.StampedLock类提供一直基于容量的锁,这种锁有三个模型来控制读写操作(它被认为是不太有名的 168 | 169 | java.util.concurrent.locks.ReadWriteLock类的替代者) 170 | 171 | #### 25.什么是Lambda表达式? 172 | 173 | Lambda Expression可以定义为允许用户将方法作为参数传递的匿名函数。这有助于删除大量的样板代码。Lambda函数没有访问修饰符(私有,公共或受保护),没有返回类型声明和没有名称。 174 | 175 | Lambda表达式允许用户将“函数”传递给代码。所以,与以前需要一整套的接口/抽象类想必,我们可以更容易地编写代码。例如,假设我们的代码具有一些复杂的循环/条件逻辑或工作流程。使用lambda表达式,在那些有难度的地方,可以得到很好的解决。 176 | 177 | 178 | 179 | #### 参考 180 | 181 | https://zhuanlan.zhihu.com/p/215758969 182 | 183 | https://baijiahao.baidu.com/s?id=1667297300847848263&wfr=spider&for=pc 184 | 185 | https://blog.csdn.net/wangbiao007/article/details/103229950 186 | 187 | https://www.cnblogs.com/wangwanchao/p/5269648.html -------------------------------------------------------------------------------- /Java基础(下).md: -------------------------------------------------------------------------------- 1 | ## 基础(下) 2 | 3 | #### 1.Java和C++的区别? 4 | 5 | 我知道很多人没学过 C++,但是面试官就是没事喜欢拿咱们 Java 和 C++ 比呀!没办法!!!就算没学过C++,也要记下来! 6 | 7 | 都是面向对象的语言,都支持封装、继承和多态 8 | 9 | Java 不提供指针来直接访问内存,程序内存更加安全 10 | 11 | Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。 12 | 13 | Java 有自动内存管理机制,不需要程序员手动释放无用内存 14 | 15 | #### 2.什么是 Java 程序的主类 应用程序和小程序的主类有何不同? 16 | 17 | 一个程序中可以有多个类,但只能有一个类是主类。在 Java 应用程序中,这个主类是指包含 main()方法的类。而在 Java 小程序中,这个主类是一个继承自系统类 JApplet 或 Applet 的子类。应用程序的主类不一定要求是 public 类,但小程序的主类要求必须是 public 类。主类是 Java 程序执行的入口点。 18 | 19 | #### 3.Java 应用程序与小程序之间有哪些差别? 20 | 21 | 简单说应用程序是从主线程启动(也就是 `main()` 方法)。applet 小程序没有 `main()` 方法,主要是嵌在浏览器页面上运行(调用`init()`或者`run()`来启动),嵌入浏览器这点跟 flash 的小游戏类似。 22 | 23 | #### 4.import java和javax有什么区别? 24 | 25 | 刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来使用。然而随着时间的推移,javax 逐渐地扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包确实太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。 所以,实际上java和javax没有区别。这都是一个名字。 26 | 27 | #### 5.object-c中的协议和java中的接口概念有何不同? 28 | 29 | OC中的协议有2层含义,官方定义为 formal和informal protocol。前者和Java接口一样。 informal protocol中的方法属于设计模式考虑范畴,不是必须实现的,但是如果有实现,就会改变类的属性。 其实关于正式协议,类别和非正式协议我很早前学习的时候大致看过,也写在了学习教程里 “非正式协议概念其实就是类别的另一种表达方式“这里有一些你可能希望实现的方法,你可以使用他们更好的完成工作”。 这个意思是,这些是可选的。比如我门要一个更好的方法,我们就会申明一个这样的类别去实现。然后你在后期可以直接使用这些更好的方法。 这么看,总觉得类别这玩意儿有点像协议的可选协议。" 现在来看,其实protocal已经开始对两者都统一和规范起来操作,因为资料中说“非正式协议使用interface修饰“, 现在我们看到协议中两个修饰词:“必须实现(@requied)”和“可选实现(@optional)”。 30 | 31 | #### 6.Javascipt的本地对象,内置对象和宿主对象 32 | 33 | 本地对象: Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError, 简单来说,本地对象就是 ECMA一262 定义的类. 34 | 35 | 内置对象: ECMA一262 把内置对象(built一in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。 同样是“独立于宿主环境”。根据定义我们似乎很难分清“内置对象”与“本地对象”的区别。而ECMA一262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。 如此就可以理解了。内置对象是本地对象的一种。而其包含的两种对象中,Math对象我们经常用到,可这个Global对象是啥东西呢? Global对象是ECMAScript中最特别的对象,因为实际上它根本不存在,有点玩人的意思。大家要清楚,在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。 类似于isNaN()、parseInt()和parseFloat()方法等,看起来都是函数,而实际上,它们都是Global对象的方法。而且Global对象的方法还不止这些. 36 | 37 | 宿主对象: ECMAScript中的“宿主”就是我们网页的运行环境,即“操作系统”和“浏览器”。所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。所有的BOM和DOM对象都是宿主对象。因为其对于不同的“宿主”环境所展示的内容不同。其实说白了就是,ECMAScript官方未定义的对象都属于宿主对象,因为其未定义的对象大多数是自己通过ECMAScript程序创建的对象。自定义的对象也是宿主对象。 38 | 39 | #### 7.在javascript中什么是伪数组,如何将伪数组转化为标准数组 40 | 41 | 这里把符合以下条件的对象称为伪数组: 42 | 43 | 1,具有length属性 44 | 45 | 2,按索引方式存储数据 46 | 47 | 3,不具有数组的push,pop等方法 伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,不具有数组的push,pop等方法,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数,还有像调用document.getElementsByTagName, document.childNodes之类的,它们返回的NodeList对象都属于伪数组。 48 | 49 | #### 8.请问EJB与JAVA BEAN的区别是什么? 50 | 51 | Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。EnterpriseJava Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理, EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 52 | 53 | #### 9.请你说说Java和PHP的区别? 54 | 55 | PHP暂时还不支持像Java那样JIT运行时编译热点代码,但是PHP具有opcache机制,能够把脚本对应的opcode缓存在内存,PHP7中还支持配置opcache.file_cache导出opcode到文件.第三方的Facebook HHVM也支持JIT.另外PHP官方基于LLVM围绕opcache机制构建的Zend JIT分支也正在开发测试中.在php-src/Zend/bench.php测试显示,PHP JIT分支速度是PHP 5.4的10倍. PHP的库函数用C实现,而Java核心运行时类库(jdk/jre/lib/rt.jar,大于60MB)用Java编写(jdk/src.zip), 所以Java应用运行的时候,用户编写的代码以及引用的类库和框架都要在JVM上解释执行. Java的HotSpot机制,直到有方法被执行10000次才会触发JIT编译, 在此之前运行在解释模式下,以避免出现JIT编译花费的时间比方法解释执行消耗的时间还要多的情况. 56 | 57 | PHP内置模板引擎,自身就是模板语言.而Java Web需要使用JSP容器如Tomcat或第三方模板引擎. 58 | 59 | PHP也可以运行在多线程模式下,比如Apache的event MPM和Facebook的HHVM都是多线程架构.不管是多进程还是多线程的PHP Web运行模式,都不需要PHP开发者关心和控制,也就是说PHP开发者不需要写代码参与进程和线程的管理,这些都由PHP-FPM/HHVM/Apache实现.PHP-FPM进程管理和并发实现并不需要PHP开发者关心,而Java多线程编程需要Java开发者编码参与.PHP一个worker进程崩溃,master进程会自动新建一个新的worker进程,并不会导致PHP服务崩溃.而Java多线程编程稍有不慎(比如没有捕获异常)就会导致JVM崩溃退出.对于PHP-FPM和Apache MOD_PHP来说,服务进程常驻内存,但一次请求释放一次资源,这种内存释放非常彻底. PHP基于引用计数的GC甚至都还没发挥作用程序就已经结束了。 60 | 61 | #### 10.请你谈谈Java中是如何支持正则表达式操作的? 62 | 63 | Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的API进行各种正则表达式操作,如: 64 | 65 | ```java 66 | import java.util.regex.Matcher; 67 | import java.util.regex.Pattern; 68 | class RegExpTest { 69 | public static void main(String[] args) { 70 | String str = "成都市(成华区)(武侯区)(高新区)"; 71 | Pattern p = Pattern.compile(".*?(?=\\()"); 72 | Matcher m = p.matcher(str); 73 | if(m.find()) { 74 | System.out.println(m.group()); 75 | } 76 | } 77 | } 78 | ``` 79 | 80 | #### 11.请你说明一下,在Java中如何跳出当前的多重嵌套循环? 81 | 82 | 在最外层循环前加一个标记如A,然后用break A;可以跳出多重循环。(Java中支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像要避免使用goto一样,应该避免使用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好),根本不能进行字符串的equals比较,否则会产生NullPointerException异常。 83 | 84 | #### 12.请说明Java的接口和C++的虚类的相同和不同处 85 | 86 | 由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。 与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。 87 | 88 | #### 13.请说明Java是否支持多继承? 89 | 90 | Java中类不支持多继承,只支持单继承(即一个类只有一个父类)。 但是java中的接口支持多继承,,即一个子接口可以有多个父接口。(接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)。 91 | 92 | #### 14.请讲讲Java有哪些特性,并举一个和多态有关的例子。 93 | 94 | 封装、继承、多态。多态:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用) 95 | 96 | #### 15.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? 97 | 98 | Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。 99 | 100 | #### 16.请列举一下,在JAVA虚拟机中,哪些对象可作为ROOT对象? 101 | 102 | 虚拟机栈中的引用对象 103 | 104 | 方法区中类静态属性引用的对象 105 | 106 | 方法区中常量引用对象 107 | 108 | 本地方法栈中JNI引用对象 109 | 110 | #### 17.C++,Java,JavaScript这三种语言的区别 111 | 112 | 参考回答: 113 | 114 | 从静态类型还是动态类型来看 115 | 116 | 静态类型,编译的时候就能够知道每个变量的类型,编程的时候也需要给定类型,如Java中的整型int,浮点型float等。C、C++、Java都属于静态类型语言。 117 | 118 | 动态类型,运行的时候才知道每个变量的类型,编程的时候无需显示指定类型,如JavaScript中的var、PHP中的$。JavaScript、Ruby、Python都属于动态类型语言。 119 | 120 | 静态类型还是动态类型对语言的性能有很大影响。 121 | 122 | 对于静态类型,在编译后会大量利用已知类型的优势,如int类型,占用4个字节,编译后的代码就可以用内存地址加偏移量的方法存取变量,而地址加偏移量的算法汇编很容易实现。 123 | 124 | 对于动态类型,会当做字符串通通存下来,之后存取就用字符串匹配。 125 | 126 | 从编译型还是解释型来看 127 | 128 | 编译型语言,像C、C++,需要编译器编译成本地可执行程序后才能运行,由开发人员在编写完成后手动实施。用户只使用这些编译好的本地代码,这些本地代码由系统加载器执行,由操作系统的CPU直接执行,无需其他额外的虚拟机等。 129 | 130 | 源代码=》抽象语法树=》中间表示=》本地代码 131 | 132 | 解释性语言,像JavaScript、Python,开发语言写好后直接将代码交给用户,用户使用脚本解释器将脚本文件解释执行。对于脚本语言,没有开发人员的编译过程,当然,也不绝对。 133 | 134 | 源代码=》抽象语法树=》解释器解释执行。 135 | 136 | 对于JavaScript,随着Java虚拟机JIT技术的引入,工作方式也发生了改变。可以将抽象语法树转成中间表示(字节码),再转成本地代码,如JavaScriptCore,这样可以大大提高执行效率。也可以从抽象语法树直接转成本地代码,如V8 137 | 138 | Java语言,分为两个阶段。首先像C++语言一样,经过编译器编译。和C++的不同,C++编译生成本地代码,Java编译后,生成字节码,字节码与平台无关。第二阶段,由Java的运行环境也就是Java虚拟机运行字节码,使用解释器执行这些代码。一般情况下,Java虚拟机都引入了JIT技术,将字节码转换成本地代码来提高执行效率。 139 | 140 | 注意,在上述情况中,编译器的编译过程没有时间要求,所以编译器可以做大量的代码优化措施。 141 | 142 | 对于JavaScript与Java它们还有的不同: 143 | 144 | 对于Java,Java语言将源代码编译成字节码,这个同执行阶段是分开的。也就是从源代码到抽象语法树到字节码这段时间的长短是无所谓的。 145 | 146 | 对于JavaScript,这些都是在网页和JavaScript文件下载后同执行阶段一起在网页的加载和渲染过程中实施的,所以对于它们的处理时间有严格要求。 147 | 148 | #### 18.java nextLine 与 next 两个方法的区别? 149 | 150 | 1. next 不会接收回车符,tab 或者空格键,在接收有效数据之前会忽略这些符号,若已经读取了有效数据,遇到这些符号会直接退出 151 | 2. nextLine 可以接收空格或者 tab 键,其输入以 enter 键结束 152 | 153 | #### 19.什么是 JavaConfig? 154 | 155 | Spring JavaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯Java 方法。因此它有助于避免使用 XML 配置。使用 JavaConfig 的优点在于: 156 | 157 | (1)面向对象的配置。由于配置被定义为 JavaConfig 中的类,因此用户可以充分利用 Java 中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean 方法等。 158 | 159 | (2)减少或消除 XML 配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在 XML 和 Java 之间来回切换。JavaConfig 为开发人员提供了一种纯 Java 方法来配置与 XML 配置概念相似的 Spring 容器。从技术角度来讲,只使用 JavaConfig 配置类来配置容器是可行的,但实际上很多人认为将JavaConfig 与 XML 混合匹配是理想的。 160 | 161 | (3)类型安全和重构友好。JavaConfig 提供了一种类型安全的方法来配置 Spring容器。由于 Java 5.0 对泛型的支持,现在可以按类型而不是按名称检索 bean,不需要任何强制转换或基于字符串的查找。 162 | 163 | #### 20.停止非循环Java线程 164 | 165 | 这可能是我误读了我所读内容的一种情况,但是在Java中杀死线程的所有示例似乎都表明您必须发出信号以杀死自己。您不能在没有严重风险的情况下从外面杀死它。问题是,所有有关如何“礼貌地”要求线程死亡的示例都有某种循环,因此您要做的就是观察每次迭代中的标志。 166 | 167 | 因此,我得到的是一个线程,该线程执行的操作仅需要一段时间(一系列SQL查询)。我当然可以在每个步骤之后进行检查,但是它们并没有处于循环中,并且我没有一种非常优雅的方式可以解决此问题。这是我正在做的事的一个例子: 168 | 169 | ``` 170 | new Thread(new Runnable(){ 171 | public void run(){ 172 | //query 1 173 | Connection conn = db.getConnection(); 174 | Statement s = conn.createStatement(); 175 | ResultSet rs = s.executeQuery("SELECT ..."); 176 | while(rs.next()){ 177 | //do stuff 178 | } 179 | 180 | //query 2 181 | rs = s.executeQuery("SELECT ..."); 182 | while(rs.next()){ 183 | //do stuff 184 | } 185 | 186 | //query 3 187 | rs = s.executeQuery("SELECT ..."); 188 | while(rs.next()){ 189 | //do stuff 190 | } 191 | } 192 | }).start(); 193 | ``` 194 | 195 | 这是一个示例,我没有使用匿名内部类,但是它说明了我的run()方法无法优雅地停止自身。此外,即使我在每个步骤之后都进行检查,如果特定查询需要很长时间才能运行,则该代码将无法在查询完成后停止。 196 | 197 | 这段代码是针对GUI应用程序的,我真的很想找到一种无需使用Thread.stop()即可快速杀死线程的好方法。 198 | 199 | **编辑** 200 | -yshavit的回答很有帮助,因为我不知道它的`Statement.cancel()`存在。如果您感到好奇,那么对我的特定问题的答案是建立一个更抽象的数据库访问类。该类必须创建一个子线程以在运行时执行查询和循环,并检查每次迭代是否当前线程(不是子线程)被中断。如果确实被中断,它将仅调用Statement.cancel(),并且子线程将引发异常并死亡。并非所有的JDBC驱动程序都支持`Statement.cancel()`,但是Oracle 201 | 11g支持。 202 | 203 | 204 | 205 | #### 21.在java中使用最简单的方法打印数组内容? 206 | 207 | 从Java 5开始,你可以将Arrays.toString(arr)或Arrays.deepToString(arr)用于数组中的数组。 208 | 请注意,Object[]版本会调用.toString()数组中的每个对象。输出甚至按照您的要求进行修饰。 209 | 210 | **例子:** 211 | 212 | 简单数组: 213 | 214 | ``` 215 | String[] array = new String[] {"John", "Mary", "Bob"}; 216 | System.out.println(Arrays.toString(array)); 217 | ``` 218 | 219 | 输出: 220 | 221 | ``` 222 | [John, Mary, Bob] 223 | ``` 224 | 225 | 嵌套数组: 226 | 227 | ``` 228 | String[][] deepArray = new String[][] {{"John", "Mary"}, {"Alice", "Bob"}}; 229 | System.out.println(Arrays.toString(deepArray)); 230 | //output: [[Ljava.lang.String;@106d69c, [Ljava.lang.String;@52e922] 231 | System.out.println(Arrays.deepToString(deepArray)); 232 | ``` 233 | 234 | 输出: 235 | 236 | ``` 237 | [[John, Mary], [Alice, Bob]] 238 | ``` 239 | 240 | double 数组: 241 | 242 | ``` 243 | double[] doubleArray = { 7.0, 9.0, 5.0, 1.0, 3.0 }; 244 | System.out.println(Arrays.toString(doubleArray)); 245 | ``` 246 | 247 | 输出: 248 | 249 | ``` 250 | [7.0, 9.0, 5.0, 1.0, 3.0 ] 251 | ``` 252 | 253 | int 数组: 254 | 255 | ``` 256 | int[] intArray = { 7, 9, 5, 1, 3 }; 257 | System.out.println(Arrays.toString(intArray)); 258 | ``` 259 | 260 | 输出: 261 | 262 | ``` 263 | [7, 9, 5, 1, 3 ] 264 | ``` 265 | 266 | #### 22.为什么打印java对象得到SomeType@2f92e0f4这样的结果? 267 | 268 | ##### 背景 269 | 270 | 所有Java对象都有一个`toString()`方法,当你尝试打印该对象时会调用该方法。 271 | 272 | ``` 273 | System.out.println(myObject); // invokes myObject.toString() 274 | ``` 275 | 276 | 此方法在`Object`类(所有Java对象的超类)中定义。该`Object.toString()`方法返回一个看起来很难看的字符串,该字符串由类的名称,`@`符号和对象的哈希码(十六进制)组成。此代码如下所示: 277 | 278 | ``` 279 | // Code of Object.toString() 280 | public String toString() { 281 | return getClass().getName() + "@" + Integer.toHexString(hashCode()); 282 | } 283 | ``` 284 | 285 | 这样的结果`com.foo.MyType@2f92e0f4`可以解释为: 286 | 287 | - com.foo.MyType -类的名称,即类MyType在package中com.foo。 288 | - @ -将字符串连接在一起 289 | - 2f92e0f4 对象的哈希码。 290 | 291 | 数组类的名称看起来有些不同,这在Javadocs for中得到了很好的解释`Class.getName()`。例如,`[Ljava.lang.String`表示: 292 | 293 | - [-一维数组(相对于[[或[[[等) 294 | - L -数组包含一个类或接口 295 | - java.lang.String -数组中对象的类型 296 | 297 | ##### 自定义输出 298 | 299 | 要在调用时打印不同的内容`System.out.println(myObject)`,必须重写`toString()`自己类中的方法。这是一个简单的例子: 300 | 301 | ``` 302 | public class Person { 303 | private String name; 304 | // constructors and other methods omitted 305 | @Override 306 | public String toString() { 307 | return name; 308 | } 309 | } 310 | ``` 311 | 312 | 现在,如果我们打印一个Person,我们将看到它们的名称,而不是`com.foo.Person@12345678`。 313 | 314 | 请记住,这toString()只是将对象转换为字符串的一种方法。通常,此输出应以简洁明了的方式完全描述你的对象。toString()对于我们的Person班级来说,更好的选择可能是: 315 | 316 | ``` 317 | @Override 318 | public String toString() { 319 | return getClass().getSimpleName() + "[name=" + name + "]"; 320 | } 321 | ``` 322 | 323 | 将打印,例如`Person[name=Henry]`。这对于调试/测试来说是非常有用的数据。 324 | 325 | 如果你只想关注对象的一个方面或包含许多爵士乐的格式,则最好定义一个单独的方法,例如String toElegantReport() {…}。 326 | 327 | ##### 自动生成输出 328 | 329 | 许多IDEtoString()基于类中的字段提供了对自动生成方法的支持。例如,请参阅Eclipse和IntelliJ的文档。 330 | 331 | 一些流行的Java库也提供此功能。一些示例包括: 332 | 333 | - ToStringBuilder来自Apache Commons Lang 334 | - MoreObjects.ToStringHelper来自Google Guava 335 | - @ToString龙目岛项目的注释 336 | 337 | ##### 打印对象组 338 | 339 | 因此,你已经`toString()`为课程创建了一个不错的选择。如果将该类放入数组或集合,会发生什么情况? 340 | 341 | ##### 数组 342 | 343 | 如果你有一个对象数组,则可以调用Arrays.toString()以生成该数组内容的简单表示。例如,考虑以下Person对象数组: 344 | 345 | ``` 346 | Person[] people = { new Person("Fred"), new Person("Mike") }; 347 | System.out.println(Arrays.toString(people)); 348 | ``` 349 | 350 | // Prints: [Fred, Mike] 351 | 352 | 注意:这是对Arrays类中调用的静态方法的调用toString(),这与我们上面讨论的内容不同。 353 | 354 | 如果你具有多维数组,则可以用于Arrays.deepToString()实现相同类型的输出。 355 | 356 | ##### 集合 357 | 358 | 大多数集合都会基于.toString()对每个元素的调用而产生漂亮的输出。 359 | 360 | ``` 361 | List people = new ArrayList<>(); 362 | people.add(new Person("Alice")); 363 | people.add(new Person("Bob")); 364 | System.out.println(people); 365 | ``` 366 | 367 | // Prints [Alice, Bob] 368 | 因此,你只需要确保列表元素定义一个`toString()`如上所述的尼斯。 369 | 370 | #### 23.如何理解和使用Java中的增强型for循环foreach? 371 | 372 | ``` 373 | for (Iterator i = someIterable.iterator(); i.hasNext();) { 374 | String item = i.next(); 375 | System.out.println(item); 376 | } 377 | ``` 378 | 379 | 请注意,如果你需要`i.remove()`;在循环中使用或以某种方式访问实际的迭代器,则不能使用该`for(:)`惯用语,因为实际的迭代器只是推断出来的。 380 | 381 | 正如Denis Bueno所指出的那样,此代码适用于实现该Iterable接口的任何对象。 382 | 383 | 同样,如果`for(:)`习惯用法的右侧是一个`array`而不是一个`Iterable`对象,则内部代码将使用一个`int`索引计数器并进行检查`array.length`。请参阅Java语言规范。 384 | 385 | #### 24.在java中为什么 1/3 == 0? 386 | 387 | 运行下面的代码结果为0? 388 | 389 | ``` 390 | public static void main(String[] args) { 391 | double g = 1 / 3; 392 | System.out.printf("%.2f", g); 393 | } 394 | ``` 395 | 396 | #### 25.Java 7中的菱形运算符(<>)有什么意义? 397 | 398 | Java 7中的菱形运算符允许如下代码: 399 | 400 | ``` 401 | List list = new LinkedList<>(); 402 | ``` 403 | 404 | 但是,在Java 5/6中,我可以简单地编写: 405 | 406 | ``` 407 | List list = new LinkedList(); 408 | ``` 409 | 410 | 我对类型擦除的理解是这些完全相同。(无论如何,泛型都会在运行时删除)。 411 | 412 | ``` 413 | List list = new LinkedList(); 414 | ``` 415 | 416 | 是在左侧,你使用的是通用类型`List`,而在右侧,你使用的是原始类型LinkedList。Java中的原始类型实际上仅存在于与前泛型代码的兼容性,并且除非绝对必要,否则绝对不能在新代码中使用。 417 | 418 | 现在,如果Java从一开始就具有泛型,并且没有LinkedList最初在具有泛型之前创建的类型(例如),则它可能已经做到了,这样泛型类型的构造函数会自动从左侧推断出其类型参数-尽可能在作业的另一侧。但事实并非如此,为了向后兼容,必须对原始类型和泛型类型进行不同的处理。这使得他们需要采取一种稍微不同但同样方便的方式来声明泛型对象的新实例,而不必重复其类型参数……菱形运算符。 419 | 420 | 就你的原始示例而言`List list = new LinkedList()`,编译器会为该分配生成警告,因为它必须这样做。考虑一下: 421 | 422 | ``` 423 | List strings = ... // some list that contains some strings 424 | 425 | // Totally legal since you used the raw type and lost all type checking! 426 | List integers = new LinkedList(strings); 427 | ``` 428 | 429 | 存在泛型以提供编译时保护以防止做错事。在上面的示例中,使用原始类型意味着你没有获得此保护,并且在运行时会收到错误消息。这就是为什么你不应该使用原始类型的原因。 430 | 431 | ``` 432 | // Not legal since the right side is actually generic! 433 | List integers = new LinkedList<>(strings); 434 | ``` 435 | 436 | 但是,菱形运算符允许将赋值的右侧定义为具有与左侧相同类型参数的真实泛型实例,而不必再次键入这些参数。它使你可以与使用原始类型几乎相同的工作来保持泛型的安全。 437 | 438 | 我认为关键要理解的是,原始类型(不带`<>`)不能与泛型类型相同。声明原始类型时,不会获得任何好处和泛型的类型检查。你还必须记住,泛型是Java语言的通用组成部分 ……它们不仅仅适用于Collections 的无参数构造函数! -------------------------------------------------------------------------------- /Jsp.md: -------------------------------------------------------------------------------- 1 | ## JSP 2 | 3 | #### 1.浏览器jsp,html之间的关系 4 | 5 | 1.JSP与Java Servlet一样,是在服务器端执行的,通常返回该客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览 6 | 7 | 2.在大多数Browser/Server结构的Web应用中,浏览器直接通过HTML或者JSP的形式与用户交互,响应用户的请求 8 | 9 | 3.JSP在服务器上执行,并将执行结果输出到客户端浏览器,我们可以说基本上与浏览器无关 10 | 11 | #### 2.自定义标签要继承哪个类 12 | 13 | 这个类可以继承TagSupport或者BodyTagSupport,两者的差别是前者适用于没有主体的标签,而后者适用于有主体的标签。如果选择继承TagSupport,可以实现doStartTag和doEndTag两个方法实现Tag的功能,如果选择继承BodyTagSupport,可以实现doAfterBody这个方法。 14 | 15 | #### 3. jsp内置对象和作用? 16 | 17 | 有九个内置对象:request、response、out、session、application、pageContext、config、page、exception 18 | 19 | 作用如下: 20 | 21 | (1) HttpServletRequest类的Request对象 22 | 23 | 作用:代表请求对象,主要用于接受客户端通过HTTP协议连接传输到服务器端的数据。 24 | 25 | (2) HttpServletResponse类的Respone对象 26 | 27 | 作用:代表响应对象,主要用于向客户端发送数据 28 | 29 | (3) JspWriter类的out对象 30 | 31 | 作用:主要用于向客户端输出数据; 32 | 33 | ​ Out的基类是JspWriter 34 | 35 | (4) HttpSession类的session对象 36 | 37 | 作用:主要用于来分别保存每个用户信息,与请求关联的会话; 38 | 39 | ​ 会话状态维持是Web应用开发者必须面对的问题。 40 | 41 | (5) ServletContex类的application对象 42 | 43 | 作用:主要用于保存用户信息,代码片段的运行环境; 44 | 45 | ​ 它是一个共享的内置对象,即一个容器中的多个用户共享一个application对象,故其保存的信息被所有用户所共享. 46 | 47 | (6) PageContext类的PageContext对象 48 | 49 | 作用:管理网页属性,为JSP页面包装页面的上下文,管理对属于JSP中特殊可见部分中已命名对象的访问,它的创建和初始化都是由容器来完成的。 50 | 51 | (7) ServletConfig类的Config对象 52 | 53 | 作用:代码片段配置对象,表示Servlet的配置。 54 | 55 | (8) Object类的Page(相当于this)对象 56 | 57 | 作用:处理JSP网页,是Object类的一个实例,指的是JSP实现类的实例,即它也是JSP本身,只有在JSP页面范围之内才是合法的。 58 | 59 | (9)Exception 60 | 61 | 作用:处理JSP文件执行时发生的错误和异常 62 | 63 | #### 4.jsp乱码如何解决,几种解决方案 64 | 65 | 一、JSP页面显示乱码 66 | <%@ page contentType=”text/html; charset=gb2312″%> 67 | 68 | 二、表单提交中文时出现乱码 69 | 70 | request.seCharacterEncoding(̶gb2312″)对请求进行统一编码 71 | 72 | 三、数据库连接出现乱码 73 | 要涉及中文的地方全部是乱码,解决办法:在数据库的数据库URL中加上useUnicode=true&characterEncoding=GBK就OK了。 74 | 75 | 四、通过过滤器完成 76 | 77 | 五、在server.xml中的设置编码格式 78 | 79 | #### 5.页面间对象传递的方法 80 | 81 | request,session,application,cookie等 82 | request.setAttribute(key,value) 83 | session.setAttribute(key,value) 84 | application.setAttribute(key,value) 85 | 86 | #### 6.BS与CS的联系与区别 87 | 88 | B/S模式是指在TCP/IP的支持下,以HTTP为传输协议,客户端通过Browser访问Web服务器以及与之相连的后台数据库的技术及体系结构。它由浏览器、Web服务器、应用服务器和数据库服务器组成。客户端的浏览器通过URL访问Web服务器,Web服务器请求数据库服务器,并将获得的结果以HTML形式返回客户端浏览器。 89 | 90 | c/s在系统机构上和B/S相似,不过需要在客户端安装一个客户端软件,由这个软件对服务器的数据进行读写,就像我们常用的qq,就是这种模式。 91 | 92 | #### 7.描述Jsp页面的运行过程? 93 | 94 | 第一步: 95 | 96 | 请求进入Web容器,将JSP页面翻译成Servlet代码 97 | 98 | 第二步: 99 | 100 | 编译Servlet代码,并将编译过的类文件装入Web容器(JVM)环境 101 | 102 | 第三步: 103 | 104 | Web容器为JSP页面创建一个Servlet类实例,并执行jspInit方法 105 | 106 | 第四步: 107 | 108 | Web容器为该JSP页面调用Servlet实例的_jspService方法;将结果发送给用户 109 | 110 | #### 8.Jsp工作原理 111 | 112 | JSP是一种Servlet,但是与HttpServlet的工作方式不太一样。HttpServlet是先由源代码编译为class文件后部署到服务器下,为先编译后部署。而JSP则是先部署后编译。JSP会在客户端第一次请求JSP文件时被编译为HttpJspPage类(接口Servlet的一个子类)。该类会被服务器临时存放在服务器工作目录里面。 113 | 114 | 由于JSP只会在客户端第一次请求的时候被编译 ,因此第一次请求JSP时会感觉比较慢,之后就会感觉快很多。如果把服务器保存的class文件删除,服务器也会重新编译JSP。 115 | 116 | 开发Web程序时经常需要修改JSP。Tomcat能够自动检测到JSP程序的改动。如果检测到JSP源代码发生了改动。Tomcat会在下次客户端请求JSP时重新编译JSP,而不需要重启Tomcat。 117 | 118 | ```java 119 | 虽然servlet和jsp本质都是servlet,运行时都是运行.class文件,但是它们的部署方式不一样。 120 | servlet是先编译后部署,修改完以后,MyEclipse进行编译,然后部署.class文件到servlet容器中。如果web服务器已启动,则之前的.class文件已被servlet容器加载,修改后的.class文件不会被servlet容器执行。 121 | 而jsp是web服务器进行编译,而不是预先编译好,编译后再加载,tomcat会监视jsp文件的改动,改动之后则重新编译、执行,所以jsp改动时不需要重启服务器。 122 | ``` 123 | 124 | #### 9.Jsp包含的部分 125 | 126 | ``` 127 | 指令: <%@ %> 128 | java小脚本: <% java代码 %> 语句带封号; 129 | 方法声明: <%! %> 130 | 表达式: <%= %> 表达式不带分号; 131 | 注释: <%-- 注释内容 --%> 132 | java中单行,多行 133 | html中 134 | html: 135 | js: 136 | css: 137 | 标签: 138 | ``` 139 | 140 | #### 10.getAttribute()与getParameter() 141 | 142 | **从获取方向来看:** 143 | 144 | `getParameter()`是获取 POST/GET 传递的参数值; 145 | 146 | `getAttribute()`是获取对象容器中的数据值; 147 | 148 | **从用途来看:** 149 | 150 | `getParameter()`用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或url重定向传值时接收数据用。 151 | 152 | `getAttribute()` 用于服务器端重定向时,即在 sevlet 中使用了 forward 函数。getAttribute 只能收到程序用 setAttribute 传过来的值。 153 | 154 | 另外,可以用 `setAttribute()`,`getAttribute()` 发送接收对象.而 `getParameter()` 显然只能传字符串。 155 | `setAttribute()` 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样`getAttribute()`就能取得你所设下的值,当然这种方法可以传对象。session也一样,只是对象在内存中的生命周期不一样而已。`getParameter()`只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值。 156 | 157 | **总结:** 158 | 159 | `getParameter()`返回的是String,用于读取提交的表单中的值;(获取之后会根据实际需要转换为自己需要的相应类型,比如整型,日期类型啊等等) 160 | 161 | `getAttribute()`返回的是Object,需进行转换,可用`setAttribute()`设置成任意对象,使用很灵活,可随时用 162 | 163 | #### 11.静态导入与动态导入 164 | 165 | 静态导入: 166 | 167 | ```java 168 | <%@include file="validate.jsp" %> 169 | 将被导入页面和导入页面,合在一起进行翻译,编译。最后产生一个Servlet,那么两个页面的变量名不能重复。 170 | ``` 171 | 172 | 动态导入: 173 | 174 | ```java 175 | 176 | 动态导入,被导入页面和导入页面分别翻译,编译,产生两个Servlet,所以两个页面的变量名可以重复.都会被执行。 177 | ``` 178 | 179 | #### 12.四种作用域 180 | 181 | SP中的四种作用域包括page、request、session和application,具体来说: 182 | 183 | - **page**代表与一个页面相关的对象和属性。 184 | - **request**代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。 185 | - **session**代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。 186 | - **application**代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。 187 | 188 | #### 13.会话跟踪技术 189 | 190 | **1)使用Cookie** 191 | 192 | 向客户端发送Cookie 193 | 194 | ```java 195 | Cookie c =new Cookie("name","value"); //创建Cookie 196 | c.setMaxAge(60*60*24); //设置最大时效,此处设置的最大时效为一天 197 | response.addCookie(c); //把Cookie放入到HTTP响应中 198 | ``` 199 | 200 | 从客户端读取Cookie 201 | 202 | ```java 203 | String name ="name"; 204 | Cookie[]cookies =request.getCookies(); 205 | if(cookies !=null){ 206 | for(int i= 0;i 233 | ``` 234 | 235 | **优点:** Cookie被禁时可以使用 236 | 237 | **缺点:** 所有页面必须是表单提交之后的结果。 238 | 239 | **4)HttpSession** 240 | 241 | 在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 HttpSession,每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方 法获得HttpSession,通过HttpSession的setAttribute方法可以将一个值放在HttpSession中,通过调用 HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的 是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession 中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了 Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。 242 | 243 | #### 14.<%…%>和<%!…%>的区别 244 | 245 | <%…%>用于在JSP页面中嵌入Java脚本 246 | 247 | <%!…%>用于在JSP页面中申明变量或方法,可以在该页面中的<%…%>脚本中调用,声明的变量相当于Servlet中的定义的成员变量。 248 | 249 | #### 15.描述Jsp页面的指令标记的功能、写法、并示例 250 | 251 | 指令标记影响JSP页面的翻译阶段 252 | 253 | <%@ page session=”false” %> 254 | 255 | <%@ include file=”incl/copyright.html” %> 256 | 257 | <%@ taglib %> 258 | 259 | #### 16.描述Jsp页面的声明标记的功能、写法、并示例 260 | 261 | 声明标记允许JSP页面开发人员包含类级声明 262 | 263 | 写法: 264 | 265 | <%! JavaClassDeclaration %> 266 | 267 | ```text 268 | 例: 269 | 270 | <%! public static final String DEFAULT_NAME = “World”; %> 271 | 272 | <%! public String getName(HttpServletRequest request) { 273 | 274 | return request.getParameter(“name”); 275 | 276 | } 277 | 278 | %> 279 | 280 | <%! int counter = 0; %> 281 | ``` 282 | 283 | #### 17.描述Jsp页面翻译成Servlet的规则 284 | 285 | jsp中的注释标记被翻译成Servlet类中的注释 286 | 287 | jsp中的指令标记被翻译成Servlet类中的import语句等 288 | 289 | jsp中的声明标记被翻译成Servlet类中的属性 290 | 291 | jsp中的脚本标记被转移到Servlet类中service方法中的代码 292 | 293 | jsp中的表达式标记被翻译成Serlvet类中的write()或者print()方法括号中的代码 294 | 295 | #### 18.page指令的功能,写法、并示例,并描述它的如下属性的功能和用法:import、session、buffer、errorPage、isErrorPage、ContentType、pageEncoding 296 | 297 | import : import 定义了一组servlet类定义必须导入的类和包,值是一个由逗号分隔的完全类名或包的列表。 298 | 299 | session : session 定义JSP页面是否参与HTTP会话,值可以为true(缺省)或false。 300 | 301 | buffer : buffer 定义用于输出流(JspWriter对象)的缓冲区大小,值可以为none或Nkb,缺省为8KB或更大。 302 | 303 | errorPage: 用来指定由另一个jsp页面来处理所有该页面抛出的异常 304 | 305 | isErrorPage : 定义JSP页面为其它JSP页面errorPage属性的目标,值为true或false(缺省)。 306 | 307 | ContentType : 定义输出流的MIME类型,缺省为text/html。 308 | 309 | pageEncoding :定义输出流的字符编码,缺省为ISO-8859-1 310 | 311 | #### 19.描述MVC各部分的功能? 312 | 313 | 1.Model 314 | 315 | 封装应用状态 316 | 317 | 响应状态查询 318 | 319 | 暴露应用的功能 320 | 321 | 2.Controller 322 | 323 | 验证HTTP请求的数据 324 | 325 | 将用户数据与模型的更新相映射 326 | 327 | 选择用于响应的视图 328 | 329 | 3.View 330 | 331 | 产生HTML响应 332 | 333 | 请求模型的更新 334 | 335 | 提供HTML form用于用户请求 336 | 337 | #### 20.什么是JavaBean? 338 | 339 | 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码 340 | 341 | 创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其 342 | 343 | 他JavaBean、applet程序或者应用来使用这些对象。 344 | 345 | #### 21.JavaBean的规则? 346 | 347 | 使用get和set方法定义属性 348 | 349 | 一个无参构造方法 350 | 351 | 无public实例变量 352 | 353 | #### 22.什么是jsp标准动作?包含那些?分别都是什么功能?如何使用? 354 | 355 | JSP页面中使用类似于XML的标记表示运行时的动作 356 | 357 | jsp:userBean 358 | 359 | jsp:setProperty 360 | 361 | jsp:getProperty 362 | 363 | jsp:parameter 364 | 365 | jsp:include 366 | 367 | jsp:forward 368 | 369 | #### 23.用代码示例如下标准动作的使用:useBean、getProperty、setProperty 370 | 371 | ```text 372 | 377 | 378 | 379 | 380 | 381 | ``` 382 | 383 | #### 24.描述说明页面上的字段和Bean中属性的对应规则 384 | 385 | id 指javabean的变量名 386 | 387 | class指javabean类的全路径 388 | 389 | scope指javabean的应用范围 390 | 391 | name指所用到的javabean的变量名 392 | 393 | property指javabean中的属性 394 | 395 | #### 25.描述useBean动作的处理过程 396 | 397 | 使用id声明变量 398 | 399 | 试图在指定的范围内查找对象 400 | 401 | 如果没找到 402 | 403 | 创建一个类的实例 404 | 405 | 执行useBean标记体初始化对象 406 | 407 | 如果找到 408 | 409 | 将对象转换为类指定的类型 410 | 411 | #### 参考: 412 | 413 | https://blog.csdn.net/woshizoe2/article/details/78993677 414 | 415 | https://zhuanlan.zhihu.com/p/252313998 416 | 417 | https://www.cnblogs.com/itzlg/p/11380691.html 418 | -------------------------------------------------------------------------------- /Kafka.md: -------------------------------------------------------------------------------- 1 | ## Kafka 2 | 3 | #### 1.什么是kafka? 4 | 5 | Apache Kafka是由Apache开发的一种发布订阅消息系统。 6 | 7 | #### 2.kafka的3个关键功能? 8 | 9 | - 发布和订阅记录流,类似于消息队列或企业消息传递系统。 10 | - 以容错的持久方式存储记录流。 11 | - 处理记录流。 12 | 13 | #### 3.kafka通常用于两大类应用? 14 | 15 | - 建立实时流数据管道,以可靠地在系统或应用程序之间获取数据 16 | - 构建实时流应用程序,以转换或响应数据流 17 | 18 | #### 4.kafka特性? 19 | 20 | 1. 消息持久化 21 | 2. 高吞吐量 22 | 3. 扩展性 23 | 4. 多客户端支持 24 | 5. Kafka Streams 25 | 6. 安全机制 26 | 7. 数据备份 27 | 8. 轻量级 28 | 9. 消息压缩 29 | 30 | #### 5.kafka的5个核心Api? 31 | 32 | - Producer API 33 | 34 | - Consumer API 35 | 36 | - Streams API 37 | 38 | - Connector API 39 | 40 | - Admin API 41 | 42 | #### 6.什么是Broker(代理)? 43 | 44 | Kafka集群中,一个kafka实例被称为一个代理(Broker)节点。 45 | 46 | #### 7.什么是Producer(生产者)? 47 | 48 | 消息的生产者被称为Producer。 49 | 50 | Producer将消息发送到集群指定的主题中存储,同时也自定义算法决定将消息记录发送到哪个分区? 51 | 52 | #### 8.什么是Consumer(消费者)? 53 | 54 | 消息的消费者,从kafka集群中指定的主题读取消息。 55 | 56 | #### 9.什么是Topic(主题)? 57 | 58 | 主题,kafka通过不同的主题却分不同的业务类型的消息记录。 59 | 60 | #### 10.什么是Partition(分区)? 61 | 62 | 每一个Topic可以有一个或者多个分区(Partition)。 63 | 64 | #### 11.分区和代理节点的关系? 65 | 66 | 一个分区只对应一个Broker,一个Broker可以管理多个分区。 67 | 68 | #### 12.什么是副本(Replication)? 69 | 70 | 每个主题在创建时会要求制定它的副本数(默认1)。 71 | 72 | #### 13.什么是记录(Record)? 73 | 74 | 实际写入到kafka集群并且可以被消费者读取的数据。 75 | 76 | 每条记录包含一个键、值和时间戳。 77 | 78 | #### 14.kafka适合哪些场景? 79 | 80 | 日志收集、消息系统、活动追踪、运营指标、流式处理、时间源等。 81 | 82 | #### 15.kafka磁盘选用上? 83 | 84 | SSD的性能比普通的磁盘好,这个大家都知道,实际中我们用普通磁盘即可。它使用的方式多是顺序读写操作,一定程度上规避了机械磁盘最大的劣势,即随机读写操作慢,因此SSD的没有太大优势。 85 | 86 | #### 16.使用RAID的优势? 87 | 88 | - 提供冗余的磁盘存储空间 89 | - 提供负载均衡 90 | 91 | #### 17.磁盘容量规划需要考虑到几个因素? 92 | 93 | - 新增消息数 94 | - 消息留存时间 95 | - 平均消息大小 96 | - 备份数 97 | - 是否启用压缩 98 | 99 | #### 18.Broker使用单个?多个文件目录路径参数? 100 | 101 | log.dirs 多个 102 | 103 | log.dir 单个 104 | 105 | #### 19.一般来说选择哪个参数配置路径?好处? 106 | 107 | log.dirs 108 | 109 | 好处: 110 | 111 | 提升读写性能,多块物理磁盘同时读写高吞吐。 112 | 113 | 故障转移。一块磁盘挂了转移到另一个上。 114 | 115 | #### 20.自动创建主题的相关参数是? 116 | 117 | auto.create.topics.enable 118 | 119 | #### 21.解决kafka消息丢失问题? 120 | 121 | - 不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。 122 | - 设置 acks = all。 123 | - 设置 retries 为一个较大的值。 124 | - 设置 unclean.leader.election.enable = false。 125 | - 设置 replication.factor >= 3。 126 | - 设置 min.insync.replicas > 1。 127 | - 确保 replication.factor > min.insync.replicas。 128 | - 确保消息消费完成再提交。 129 | 130 | #### 22.如何自定分区策略? 131 | 132 | 显式地配置生产者端的参数partitioner.class 133 | 134 | 参数为你实现类的 全限定类名,一般来说实现partition方法即可。 135 | 136 | #### 23.kafka压缩消息可能发生的地方? 137 | 138 | Producer 、Broker。 139 | 140 | #### 24.kafka消息重复问题? 141 | 142 | 做好幂等。 143 | 144 | 数据库方面可以(唯一键和主键)避免重复。 145 | 146 | 在业务上做控制。 147 | 148 | #### 25.你知道的kafka监控工具? 149 | 150 | - JMXTool 工具 151 | - Kafka Manager 152 | - Burrow 153 | - JMXTrans + InfluxDB + Grafana 154 | - Confluent Control Center 155 | 156 | #### 26.kafka follower如何与leader同步数据 157 | 158 | Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。完全同步复制要求All Alive Follower都复制完,这条消息才会被认为commit,这种复制方式极大的影响了吞吐率。而异步复制方式下,Follower异步的从Leader复制数据,数据只要被Leader写入log就被认为已经commit,这种情况下,如果leader挂掉,会丢失数据,kafka使用ISR的方式很好的均衡了确保数据不丢失以及吞吐率。Follower可以批量的从Leader复制数据,而且Leader充分利用磁盘顺序读以及send file(zero copy)机制,这样极大的提高复制性能,内部批量写磁盘,大幅减少了Follower与Leader的消息量差。 159 | 160 | #### 27.什么情况下一个 broker 会从 isr中踢出去 161 | 162 | leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),每个Partition都会有一个ISR,而且是由leader动态维护 ,如果一个follower比一个leader落后太多,或者超过一定时间未发起数据复制请求,则leader将其重ISR中移除 。 163 | 164 | 165 | 166 | #### 参考: 167 | 168 | 《Kafka并不难学》 169 | 170 | 《kafka入门与实践》 171 | 172 | 极客时间:Kafka核心技术与实战 173 | 174 | http://kafka.apache.org/ 175 | 176 | https://blog.csdn.net/qq_28900249/article/details/90346599 177 | 178 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 179 | -------------------------------------------------------------------------------- /Linux.md: -------------------------------------------------------------------------------- 1 | ## Linux 2 | 3 | #### 1.什么是Linux? 4 | 5 | 是一套免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年第一次释出,它主要受到Minix和Unix思想的启发,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。 6 | 7 | #### 2.Linux内核主要负责哪些功能 8 | 9 | - 系统内存管理 10 | - 软件程序管理 11 | - 硬件设备管理 12 | - 文件系统管理 13 | 14 | #### 3.交互方式 15 | 16 | 控制台终端、图形化终端 17 | 18 | #### 4.启动shell 19 | 20 | GNU bash shell能提供对linux 系统的交互式访问。作为普通程序运行,通常在用户登陆终端时启动。登录时系统启动的shell依赖与用户账户的配置。 21 | 22 | #### 5.bash手册 23 | 24 | 大多数linux发行版自带以查找shell命令及其他GNU工具信息的在线手册。man命令用来访问linux系统上的手册页面。当用man命令查看手册,使用分页的程序来现实的。 25 | 26 | #### 6.登陆后你在的位置? 27 | 28 | 一般登陆后,你的位置位于自己的主目录中。 29 | 30 | #### 7.绝对文件路径?相对文件路径?快捷方式? 31 | 32 | 绝对文件路径:描述了在虚拟目录结构中该目录的确切位置,以虚拟目录跟目录开始,相当于目录全名。 33 | 34 | 以正斜线(/)开始,比如 /usr/local。 35 | 36 | 相对文件路径:允许用户执行一个基于当前位置的目标文件路径。 37 | 38 | 比如:当前在/usr/local 39 | 40 | ``` 41 | ➜ local ls 42 | Caskroom Frameworks bin go lib sbin var 43 | Cellar Homebrew etc include opt share 44 | ➜ local cd go 45 | ``` 46 | 47 | 快捷方式(在相对路径中使用): 48 | 49 | 单点符(.) : 表示当前目录; 双点符(..) : 表示当前目录的父目录。 50 | 51 | #### 8.迷路,我的当前位置在哪? 52 | 53 | pwd 显示当前目录 54 | 55 | ``` 56 | [root@iz2ze76ybn73dvwmdij06zz local]# pwd 57 | /usr/local 58 | ``` 59 | 60 | #### 9.如何切换目录? 61 | 62 | 语法: cd destination 63 | 64 | destination : 相对文件路径或绝对文件路径 65 | 66 | 可以跳到存在的任意目录。 67 | 68 | #### 10.如何查看目录中的文件?区分哪些是文件哪些是目录?递归查? 69 | 70 | ls 命令会用最基本的形式显示当前目录下的文件和目录: 71 | 72 | ``` 73 | ➜ local ls 74 | Caskroom Frameworks bin go lib sbin var 75 | Cellar Homebrew etc include opt share 76 | ``` 77 | 78 | 可以看出默认是按照字母序展示的 79 | 80 | 一般来说,ls命令回显示不同的颜色区分不同的文件类型,如果没有安装颜色插件可以用ls -F来区分哪些是目录(目录带/),哪些是文件(文件不带/) 81 | 82 | ls -R 递归展示出目录下以及子目录的文件,目录越多输出越多 83 | 84 | #### 11.创建文件?创建目录?批量创建? 85 | 86 | 创建文件:touch 文件名 87 | 88 | 批量创建文件: touch 文件名 文件名 … 89 | 90 | ``` 91 | ➜ test touch a 92 | ➜ test ls 93 | a 94 | ➜ test touch b c 95 | ➜ test ls 96 | a b c 97 | ``` 98 | 99 | 创建目录:mkdir 目录名 100 | 101 | 批量创建目录: mkdir 目录名 目录名 … 102 | 103 | ``` 104 | ➜ test mkdir aa 105 | ➜ test mkdir bb cc 106 | ➜ test ls 107 | a aa b bb c cc 108 | ➜ test ls -F 109 | a aa/ b bb/ c cc/ 110 | ``` 111 | 112 | #### 12.删除文件?强制删除?递归删除? 113 | 114 | 语法: rm destination 115 | 116 | -i 询问是否删除,-r 递归删除,-f 强制删除。 117 | 118 | rm不能删除有文件的目录,需要递归删除。 119 | 120 | ``` 121 | ➜ xktest rm jdk 122 | rm: jdk: is a directory 123 | ➜ xktest rm -r jdk 124 | ➜ xktest ls 125 | ``` 126 | 127 | rm -i 询问删除,建议大家平时删除多用 -i,确定一下再删除。 128 | 129 | ``` 130 | ➜ xktest touch tomcat 131 | ➜ xktest rm -i tomcat 132 | remove tomcat? n 133 | ``` 134 | 135 | rm -rf 会直接删除,没有警告信息,使用必须谨慎**。 136 | 137 | #### 13.制表符自动补全? 138 | 139 | 有的时候文件的名字很长,很容易拼出错即使拼写对了也很浪费时间。 140 | 141 | ``` 142 | ➜ xktest ls java* 143 | javaxiaokaxiu 144 | ``` 145 | 146 | 比如操作javaxiaokaxiu这个文件时,输入到java的时候,然后按制表键(tab)就会补全成javaxiaokaxiu,是不是方便多了。 147 | 148 | #### 14.复制文件 149 | 150 | 语法: cp source target 151 | 152 | 如果target不存在则直接创建,如果存在,默认不会提醒你是否需要覆盖,需要加-i就会询问你是否覆盖,n否y是。 153 | 154 | ``` 155 | ➜ xktest cp a c 156 | ➜ xktest cp -i a c 157 | overwrite c? (y/n [n]) y 158 | ➜ xktest ls 159 | a c 160 | ``` 161 | 162 | #### 15.重新命名文件?移动文件? 163 | 164 | 语法 : mv soucre target 165 | 166 | 重命名: 167 | 168 | ``` 169 | ➜ xktest ls 170 | ➜ xktest touch java 171 | ➜ xktest ls 172 | java 173 | ➜ xktest mv java java1.8 174 | ➜ xktest ls 175 | java1.8 176 | ``` 177 | 178 | 移动文件: 179 | 180 | 新建jdk目录把java1.8文件移动到jdk目录下。 181 | 182 | ``` 183 | ➜ xktest ls 184 | java1.8 185 | ➜ xktest mkdir jdk 186 | ➜ xktest mv java1.8 jdk 187 | ➜ xktest ls -R 188 | jdk 189 | 190 | ./jdk: 191 | java1.8 192 | ``` 193 | 194 | #### 16.什么是链接文件? 195 | 196 | 如过需要在系统上维护同一文件的两份或者多份副本,除了保存多分单独的物理文件副本之外。还可以采用保存一份物理文件副本和多个虚拟副本的方法,这种虚拟的副本就叫做链接。 197 | 198 | #### 17.查看文件类型?字符编码? 199 | 200 | 语法: file destination 201 | 202 | ``` 203 | ➜ apache file tomcat 204 | tomcat: ASCII text 205 | ``` 206 | 207 | 可以看出,file命令可以显示文件的类型text以及字符编码ASCII 208 | 209 | #### 18.查看整个文件?按照有文本显示行号?无文本显示行号? 210 | 211 | 语法 : cat destination 212 | 213 | -n 显示行号,-b 有文本的显示行号。 (默认是不显示行号的) 214 | 215 | ``` 216 | ➜ apache cat -n tomcat 217 | 1 text 218 | 2 text 219 | 3 220 | 4 start 221 | 5 stop 222 | 6 restart 223 | 7 end 224 | ➜ apache cat -b tomcat 225 | 1 text 226 | 2 text 227 | 228 | 3 start 229 | 4 stop 230 | 5 restart 231 | 6 end 232 | ``` 233 | 234 | #### 19.查看部分文件 235 | 236 | 语法 : tail destination 237 | 238 | 默认情况会展示文件的末尾10行。 -n 行数,显示最后n行。 239 | 240 | ``` 241 | ➜ apache tail -n 2 tomcat 242 | restart 243 | end 244 | ``` 245 | 246 | 语法: head destination 247 | 248 | 默认情况会展示文件的开头10行。 -n 行数,显示开头n行。 249 | 250 | ``` 251 | ➜ apache head -n 2 tomcat 252 | text 253 | text 254 | ``` 255 | 256 | #### 20.数据排序?对数字进行排序?对月份排序? 257 | 258 | 默认情况下,文件的数据展示是按照原顺序展示的。sort命令可以对文本文件中的数据进行排序。sort默认会把数据当成字符处理。 259 | 260 | 语法: sort destination 261 | 262 | sort -n 所以排序数字时需要用-n,它的含义是说当前排序是的数字。 263 | 264 | sort -M 比如月份Jan、Feb、Mar,如果希望它按照月份排序,加入-M就会按照月份的大小来排序。 265 | 266 | #### 21.查找匹配数据?反向搜? 267 | 268 | 语法: grep [options] pattern [file] 269 | 270 | 该命令会查找匹配执行模式的字符串的行,并输出。 271 | 272 | ``` 273 | ➜ apache grep start tomcat 274 | start 275 | restart 276 | ``` 277 | 278 | -v 反向搜 279 | 280 | ``` 281 | ➜ apache grep -v start tomcat 282 | text 283 | text 284 | 285 | stop 286 | end 287 | ``` 288 | 289 | -n 显示行号 290 | 291 | -c 显示匹配的行数 292 | 293 | #### 22.压缩工具有哪些? 294 | 295 | ![image-20200421122324314](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200421122324314.png) 296 | 297 | #### 23.如何压缩文件?如何解压文件? 298 | 299 | 比如以.gz的格式举例。 300 | 301 | 压缩语法: gzip destination 302 | 303 | ``` 304 | ➜ apache gzip tomcat 305 | ➜ apache ls 306 | tomcat.gz 307 | ``` 308 | 309 | 解压语法: gunzip destination 310 | 311 | ``` 312 | ➜ apache gunzip tomcat.gz 313 | ➜ apache ls 314 | tomcat 315 | ``` 316 | 317 | #### 24.Linux广泛使用的归档数据方法? 318 | 319 | 虽然zip命令能压缩和解压单个文件,但是更多的时候广泛使用tar命令来做归档。 320 | 321 | 语法: tar function [options] obj1 obj2 322 | 323 | ![image-20200421122932671](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200421122932671.png) 324 | 325 | ``` 326 | ➜ apache tar -cvf service.tar service1 service2 // 创建规定文件service.tar 327 | a service1 328 | a service2 329 | ➜ apache tar -tf service.tar //查看文件中的目录内容 330 | service1 331 | service2 332 | ➜ apache tar zxvf service.tar //解压 333 | x service1 334 | x service2 335 | ``` 336 | 337 | #### 25.如何查看命令历史记录? 338 | 339 | history 命令可以展示你用的命令的历史记录。 340 | 341 | ``` 342 | 4463 touch service1 service2 343 | 4464 ls 344 | 4465 tar -cvf service.tar service1 service2 345 | 4466 tar -tf service.tar 346 | 4467 tar zxvf service 347 | 4468 tar zxvf service.t 348 | 4469 tar zxvf service.tar 349 | 4470 ls 350 | 4471 tar -zxvf service.tar 351 | 4472 ls 352 | ``` 353 | 354 | #### 26.查看已有别名?建立属于自己的别名? 355 | 356 | alias -p 查看当前可用别名 357 | 358 | ``` 359 | [root@iz2ze76ybn73dvwmdij06zz ~]# alias -p 360 | alias cp='cp -i' 361 | alias egrep='egrep —color=auto' 362 | alias fgrep='fgrep —color=auto' 363 | alias grep='grep —color=auto' 364 | alias l.='ls -d .* —color=auto' 365 | alias ll='ls -l —color=auto' 366 | ``` 367 | 368 | alias li = 'ls -li' 创建别名 369 | 370 | #### 27.什么是环境变量? 371 | 372 | bash shell用一个叫作环境变量(environment variable)的特性来存储有关shell会话和工作环境的信息。这项特性允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。 373 | 374 | 在bash shell中,环境变量分为两类: 375 | 376 | 全局变量:对于 shell会话和所有生成的子shell都是可见的。 局部变量: 只对创建他们的shell可见。 377 | 378 | #### 28.储存用户的文件是?包括哪些信息? 379 | 380 | /etc/passwd存储来一些用户有关的信息。 381 | 382 | ``` 383 | [root@iz2ze76ybn73dvwmdij06zz ~]# cat /etc/passwd 384 | root:x:0:0:root:/root:/bin/bash 385 | bin:x:1:1:bin:/bin:/sbin/nologin 386 | ``` 387 | 388 | 文件信息包括如下内容。 389 | 390 | - 登录用户名 391 | - 用户密码 392 | - 用户账户的UID(数字形式) 393 | - 用户账户的组ID(GID)(数字形式) 394 | - 用户账户的文本描述(称为备注字段) 395 | - 用户HOME目录的位置 396 | - 用户的默认shell 397 | 398 | #### 29.账户默认信息?添加账户?删除用户? 399 | 400 | ``` 401 | [root@iz2ze76ybn73dvwmdij06zz ~]# useradd -D//查看系统默认创建用户信息 402 | GROUP=100 403 | HOME=/home 404 | INACTIVE=-1 405 | EXPIRE= 406 | SHELL=/bin/bash 407 | SKEL=/etc/skel 408 | CREATE_MAIL_SPOOL=yes 409 | [root@iz2ze76ybn73dvwmdij06zz ~]# useradd xiaoka//添加用户 410 | 411 | [root@iz2ze76ybn73dvwmdij06zz /]# userdel xiaoka//删除用户 412 | ``` 413 | 414 | #### 30.查看组信息?如何创建组?删除组? 415 | 416 | ``` 417 | [root@iz2ze76ybn73dvwmdij06zz ~]# cat /etc/group 418 | root:x:0: 419 | bin:x:1: 420 | daemon:x:2: 421 | sys:x:3: 422 | adm:x:4: 423 | tty:x:5: 424 | disk:x:6: 425 | [root@iz2ze76ybn73dvwmdij06zz ~]# groupadd java //创建组 426 | [root@iz2ze76ybn73dvwmdij06zz ~]# groupdel java //创建组 427 | ``` 428 | 429 | #### 31.文件描述符?每个描述符的含义? 430 | 431 | ``` 432 | [root@iz2ze76ybn73dvwmdij06zz xiaoka]# ls -l 433 | 总用量 0 434 | -rw-r—r— 1 root root 0 4月 21 13:17 a 435 | -rw-r—r— 1 root root 0 4月 21 13:17 b 436 | -rw-r—r— 1 root root 0 4月 21 13:17 c 437 | -rw-r—r— 1 root root 0 4月 21 13:17 d 438 | -rw-r—r— 1 root root 0 4月 21 13:17 e 439 | ``` 440 | 441 | 1、文件类型: 442 | 443 | - -代表文件 444 | - d代表目录 445 | - l代表链接 446 | - c代表字符型设备 447 | - b代表块设备 448 | - n代表网络设备 449 | 450 | 2、访问权限符号: 451 | 452 | - r代表对象是可读的 453 | - w代表对象是可写的 454 | - x代表对象是可执行的 455 | 456 | 若没有某种权限,在该权限位会出现单破折线。 457 | 458 | 3、这3组权限分别对应对象的3个安全级别: 459 | 460 | - 对象的属主 461 | - 对象的属组 462 | - 系统其他用户 463 | 464 | #### 31.修改权限? 465 | 466 | chmod options mode file 467 | 468 | 比如给文件附加可以执行权限: 469 | 470 | ``` 471 | [root@xiaoka ~]# chmod +x filename 472 | ``` 473 | 474 | #### 32.如何执行可以执行文件? 475 | 476 | ``` 477 | [root@xiaoka ~]# sh sleep.sh 478 | hello,xiaoka 479 | [root@xiaoka ~]# ./sleep.sh 480 | hello,xiaoka 481 | ``` 482 | 483 | #### 33.列出已经安装的包?安装软件?更新软件?卸载? 484 | 485 | 列出已经安装的包: yum list installed 486 | 487 | 安装软件: yum install package_name 488 | 489 | 更新软件: yum update package_name 490 | 491 | 卸载软件:yum remove package_name //只删除软件包保留数据文件和配置文件 492 | 493 | 如果不希望保留数据文件和配置文件 494 | 495 | 可以执行:yum erase package_name 496 | 497 | #### 34.源码安装通常的路子? 498 | 499 | ``` 500 | tar -zxvf xx.gz //解包 501 | cd xx 502 | ./configure 503 | make 504 | make install 505 | ``` 506 | 507 | #### 35.vim编辑器几种操作模式?基本操作? 508 | 509 | 操作模式: 510 | 511 | - 普通模式 512 | - 插入模式 513 | 514 | 基础操作: 515 | 516 | - h:左移一个字符。 517 | - j:下移一行(文本中的下一行)。 518 | - k:上移一行(文本中的上一行)。 519 | - l:右移一个字符。 520 | 521 | vim提供了一些能够提高移动速度的命令: 522 | 523 | - PageDown(或Ctrl+F):下翻一屏 524 | - PageUp(或Ctrl+B):上翻一屏。 525 | - G:移到缓冲区的最后一行。 526 | - num G:移动到缓冲区中的第num行。 527 | - gg:移到缓冲区的第一行。 528 | 529 | 退出vim: 530 | 531 | - q:如果未修改缓冲区数据,退出。 532 | - q!:取消所有对缓冲区数据的修改并退出。 533 | - w filename:将文件保存到另一个文件中。 534 | - wq:将缓冲区数据保存到文件中并退出。 535 | 536 | #### 36.查看设备还有多少磁盘空间? 537 | 538 | df 可以查看所有已挂在磁盘的使用情况。 539 | 540 | -m 用兆字节,G代替g字节 541 | 542 | ``` 543 | [root@iz2ze76ybn73dvwmdij06zz ~]# df 544 | 文件系统 1K-块 已用 可用 已用% 挂载点 545 | devtmpfs 1931568 0 1931568 0% /dev 546 | tmpfs 1940960 0 1940960 0% /dev/shm 547 | tmpfs 1940960 720 1940240 1% /run 548 | tmpfs 1940960 0 1940960 0% /sys/fs/cgroup 549 | /dev/vda1 41152812 9068544 30180560 24% / 550 | tmpfs 388192 0 388192 0% /run/user/0 551 | ``` 552 | 553 | ###### 快速判断某个特定目录是否有超大文件? 554 | 555 | 默认情况,du会显示当前目录的所有文件、目录、子目录的磁盘使用情况。 556 | 557 | ``` 558 | [root@iz2ze76ybn73dvwmdij06zz src]# du 559 | 4 ./debug 560 | 4 ./kernels 561 | 12 562 | ``` 563 | 564 | #### 37.默认进程信息显示? 565 | 566 | ps它能输出运行在系统上的所有程序的许多信息。 567 | 568 | 默认情况下ps值显示运行在当前控制台下的当前用户的进程。 569 | 570 | ``` 571 | [root@iz2ze76ybn73dvwmdij06zz ~]# ps 572 | PID TTY TIME CMD 573 | 10102 pts/0 00:00:00 bash 574 | 10131 pts/0 00:00:00 ps 575 | ``` 576 | 577 | #### 38.实时监测进程 578 | 579 | 与ps相比,top可以实时监控进程信息。 580 | 581 | ![image-20200421114633852](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200421114633852.png) 582 | 583 | 平均负载有3个值:最近1分钟的、最近5分钟的和最近15分钟的平均负载。值越大说明系统 的负载越高。由于进程短期的突发性活动,出现最近1分钟的高负载值也很常见,但如果近15分 钟内的平均负载都很高,就说明系统可能有问题。 584 | 585 | #### 39.如何中断一个进程? 586 | 587 | 在一个终端中, Ctrl + c 588 | 589 | 通过这个命令许多(不是全部)命令行程序都可以被中断。 590 | 591 | #### 40.如何把一个进程放到后台运行? 592 | 593 | ``` 594 | [root@iz2ze76ybn73dvwmdij06zz ~]# ./sleep.sh & 595 | ``` 596 | 597 | 此时,进程并不能被Ctrl + c 中断。 598 | 599 | #### 41.如何停止一个进程? 600 | 601 | kill命令被用来给程序发送信号。如果没有指定信号,默认发送TERM(终止)信号。 602 | 603 | 语法 : kill [-signal] PID … 604 | 605 | ![image-20200421141556974](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200421141556974.png) 606 | 607 | \#### 608 | 609 | #### 42.验证网络可链接命令是什么?什么原理? 610 | 611 | ping。这个 ping 命令发送一个特殊的网络数据包(叫做 IMCP ECHO REQUEST)到一台指定的主机。大多数接收这个包的网络设备将会回复它,来允许网络连接验证。 612 | 613 | ![image-20200421142307602](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200421142307602.png) 614 | 615 | 一旦启动,ping会持续在特定时间(默认1秒)发送数据包。 616 | 617 | #### 43.查看某端口是否被占用? 618 | 619 | netstat -ntulp|grep 8080 620 | 621 | ``` 622 | [root@iz2ze76ybn73dvwmdij06zz ~]# netstat -ntulp|grep 8080 623 | tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 4517/java 624 | ``` 625 | 626 | 参数说明: 627 | 628 | - -t (tcp) 仅显示tcp相关选项 629 | - -u (udp)仅显示udp相关选项 630 | - -n 拒绝显示别名,能显示数字的全部转化为数字 631 | - -l 仅列出在Listen(监听)的服务状态 632 | - -p 显示建立相关链接的程序名 633 | 634 | #### 44.如何查找匹配的文件?基于文件属性? 635 | 636 | find 程序能基于各种各样的属性,搜索一个给 定目录(以及它的子目录),来查找文件。 637 | 638 | find 命令的最简单使用是,搜索一个或多个目录。 639 | 640 | 普通查找,按照name查找: 641 | 642 | ``` 643 | [root@iz2ze76ybn73dvwmdij06zz ~]# find -name xiaoka 644 | ./xiaoka 645 | ``` 646 | 647 | 文件类型查找: 648 | 649 | 比如,输出我们的家目录文件数量 650 | 651 | ``` 652 | [root@iz2ze76ybn73dvwmdij06zz ~]# find ~|wc -l 653 | 17130 654 | ``` 655 | 656 | 根据文件类型查: 657 | 658 | ``` 659 | [root@iz2ze76ybn73dvwmdij06zz ~]# find ~ -type d | wc -l 660 | 7340 661 | ``` 662 | 663 | find支持的类型: b 块设备文件、 c 字符设备文件、d 目录、f 普通文件、l 符号链接 664 | 665 | #### 45.如何查看当前主机名?如何修改?如何重启后生效? 666 | 667 | ``` 668 | [root@iz2ze76ybn73dvwmdij06zz ~]# hostname//查看当前主机名 669 | iz2ze76ybn73dvwmdij06zz 670 | [root@iz2ze76ybn73dvwmdij06zz ~]# hostname xiaoka//修改当前主机名 671 | [root@iz2ze76ybn73dvwmdij06zz ~]# hostname 672 | xiaoka 673 | ``` 674 | 675 | 大家知道一般来讲命令重启就会失效,目前基本上用的centos7的比较多,两种方式可以支持重启生效。 676 | 677 | 一、命令 678 | 679 | ``` 680 | [root@iz2ze76ybn73dvwmdij06zz ~]# hostnamectl set-hostname xiaoka 681 | [root@iz2ze76ybn73dvwmdij06zz ~]# hostname 682 | xiaoka 683 | [root@xiaoka ~]# 684 | ``` 685 | 686 | 二、修改配置文件:/etc/hostname 687 | 688 | ``` 689 | [root@xiaoka ~]# vim /etc/hostname 690 | ``` 691 | 692 | #### 46.如何写一条规则,拒绝某个ip访问本机8080端口? 693 | 694 | ``` 695 | iptables -I INPUT -s ip -p tcp —dport 8080 -j REJECT 696 | ``` 697 | 698 | #### 47.哪个文件包含了主机名和ip的映射关系? 699 | 700 | /etc/hosts 701 | 702 | #### 48.如何用sed只打印第5行?删除第一行?替换字符串? 703 | 704 | 只打印第5行: 705 | 706 | ``` 707 | ➜ apache sed -n "5p" tomcat 708 | stop 709 | ``` 710 | 711 | 删除第一行: 712 | 713 | ``` 714 | [root@xiaoka ~]# cat story 715 | Long ago a lion and a bear saw a kid. 716 | They sprang upon it at the same time. 717 | The lion said to the bear, “I caught this kid first, and so this is mine.” 718 | [root@xiaoka ~]# cat story 719 | They sprang upon it at the same time. 720 | The lion said to the bear, “I caught this kid first, and so this is mine.” 721 | ``` 722 | 723 | 替换字符串: 724 | 725 | ``` 726 | ➜ apache cat story 727 | Long ago a lion and a bear saw a kid. 728 | They sprang upon it at the same time. 729 | The lion said to the bear, “I caught this kid first, and so this is mine.” 730 | ➜ apache sed 's#this#that#g' story 731 | Long ago a lion and a bear saw a kid. 732 | They sprang upon it at the same time. 733 | The lion said to the bear, “I caught that kid first, and so that is mine.” 734 | ``` 735 | 736 | #### 49.打印文件第一行到第三行? 737 | 738 | ​ 文件tomcat中内容: 739 | 740 | ``` 741 | ➜ apache cat tomcat 742 | text21 743 | text22 744 | text23 745 | start 746 | stop 747 | restart 748 | end 749 | ➜ apache head -3 tomcat 750 | text21 751 | text22 752 | text23 753 | ➜ apache sed -n '1,3p' tomcat 754 | text21 755 | text22 756 | text23 757 | ➜ apache awk 'NR>=1&&NR<=3' tomcat 758 | text21 759 | text22 760 | text23 761 | ``` 762 | 763 | #### 50.如何用awk查看第2行倒数第3个字段? 764 | 765 | ``` 766 | ➜ apache awk 'NR==3{print $(NF-2)}' story 767 | this 768 | ➜ apache cat story 769 | Long ago a lion and a bear saw a kid. 770 | They sprang upon it at the same time. 771 | The lion said to the bear, “I caught this kid first, and so this is mine.” 772 | ``` 773 | 774 | 参考: 775 | 776 | - 《鸟哥Linux私房菜》 777 | 778 | - 《快乐的命令行》 779 | 780 | - 《Linux命令行与shell脚本编程大全(第3版)》 781 | 782 | - 《Linux从入门到精通》 783 | 784 | - 百度百科 785 | 786 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 787 | -------------------------------------------------------------------------------- /Maven.md: -------------------------------------------------------------------------------- 1 | ## Maven 2 | 3 | #### 1.Maven 是什么? 4 | 5 | Maven 主要服务于基于 Java 平台的项目构建、依赖管理和项目信息管理。 6 | 7 | Maven 的主要功能主要分为 5 点: 8 | 9 | - 依赖管理系统 10 | - 多模块构建 11 | - 一致的项目结构 12 | - 一致的构建模型和插件机制 13 | 14 | #### 2.什么选用 Maven 进行构建? 15 | 16 | - 首先,Maven 是一个优秀的项目构建工具。使用 maven,可以很方便的对项目进行分模块构建,这样在开发和测试打包部署时,效率会提高很多。 17 | - 其次,Maven 可以进行依赖的管理。使用 Maven ,可以将不同系统的依赖进行统一管理,并且可以进行依赖之间的传递和继承。 18 | 19 | #### 3. Maven 规约是什么? 20 | 21 | - `/src/main/java/` :Java 源码。 22 | - `/src/main/resource` :Java 配置文件,资源文件。 23 | - `/src/test/java/` :Java 测试代码。 24 | - `/src/test/resource` :Java 测试配置文件,资源文件。 25 | - `/target` :文件编译过程中生成的 `.class` 文件、jar、war 等等。 26 | - `pom.xml` :配置文件 27 | 28 | Maven 要负责项目的自动化构建,以编译为例,Maven 要想自动进行编译,那么它必须知道 Java 的源文件保存在哪里,这样约定之后,不用我们手动指定位置,Maven 能知道位置,从而帮我们完成自动编译。 29 | 30 | 遵循 **“约定>>> 配置 >>> 编码”**。即能进行配置的不要去编码指定,能事先约定规则的不要去进行配置。这样既减轻了劳动力,也能防止出错。 31 | 32 | #### 4.Maven 常用命令 33 | 34 | - `mvn archetype:create` :创建 Maven 项目。 35 | - `mvn compile` :编译源代码。 36 | - `mvn deploy` :发布项目。 37 | - `mvn test-compile` :编译测试源代码。 38 | - `mvn test` :运行应用程序中的单元测试。 39 | - `mvn site` :生成项目相关信息的网站。 40 | - `mvn clean` :清除项目目录中的生成结果。 41 | - `mvn package` :根据项目生成的 jar/war 等。 42 | - `mvn install` :在本地 Repository 中安装 jar 。 43 | - `mvn eclipse:eclipse` :生成 Eclipse 项目文件。 44 | - `mvn jetty:run` 启动 Jetty 服务。 45 | - `mvn tomcat:run` :启动 Tomcat 服务。 46 | - `mvn clean package -Dmaven.test.skip=true` :清除以前的包后重新打包,跳过测试类。 47 | 48 | 用到最多的命令 49 | 50 | - `mvn eclipse:clean` :清除 Project 中以前的编译的东西,重新再来。 51 | - `mvn eclipse:eclipse` :开始编译 Maven 的 Project 。 52 | - `mvn clean package` :清除以前的包后重新打包。 53 | 54 | #### 5.Maven 有哪些优点和缺点 55 | 56 | ##### 1)优点 57 | 58 | - 简化了项目依赖管理。 59 | 60 | 当年,多少人被 SSH 整合搞死搞活,很多时候,是因为依赖不完整,或者版本不正确。自从 Maven 出来后,终于可以无痛了~ 当然,也有一部分功劳是 Spring Boot ,这是后话。 61 | 62 | - 易于上手,对于新手可能一个 `mvn clean package` 命令就可能满足我们的工作。 63 | 64 | - 便于与持续集成工具 (Jenkins) 整合。 65 | 66 | - 便于项目升级,无论是项目本身升级还是项目使用的依赖升级。 67 | 68 | - 有助于多模块项目的开发,一个模块开发好后,发布到仓库,依赖该模块时可以直接从仓库更新,而不用自己去编译。 69 | 70 | - Maven 有很多插件,便于功能扩展,比如生产站点,自动发布版本等。 71 | 72 | ##### 2)缺点 73 | 74 | - Maven 是一个庞大的构建系统,学习难度大。 75 | 76 | 这里的学习,更多指的完整学习。如果基本使用,并不会存在该问题。 77 | 78 | - Maven 采用约定优于配置的策略 (convention over configuration),虽然上手容易,但是一旦出了问题,难于调试。 79 | 80 | 这个确实,略微痛苦。 81 | 82 | - 当依赖很多时,m2eclipse 老是搞得 Eclipse 很卡。 83 | 84 | 使用 IDEA ,而不是 Eclipse ,完美解决。 85 | 86 | - 中国的网络环境差,很多 repository 无法访问,比如 Google Code、 JBoss 仓库无法访问等。 87 | 88 | 这个也好解决,在 `` 中增加阿里巴巴的 Maven 私服,具体可以参见 [《提高 Maven 速度 —— Maven 仓库修改成国内阿里巴巴地址》](https://my.oschina.net/af8991/blog/833513) 文章。 89 | 90 | #### 6.什么是Maven的坐标 91 | 92 | Maven的坐标通过groupId,artifactId,version唯一标志一个构件。groupId通常为公司或组织名字,artifactId通常为项目名称,versionId为版本号。 93 | 94 | #### 7.通过坐标如何定位地址 95 | 96 | 加上groupId为org.codehaus.mojo,artifactId为myproject,versionId为v1.0.0,则对应地址为:仓库目录(.m2)/org/codehaus/mojo/myproject/v1.0.0 97 | 98 | #### 8.Maven的依赖范围有哪些(在scope中指定) 99 | 100 | compile:默认范围,如果未指定任何范围,则使用该范围。编译依赖项在所有(编译,测试,运行)类路径中都可用。此外,这些依赖关系会传播到依赖的项目 101 | 102 | provided:这很像compile,但表示您希望JDK或容器在运行时提供它。它只在编译和测试类路径上可用,不可传递。 103 | 104 | runtime:此范围表示编译不需要依赖项,但需要执行依赖项。它在运行时和测试类路径中,但不在编译类路径中。(servlet-api) 105 | 106 | test:表示应用程序的正常使用不需要依赖项,并且仅在测试编译和执行阶段可用。它不是传递的。(jdbc) 107 | 108 | system:系统依赖范围。该依赖与三种classpath的关系和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植。 109 | 110 | #### 9.Maven生命周期 111 | 112 |  有三套什么周期,分别为clean,default,site 113 | 114 |    clean: 115 | 116 |     此生命周期旨在给工程做清理工作,它主要包含以下阶段: 117 | 118 |     pre-clean - 执行项目清理前所需要的工作。 119 | 120 |     clean - 清理上一次build项目生成的文件。 121 | 122 |     post-clean - 执行完成项目清理所需的工作。 123 | 124 |    default: 125 | 126 |     validate - 验证项目是否正确且所有必要的信息都可用。 127 | 128 |     initialize - 初始化构建工作,如:设置参数,创建目录等。 129 | 130 |     generate-sources - 为包含在编译范围内的代码生成源代码. 131 | 132 |     process-sources - 处理源代码, 如过滤值. 133 | 134 |     generate-resources - 135 | 136 |     process-resources - 复制并处理资源文件,至目标目录,准备打包。 137 | 138 |     compile - 编译项目中的源代码. 139 | 140 |     process-classes - 为编译生成的文件做后期工作, 例如做Java类的字节码增强. 141 | 142 |     generate-test-sources - 为编译内容生成测试源代码. 143 | 144 |     process-test-sources - 处理测试源代码。 145 | 146 |     generate-test-resources - 147 | 148 |     process-test-resources - 复制并处理资源文件,至目标测试目录。 149 | 150 |     test-compile - 将需测试源代码编译到路径。一般来说,是编译/src/test/java目录下的java文件至目标输出的测试classpath目录中。 151 | 152 |     process-test-classes - 153 | 154 |     test - 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。 155 | 156 |     prepare-package - 157 | 158 |     package - 接受编译好的代码,打包成可发布的格式,如 JAR 。 159 | 160 |     pre-integration-test - 161 | 162 |     integration-test - 按需求将发布包部署到运行环境。 163 | 164 |     post-integration-test - 165 | 166 |     verify - 167 | 168 |     install -将包安装到本地仓库,给其他本地引用提供依赖。 169 | 170 |     deploy -完成集成和发布工作,将最终包复制到远程仓库以便分享给其他开发人员。 171 | 172 |    site: 173 | 174 |     pre-site - 执行一些生成项目站点前的准备工作。 175 | 176 |     site - 生成项目站点的文档。 177 | 178 |     post-site - 执行需完成站点生成的工作,如站点部署的准备工作。 179 | 180 |     site-deploy - 向制定的web服务器部署站点生成文件。 181 | 182 | #### 10.Maven命令 183 | 184 |  mvn archetype:generate 创建Maven项目 185 | 186 |    mvn compile 编译源代码 187 | 188 |    mvn deploy 发布项目 189 | 190 |    mvn test-compile 编译测试源代码 191 | 192 |    mvn test 运行应用程序中的单元测试 193 | 194 |    mvn site 生成项目相关信息的网站 195 | 196 |    mvn clean 清除项目目录中的生成结果 197 | 198 |    mvn package 根据项目生成的jar 199 | 200 |    mvn install 在本地Repository中安装jar 201 | 202 |    mvn eclipse:eclipse 生成eclipse项目文件 203 | 204 |    mvn[jetty](https://baike.baidu.com/item/jetty):run 启动jetty服务 205 | 206 |    mvn[tomcat](https://baike.baidu.com/item/tomcat):run 启动tomcat服务 207 | 208 |    mvn clean package -Dmaven.test.skip=true:清除以前的包后重新打包,跳过测试 209 | 210 | #### 11.依赖的解析机制 211 | 212 | 当依赖的范围是 system 的时候,Maven 直接从本地文件系统中解析构件。 213 | 214 | 根据依赖坐标计算仓库路径,尝试直接从本地仓库寻找构件,如果发现对应的构件,就解析成功。 215 | 216 | 如果在本地仓库不存在相应的构件,就遍历所有的远程仓库,发现后,下载并解析使用。 217 | 218 | 如果依赖的版本是 RELEASE 或 LATEST,就基于更新策略读取所有远程仓库的元数据文件(groupId/artifactId/maven-metadata.xml),将其与本地仓库的对应元合并后,计算出 RELEASE 或者 LATEST 真实的值,然后基于该值检查本地仓库,或者从远程仓库下载。 219 | 220 | 如果依赖的版本是 SNAPSHOT,就基于更新策略读取所有远程仓库的元数据文件,将它与本地仓库对应的元数据合并,得到最新快照版本的值,然后根据该值检查本地仓库,或从远程仓库下载。 221 | 222 | 如果最后解析得到的构件版本包含有时间戳,先将该文件下载下来,再将文件名中时间戳信息删除,剩下 SNAPSHOT 并使用(以非时间戳的形式使用)。 223 | 224 | #### 12.创建Maven的普通Java项目 225 | 226 | mvn archetype:create -DgroupId=packageName -DartifactId=projectName 227 | 228 | #### 13.创建 Maven 的 Web 项目 229 | 230 | mvn archetype:create -DgroupId=packageName -DartifactId=webappName -DarchetypeArtifactId=maven-archetype-webapp 231 | 232 | #### 14.反向生成 maven 项目的骨架 233 | 234 | mvn artifacttype:generate 235 | 236 | #### 15.编译源代码 237 | 238 | mvn compile 239 | 240 | #### 16.编译测试代码 241 | 242 | mvn test-compile 243 | 244 | #### 17.运行测试 245 | 246 | mvn test 247 | 248 | #### 18.产生 site 249 | 250 | mvn site 251 | 252 | #### 19.打包 253 | 254 | mvn package 255 | 256 | #### 20.在本地 Repository 中安装 jar 257 | 258 | mvn install(例:installing D:\xxx\xx.jar to D:\xx\xxxx) 259 | 260 | #### 21.清除产生的项目 261 | 262 | mvn clean 263 | 264 | #### 22.生成 Eclipse 项目/idea项目 265 | 266 | eclipse项目 267 | 268 | mvn eclipse:eclipse 269 | 270 | idea 项目 271 | 272 | mvn idea:idea 273 | 274 | #### 23.组合使用 goal 命令,如只打包不测试 275 | 276 | mvn -Dtest package 277 | 278 | #### 24.编译测试的内容 279 | 280 | mvn test-compile 281 | 282 | #### 25.只打 jar 包 283 | 284 | mvn jar:jar 285 | 286 | #### 26.只测试而不编译,也不测试编译 287 | 288 | mvn test -skipping compile -skipping test-compile 289 | 290 | #### 27.清除 eclipse 的一些系统设置 291 | 292 | mvn eclipse:clean 293 | 294 | #### 28.查找当前项目已被解析的依赖 295 | 296 | mvn dependency:list 297 | 298 | #### 29.上传到私服 299 | 300 | mvn deploy 301 | 302 | #### 30.强制检查更新,由于快照版本的更新策略(一天更新几次、隔断时间更新一次)存在,如果想强制更新就会用到此命令 303 | 304 | mvn clean install-U 305 | 306 | #### 31.源码打包 307 | 308 | mvn source:jar 309 | 310 | 或 311 | 312 | mvn source:jar-no-fork 313 | 314 | #### 参考 315 | 316 | https://blog.csdn.net/a303549861/article/details/93752178 317 | 318 | https://www.cnblogs.com/lin0/p/14153982.html 319 | -------------------------------------------------------------------------------- /MySql-上卷.md: -------------------------------------------------------------------------------- 1 | ## Mysql(上) 2 | 3 | #### 1.什么是数据库? 4 | 5 | 数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。 6 | 7 | #### 2.如何查看某个操作的语法? 8 | 9 | 比如看建表的语法: 10 | 11 | ``` 12 | mysql> ? create table 13 | Name: 'CREATE TABLE' 14 | Description: 15 | Syntax: 16 | CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name 17 | (create_definition,…) 18 | [table_options] 19 | [partition_options] 20 | 21 | CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name 22 | [(create_definition,…)] 23 | [table_options] 24 | [partition_options] 25 | [IGNORE | REPLACE] 26 | [AS] query_expression 27 | 28 | CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name 29 | ``` 30 | 31 | #### 3.MySql的存储引擎有哪些? 32 | 33 | MyISAM、 InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、 ARCHIVE、CSV、BLACKHOLE、FEDERATED。 34 | 35 | Tips:InnoDB和BDB提供事务安全表,其他存储引擎都是非事务安全表。 36 | 37 | #### 4.常用的2种存储引擎? 38 | 39 | 1.Myisam是Mysql的默认存储引擎,当create创建新表时,未指定新表的存储引擎时,默认使用Myisam。 40 | 41 | 每个MyISAM 在磁盘上存储成三个文件。文件名都和表名相同,扩展名分别是 .frm (存储表定义) 、.MYD (MYData,存储数据)、.MYI (MYIndex,存储索引)。 42 | 43 | 数据文件和索引文件可以放置在不同的目录,平均分布io,获得更快的速度。 44 | 45 | 2.InnoDB 存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比 Myisam 的存储引擎,InnoDB 写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。 46 | 47 | #### 6.可以针对表设置引擎吗?如何设置? 48 | 49 | 可以, ENGINE=xxx 设置引擎。 50 | 51 | 代码示例: 52 | 53 | ``` 54 | create table person( 55 | id int primary key auto_increment, 56 | username varchar(32) 57 | ) ENGINE=InnoDB 58 | ``` 59 | 60 | #### 6.选择合适的存储引擎? 61 | 62 | 选择标准: 根据应用特点选择合适的存储引擎,对于复杂的应用系统可以根据实际情况选择 多种存储引擎进行组合. 下面是常用存储引擎的适用环境: 63 | 64 | 1. MyISAM: 默认的 MySQL 插件式存储引擎, 它是在 Web、 数据仓储和其他应用环境下最常使用的存储引擎之一。 65 | 2. InnoDB:用于事务处理应用程序,具有众多特性,包括 ACID 事务支持。 66 | 3. Memory: 将 所有数据保存在RAM 中, 在 需要快速查找引用和其他类似数据的环境下,可 提供极快的访问。 67 | 4. Merge:允许 MySQL DBA 或开发人员将一系列等同的 MyISAM 表以逻辑方式组合在一起,并作为 1 个对象引用它们。对于诸如数据仓储等 VLDB 环境十分适合。 68 | 69 | #### 7.选择合适的数据类型 70 | 71 | 前提: 使用适合存储引擎。 72 | 73 | 选择原则: 根据选定的存储引擎,确定如何选择合适的数据类型下面的选择方法按存储引擎分类 : 74 | 75 | 1. MyISAM 数据存储引擎和数据列 76 | 77 | MyISAM数据表,最好使用固定长度的数据列代替可变长度的数据列。 78 | 79 | 2. MEMORY存储引擎和数据列 80 | 81 | MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用CHAR或VARCHAR列都没有关系。两者都是作为CHAR类型处理的。 82 | 83 | 3. InnoDB 存储引擎和数据列 84 | 85 | 建议使用 VARCHAR类型 86 | 87 | 对于InnoDB数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行 都使用指向数据列值的头指针) ,因此在本质上,使用固定长度的CHAR列不一定比使 用可变长度VARCHAR列简单。 因而, 主要的性能因素是数据行使用的存储总量。 由于 CHAR 平均占用的空间多于VARCHAR,因此使用VARCHAR来最小化需要处理的数据行的存储总 量和磁盘I/O是比较好的。 88 | 89 | #### 8.char & varchar 90 | 91 | 保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。 92 | 93 | #### 9.Mysql字符集 94 | 95 | mysql服务器可以支持多种字符集 (可以用show character set命令查看所有mysql支持 的字符集) ,在同一台服务器、同一个数据库、甚至同一个表的不同字段都可以指定使用不 同的字符集。 96 | 97 | mysql的字符集包括字符集(CHARACTER)和校对规则(COLLATION)两个概念。 98 | 99 | #### 10.如何选择字符集? 100 | 101 | 建议在能够完全满足应用的前提下,尽量使用小的字符集。因为更小的字符集意味着能够节省空间、 减少网络传输字节数,同时由于存储空间的较小间接的提高了系统的性能。 102 | 103 | 有很多字符集可以保存汉字,比如 utf8、gb2312、gbk、latin1 等等,但是常用的是 gb2312 和 gbk。因为 gb2312 字库比 gbk 字库小,有些偏僻字(例如:洺)不能保存,因此 在选择字符集的时候一定要权衡这些偏僻字在应用出现的几率以及造成的影响, 不能做出肯 定答复的话最好选用 gbk。 104 | 105 | #### 11.什么是索引? 106 | 107 | 在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。 108 | 109 | #### 12.索引设计原则? 110 | 111 | 1. 搜索的索引列,不 一定是所要选择的列。最适合索引的列是出现在WHERE子句中的列,或连接子句中指定的列,而不是出现在SELECT 关键字后的选择列表中的列。 112 | 113 | 2. 使用惟一索引。考虑某列中值的分布。 对于惟一值的列,索引的效果最好,而具有多个 重复值的列,其索引效果最差。 114 | 115 | 3. 使用短索引。如果对串列进行索引,应该指定一个前缀长度,只要有可能就应该这做样。 例如,如果有一个 CHAR(200) 列,如果在前 10 个或 20 个字符内,多数值是惟一的, 那么就不要对整个列进行索引。 116 | 117 | 4. 利用最左前缀。在创建 一个 n 列的索引时,实际是创建了 MySQL 可利用的 n 个索引。 多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行。 这样的列集 称为最左前缀。 (这与索引一个列的前缀不同,索引一个列的前缀是利用该的n前个字 符作为索引值 ) 118 | 119 | 5. 不要过度索引。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能,这一点我们前面已经介绍 过。在修改表的内容时,索引必须进行更新,有时可能需要重构, 因此, 索引越多,所花的时间越长。 120 | 121 | 如果有一个索引很少利用或从不使用,那么会不必要地减缓表的修改速度。 此外,MySQL 在生成一个执行计划时,要考虑各个索引,这也要费时间。 122 | 123 | 创建多余的索引给查询优化带来了更多的工作。索引太多,也可能会使 MySQL选择不到所要使用的 最好索引。 只保持所需的索引有利于查询优化。 如果想给已索引的表增加索引, 应 该考虑所要增加的索引是否是现有多列索引的最左索引。 124 | 125 | 6. 考虑在列上进行的比较类型。 索引可用于“ <”、“ < = ”、“ = ”、“ > =”、“ > ”和 BETWEEN 运算。在模式具有一个直接量前缀时,索引也用于 LIKE 运算。如果只将某个列用于其他类型的运算时(如 STRCMP( )) ,对其进行索引没有价值。 126 | 127 | #### 13.MySql有哪些索引? 128 | 129 | - ###### 数据结构角度 130 | 131 | 1. BTREE 132 | 2. HASH 133 | 3. FULLTEXT 134 | 4. R-Tree 135 | 136 | - 物理存储角度 137 | 138 | 1、聚集索引(clustered index) 139 | 140 | 2、非聚集索引(non-clustered index) 141 | 142 | - 从逻辑角度 143 | 144 | 1. 普通索引:仅加速查询 145 | 2. 唯一索引:加速查询 + 列值唯一(可以有null) 146 | 3. 主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个 147 | 4. 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并 148 | 5. 全文索引:对文本的内容进行分词,进行搜索 149 | 150 | #### 14.Hash索引和B+树索引的底层实现原理: 151 | 152 | hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据.B+树底层实现是多路平衡查找树.对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据. 153 | 154 | 那么可以看出他们有以下的不同: 155 | 156 | - hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询. 157 | 158 | 因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围. 159 | 160 | - hash索引不支持使用索引进行排序,原理同上. 161 | - hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测.**AAAA**和**AAAAB**的索引没有相关性. 162 | - hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询. 163 | - hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低. 164 | 165 | 因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度.而不需要使用hash索引. 166 | 167 | #### **15. 非聚簇索引一定会回表查询吗?** 168 | 169 | 不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询. 170 | 171 | 举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行`select age from employee where age < 20`的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询. 172 | 173 | #### 16.如何查询最后一行记录? 174 | 175 | ``` 176 | select * from table_name order by id desc limit 1; 177 | ``` 178 | 179 | #### 17.MySQL自增id不连续问题? 180 | 181 | - 唯一键冲突 182 | - 事务回滚 183 | - 批量申请自增id的策略 184 | 185 | #### 18.sql注入问题? 186 | 187 | 原因:用户传入的参数中注入符合sql的语法,从而破坏原有sql结构语意,达到攻击效果。 188 | 189 | #### 19.什么是3NF(范式)? 190 | 191 | - 1NF 指的是数据库表中的任何属性都具有原子性的,不可再分解 192 | - 2NF 是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性 193 | - 3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余 194 | 195 | #### 20. NULL和空串判断? 196 | 197 | NULL值是没有值,,它不是空串。如果指定''(两个单引号,其间没有字符),这在NOT NULL列中是允许的。空串是一个有效的值,它不是无值。 198 | 199 | 判断NULL需要用 IS NULL 或者 IS NOT NULL。 200 | 201 | #### 21.什么是事务? 202 | 203 | 可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行。 204 | 205 | #### 22.事务4个特性? 206 | 207 | 事务是必须满足4个条件(ACID): 208 | 209 | - **原子性 Atomicity:**一个事务中的所有操作,要么全部完成,要么全部不完成,最小的执行单位。 210 | - **一致性 Consistency:**事务执行前后,都处于一致性状态。 211 | - **隔离性 Isolation:**数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。 212 | - **持久性 Durability:**事务执行完成后,对数据的修改就是永久的,即便系统故障也不会丢失。 213 | 214 | #### 23.事务隔离级别分别是? 215 | 216 | - READ_UNCOMMITTED 这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。解决第一类丢失更新的问题,但是会出现脏读、不可重复读、第二类丢失更新的问题,幻读 。 217 | - READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取,即另外一个事务不能读取该事务未提交的数据。解决第一类丢失更新和脏读的问题,但会出现不可重复读、第二类丢失更新的问题,幻读问题 218 | - REPEATABLE_READ 保证一个事务相同条件下前后两次获取的数据是一致的 (注意是 一个事务,可以理解为事务间的数据互不影响)解决第一类丢失更新,脏读、不可重复读、第二类丢失更新的问题,但会出幻读。 219 | - SERIALIZABLE 事务串行执行,解决了脏读、不可重复读、幻读。但效率很差,所以实际中一般不用。 220 | 221 | #### 24.InnoDB默认事务隔离级别?如何查看当前隔离级别 222 | 223 | 可重复读(REPEATABLE-READ) 224 | 225 | 查看: 226 | 227 | ``` 228 | mysql> select @@global.tx_isolation; 229 | +———————————+ 230 | | @@global.tx_isolation | 231 | +———————————+ 232 | | REPEATABLE-READ | 233 | +———————————+ 234 | 1 row in set, 1 warning (0.01 sec) 235 | ``` 236 | 237 | #### 25.什么是锁? 238 | 239 | 数据库的锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性,这样才能保证在高并发的情况下,访问数据库的时候,数据不会出现问题。 240 | 241 | #### 26.死锁? 242 | 243 | 是指两个或两个以上进程执行过程中,因竞争共享资源造成的相互等待现象。 244 | 245 | #### 27.如何处理死锁? 246 | 247 | - 设置超时时间。超时后自动释放。 248 | - 发起死锁检测,主动回滚其中一条事务,让其他事务继续执行。 249 | 250 | #### 28.如何创建用户?授权? 251 | 252 | 创建用户: 253 | 254 | ``` 255 | CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 256 | ``` 257 | 258 | 授权: 259 | 260 | ``` 261 | GRANT privileges ON databasename.tablename TO 'username'@'host'; 262 | ``` 263 | 264 | - username:用户名 265 | - host:可以登陆的主机地址。本地用户用localhost表示,任意远程主机用通配符%。 266 | - password:登陆密码,密码可以为空表示不需要密码登陆服务器 267 | - databasename: 数据库名称。 268 | - tablename:表名称,*代表所有表。 269 | 270 | #### 29.如何查看表结构? 271 | 272 | ​ desc table_name; 273 | 274 | ``` 275 | mysql> desc zipkin_spans; 276 | +———————+———————+———+——+————+———+ 277 | | Field | Type | Null | Key | Default | Extra | 278 | +———————+———————+———+——+————+———+ 279 | | trace_id_high | bigint(20) | NO | PRI | 0 | | 280 | | trace_id | bigint(20) | NO | PRI | NULL | | 281 | | id | bigint(20) | NO | PRI | NULL | | 282 | | name | varchar(255) | NO | MUL | NULL | | 283 | | parent_id | bigint(20) | YES | | NULL | | 284 | | debug | bit(1) | YES | | NULL | | 285 | | start_ts | bigint(20) | YES | MUL | NULL | | 286 | | duration | bigint(20) | YES | | NULL | | 287 | +———————+———————+———+——+————+———+ 288 | 8 rows in set (0.01 sec) 289 | ``` 290 | 291 | #### 30.Mysql删除表的几种方式?区别? 292 | 293 | 1.delete : 仅删除表数据,支持条件过滤,支持回滚。记录日志。因此比较慢。 294 | 295 | ``` 296 | delete from table_name; 297 | ``` 298 | 299 | 2.truncate: 仅删除所有数据,不支持条件过滤,不支持回滚。不记录日志,效率高于delete。 300 | 301 | ``` 302 | truncate table table_name; 303 | ``` 304 | 305 | 3.drop:删除表数据同时删除表结构。将表所占的空间都释放掉。删除效率最高。 306 | 307 | ``` 308 | drop table table_name; 309 | ``` 310 | 311 | #### 31.like走索引吗? 312 | 313 | Xxx% 走索引, %xxx不走索引。 314 | 315 | #### 32.什么是回表? 316 | 317 | 在普通索引查到主键索引后,再去主键索引定位记录。等于说非主键索引需要多走一个索引树。 318 | 319 | #### 33.如何避免回表? 320 | 321 | 索引覆盖被查询的字段。 322 | 323 | #### 34.索引覆盖是什么? 324 | 325 | 如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’。 326 | 327 | #### 35.视图的优缺点? 328 | 329 | **优点** 330 | 331 | > 简单化,数据所见即所得 332 | > 333 | > 安全性,用户只能查询或修改他们所能见到得到的数据 334 | > 335 | > 逻辑独立性,可以屏蔽真实表结构变化带来的影响 336 | 337 | **缺点** 338 | 339 | > 性能相对较差,简单的查询也会变得稍显复杂 340 | > 341 | > 修改不方便,特变是复杂的聚合视图基本无法修改 342 | 343 | #### 36.主键和唯一索引区别? 344 | 345 | 本质区别,主键是一种约束,唯一索引是一种索引。 346 | 347 | 主键不能有空值(非空+唯一),唯一索引可以为空。 348 | 349 | 主键可以是其他表的外键,唯一索引不可以。 350 | 351 | 一个表只能有一个主键,唯一索引 可以多个。 352 | 353 | 都可以建立联合主键或联合唯一索引。 354 | 355 | 主键-》聚簇索引,唯一索引->非聚簇索引。 356 | 357 | #### 37.如何随机获取一条记录? 358 | 359 | ``` 360 | SELECT * FROM table_name ORDER BY rand() LIMIT 1; 361 | ``` 362 | 363 | #### 38.Mysql中的数值类型? 364 | 365 | ![image-20200422123555254](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200422123555254.png) 366 | 367 | #### 39.查看当前表有哪些索引? 368 | 369 | ``` 370 | show index from table_name; 371 | ``` 372 | 373 | #### 40.索引不生效的情况? 374 | 375 | - 使用不等于查询 376 | - NULL值 377 | - 列参与了数学运算或者函数 378 | - 在字符串like时左边是通配符.比如 %xxx 379 | - 当mysql分析全表扫描比使用索引快的时候不使用索引. 380 | - 当使用联合索引,前面一个条件为范围查询,后面的即使符合最左前缀原则,也无法使用索引. 381 | 382 | #### 41.MVVC? 383 | 384 | MVCC 全称是多版本并发控制系统,InnoDB 的 MVCC 是通过在每行记录后面保存两个隐藏的列来实现,这两个列一个保存了行的创建时间,一个保存行的过期时间(删除时间)。当然存储的并不是真实的时间而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动新增,事务开始时刻的系统版本号会作为事务的版本号,用来查询到每行记录的版本号进行比较。 385 | 386 | #### 42.sql语句的执行流程? 387 | 388 | 客户端连接数据库,验证身份。 389 | 390 | 获取当前用户权限。 391 | 392 | 当你查询时,会先去缓存看看,如果有返回。 393 | 394 | 如果没有,分析器对sql做词法分析。 395 | 396 | 优化器对sql进行“它认为比较好的优化”。 397 | 398 | 执行器负责具体执行sql语句。 399 | 400 | 最后把数据返回给客户端。 401 | 402 | #### 43.如何获取select 语句执行计划? 403 | 404 | explain sql; 405 | 406 | #### 44.explain列有哪些?含义? 407 | 408 | ![image-20200501154131370](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200501154131370.png) 409 | 410 | 一、 id 411 | 412 | SQL查询中的序列号。 413 | 414 | id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行。 415 | 416 | 二、select_type 417 | 418 | ![image-20200501154212022](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200501154212022.png) 419 | 420 | 三、table 421 | 422 | 显示这一行的数据是关于哪张表的。不一定是实际存在的表名。 可以为如下的值: 423 | 424 | - : 引用id为M和N UNION后的结果。 425 | - : 引用id为N的结果派生出的表。派生表可以是一个结果集,例如派生自FROM中子查询的结果。 426 | - : 引用id为N的子查询结果物化得到的表。即生成一个临时表保存子查询的结果。 427 | 428 | 四、type 429 | 430 | 这是**最重要的字段之一**,显示查询使用了何种类型。从最好到最差的连接类型依次为: 431 | 432 | > system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL 433 | 434 | 1、system 435 | 436 | 表中只有一行数据或者是空表,这是const类型的一个特例。且只能用于myisam和memory表。如果是Innodb引擎表,type列在这个情况通常都是all或者index 437 | 438 | 2、const 439 | 440 | 最多只有一行记录匹配。当联合主键或唯一索引的所有字段跟常量值比较时,join类型为const。其他数据库也叫做唯一索引扫描 441 | 442 | 3、eq_ref 443 | 444 | 多表join时,对于来自前面表的每一行,在当前表中只能找到一行。这可能是除了system和const之外最好的类型。当主键或唯一非NULL索引的所有字段都被用作join联接时会使用此类型。 445 | 446 | eq_ref可用于使用'='操作符作比较的索引列。比较的值可以是常量,也可以是使用在此表之前读取的表的列的表达式。 447 | 448 | > 相对于下面的ref区别就是它使用的唯一索引,即主键或唯一索引,而ref使用的是非唯一索引或者普通索引。 eq_ref只能找到一行,而ref能找到多行。 449 | 450 | 4、ref 451 | 452 | 对于来自前面表的每一行,在此表的索引中可以匹配到多行。若联接只用到索引的最左前缀或索引不是主键或唯一索引时,使用ref类型(也就是说,此联接能够匹配多行记录)。 453 | 454 | ref可用于使用'='或'<=>'操作符作比较的索引列。 455 | 456 | 5、 fulltext 457 | 458 | 使用全文索引的时候是这个类型。要注意,**全文索引的优先级很高**,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引 459 | 460 | 6、ref_or_null 461 | 462 | 跟ref类型类似,只是增加了null值的比较。实际用的不多。 463 | 464 | 7、index_merge 465 | 466 | 表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range 467 | 468 | 8、unique_subquery 469 | 470 | 用于where中的in形式子查询,子查询返回不重复值唯一值,可以完全替换子查询,效率更高。 该类型替换了下面形式的IN子查询的ref: `value IN (SELECT primary_key FROM single_table WHERE some_expr)` 471 | 472 | 9、index_subquery 473 | 474 | 该联接类型类似于unique_subquery。适用于非唯一索引,可以返回重复值。 475 | 476 | 10、range 477 | 478 | 索引范围查询,常见于使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN()或者like等运算符的查询中。 479 | 480 | 11、index 481 | 482 | 索引全表扫描,把索引从头到尾扫一遍。这里包含两种情况: 一种是查询使用了覆盖索引,那么它只需要扫描索引就可以获得数据,这个效率要比全表扫描要快,因为索引通常比数据表小,而且还能避免二次查询。在extra中显示Using index,反之,如果在索引上进行全表扫描,没有Using index的提示。 483 | 484 | 12、all 485 | 486 | 全表扫描,性能最差。 487 | 488 | 五、possible_keys 489 | 490 | 查询可能使用到的索引都会在这里列出来。 491 | 492 | 六、Key 493 | 494 | key列显示MySQL实际使用的键(索引) 495 | 496 | 要想强制MySQL使用或忽视possible_keys列中的索引,可以使用FORCE INDEX、USE INDEX或者IGNORE INDEX。 497 | 498 | select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。 499 | 500 | 七、key_len 501 | 502 | 表示索引中使用的字节数。 503 | 504 | key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。 505 | 506 | 不损失精确性的情况下,长度越短越好 。 507 | 508 | 八、ref 509 | 510 | 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。 511 | 512 | 九、rows 513 | 514 | rows 也是一个重要的字段。 这是mysql估算的需要扫描的行数(不是精确值)。 515 | 516 | 十、Extra 517 | 518 | 该列包含MySQL解决查询的详细信息,有以下几种情况: 519 | 520 | - Using where:列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤。 521 | - Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询。 522 | - Using filesort:MySQL中无法利用索引完成的排序操作称为“文件排序”。 523 | - Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。 524 | - Impossible where:这个值强调了where语句会导致没有符合条件的行。 525 | - Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行。 526 | 527 | 链接:https://www.jianshu.com/p/8fab76bbf448 528 | 529 | #### 45.MySql最多创建多少列索引? 530 | 531 | 16 532 | 533 | #### 46.为什么最好建立一个主键? 534 | 535 | 主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的ID列作为主键.设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全. 536 | 537 | #### 47.**字段为什么要求建议为not null?** 538 | 539 | MySQL官网这样介绍: 540 | 541 | > NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte. 542 | 543 | null值会占用更多的字节,且会在程序中造成很多与预期不符的情况. 544 | 545 | #### 48.**varchar(10)和int(10)代表什么含义** 546 | 547 | varchar的10代表了申请的空间长度,也是可以存储的数据的最大长度,而int的10只是代表了展示的长度,不足10位以0填充.也就是说,int(1)和int(10)所能存储的数字大小以及占用的空间都是相同的,只是在展示时按照长度展示。 548 | 549 | #### 49.视图是什么?对比普通表优势? 550 | 551 | 视图(View)是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的。视图并 不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时 动态生成的。 552 | 553 | 视图相对于普通的表的优势主要包括以下几项。 554 | 555 | - 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件, 556 | 557 | 对用户来说已经是过滤好的复合条件的结果集。 558 | 559 | - 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能 560 | 561 | 限制到某个行某个列,但是通过视图就可以简单的实现。 562 | 563 | - 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加 564 | 565 | 列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问 者的影响。 566 | 567 | #### 50.count(*)在不同引擎的实现方式? 568 | 569 | MyISAM :把一个表的总行数存在了磁盘上,执行 count(*) 的时候会直接返回这个数,效率很高。 570 | 571 | InnoDB : 比较麻烦,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。 572 | 573 | 参考: 574 | 575 | - 《深入浅出MySQL》 576 | - 《高性能MySql》 577 | - 《MySQL技术内幕(第5版)》 578 | - 《MySQL必知必会》 579 | - 极客时间:MySQL实战45讲 580 | - 百度百科 581 | 582 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) -------------------------------------------------------------------------------- /Mybatis.md: -------------------------------------------------------------------------------- 1 | ## Mybatis 2 | 3 | #### 1.什么是Mybatis? 4 | 5 | MyBatis 是一款优秀的支持自定义 SQL 查询、存储过程和高级映射的持久层框架,消除了 几乎所有的 JDBC 代码和参数的手动设置以及结果集的检索 。 MyBatis 可以使用 XML 或注解进 行配置和映射, MyBatis 通过将参数映射到配置的 SQL 形成最终执行的 SQL 语句 ,最后将执行 SQL 的结果映射成 Java对象返回。 6 | 7 | #### 2.Hibernate优点? 8 | 9 | Hibernate建立在POJO和数据库表模型的直接映射关系上。通过xml或注解即可和数据库表做映射。通过pojo直接可以操作数据库的数据。它提供的是全表的映射模型。 10 | 11 | - 消除代码映射规则,被分离到xml或注解里配置。 12 | - 无需在管理数据库连接,配置在xml中即可。 13 | - 一个会话中,不要操作多个对象,只要操作Session对象即可。 14 | - 关闭资源只需关闭Session即可。 15 | 16 | #### 3.Hibernate缺点? 17 | 18 | - 全表映射带来的不便,比如更新需要发送所有的字段。 19 | - 无法根据不同的条件组装不同的sql。 20 | - 对多表关联和复杂的sql查询支持较差,需要自己写sql,返回后,需要自己将数据组成pojo。 21 | - 不能有效支持存储过程。 22 | - 虽然有hql,但是性能较差,大型互联网需要优化sql,而hibernate做不到。 23 | 24 | #### 4.Mybatis优点? 25 | 26 | 1. 小巧,学习成本低,会写sql上手就很快了。 27 | 2. 比jdbc,基本上配置好了,大部分的工作量就专注在sql的部分。 28 | 3. 方便维护管理,sql不需要在Java代码中找,sql代码可以分离出来,重用。 29 | 4. 接近jdbc,灵活,支持动态sql。 30 | 5. 支持对象与数据库orm字段关系映射。 31 | 32 | #### 5.Mybatis缺点? 33 | 34 | - 由于工作量在sql上,需要 sql的熟练度高。 35 | - 移植性差。sql语法依赖数据库。不同数据库的切换会因语法差异,会报错。 36 | 37 | #### 6.什么时候用Mybatis? 38 | 39 | 如果你需要一个灵活的、可以动态生成映射关系的框架。目前来说,因为适合,互联网项目用Mybatis的比例还是很高滴。 40 | 41 | #### 7.Mybatis的核心组件有哪些?分别是? 42 | 43 | SqlSessionFactoryBuilder(构造器) :它会根据配置信息或者代码来生成SqlSessionFactory。 44 | 45 | SqlSessionFactory(工厂接口):依靠工厂来生成SqlSession。 46 | 47 | SqlSession(会话):是一个既可以发送 sql去执行返回结果,也可以获取Mapper接口。 48 | 49 | SQL Mapper:它是新设计的组件,是由一个Java接口和XML文件(或注解)构成的。需要给出对象的SQl和映射规则。它负责发送SQL去执行,并返回结果。 50 | 51 | #### 8.#{}和${}的区别是什么? 52 | 53 | ${}是字符串替换,#{}是预编译处理。一般用#{}防止 sql注入问题。 54 | 55 | #### 9.Mybatis中9个动态标签是? 56 | 57 | - if 58 | - c h o o s e (when 、 oterwise) 59 | - trim (where、 set) 60 | - foreach 61 | - bind 62 | 63 | #### 10.xml映射文件中,有哪些标签? 64 | 65 | select|insert|updae|delete|resultMap|parameterMap|sql|include|selectKey 加上9个动态标签,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。 66 | 67 | #### 11.Mybatis支持注解吗?优点?缺点? 68 | 69 | 支持。 70 | 71 | 优点:对于需求简单sql逻辑简单的系统,效率较高。 72 | 73 | 缺点: 当sql变化需要重新编译代码,sql复杂时,写起来更不方便,不好维护。 74 | 75 | #### 12.Mybatis动态sql? 76 | 77 | Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑 78 | 判断和动态拼接 sql 的功能 79 | 80 | #### 13.**Mybatis 是如何进行分页的?分页插件的原理是什么?** 81 | 82 | 1)Mybatis 使用 RowBounds 对象进行分页,也可以直接编写 sql 实现分页,也可以使用 83 | Mybatis 的分页插件。 84 | 2)分页插件的原理:实现 Mybatis 提供的接口,实现自定义插件,在插件的拦截方法内拦 85 | 截待执行的 sql,然后重写 sql。 86 | 举例:select from student,拦截 sql 后重写为:select t. from (select from student)t 87 | limit 0,10 88 | 89 | #### 14.如何获取自增主键? 90 | 91 | 注解: 92 | 93 | ```java 94 | @Options(useGeneratedKeys =true, keyProperty =”id”) 95 | 96 | int insert( ); 97 | ``` 98 | 99 | Xml: 100 | 101 | ```xml 102 | 103 | 104 | sql 105 | 106 | 107 | ``` 108 | 109 | #### 15.为什么Mapper接口没有实现类,却能被正常调用? 110 | 111 | 这是因为MyBatis在Mapper接口上使用了动态代理。 112 | 113 | #### 16.用注解好还是xml好? 114 | 115 | 简单的增删改查可以注解。 116 | 117 | 复杂的sql还是用xml,官方也比较推荐xml方式。 118 | 119 | xml的方式更便于统一维护管理代码。 120 | 121 | #### 17.如果不想手动指定别名,如何用驼峰的形式自动映射? 122 | 123 | mapUnderscoreToCamelCase=true 124 | 125 | #### 18.当实体属性名和表中字段不一致,怎么办? 126 | 127 | 一、别名: 比如 order_num 128 | 129 | select order_num orderNum 130 | 131 | 二、通过做映射 132 | 133 | ​ 134 | 135 | 三、如果是驼峰注解用17问的方式。 136 | 137 | #### 19.嵌套查询用什么标签? 138 | 139 | association 标签的嵌套查询常用的属性如下 。 140 | 141 | select:另一个映射查询的 id, MyBatis会额外执行这个查询获取嵌套对象的结果。 142 | 143 | column:列名(或别名),将主查询中列的结果作为嵌套查询的 参数,配置 方式如 column={propl=coll , prop2=col2}, propl 和 prop2 将作为嵌套查询的参数。 144 | 145 | fetch Type:数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载, 这个配置会覆盖全局的 lazyLoadingEnabled 配置 。 146 | 147 | #### 20.like模糊查询怎么写? 148 | 149 | (1)'%${value}%' 不推荐 150 | 151 | (2)CONCAT('%',#{value},'%') 推荐 152 | 153 | (3) like '%'|| #{value} || '%' 154 | 155 | (4)使用bind 156 | 157 | 158 | 159 | LIKE #{pattern} 160 | 161 | #### 21.Mybatis支持枚举吗? 162 | 163 | 支持。有转换器EnumTypeHandler和EnumOrdinalTypeHandler 164 | 165 | ```xml 166 | 167 | 168 | 169 | ``` 170 | 171 | #### 22.SqlSessionFactoryBuilder生命周期? 172 | 173 | 利用xml或者Java代码获得资源构建SqlSessionFactoryBuilder,它可以创建多个SessionFactory,一旦构建成功SessionFactory,就可以回收它了。 174 | 175 | #### 23.一级缓存的结构?如何开启一级缓存?如何不使用一级缓存? 176 | 177 | Map 。默认情况下,一级缓存是开启的。< select >标签内加属性flushCache=true。 178 | 179 | #### 24.二级缓存如何配置? 180 | 181 | ```xml 182 | 183 | 〈 !一其他自己直一 〉 184 | 185 | 186 | ``` 187 | 188 | 这个参数是二级缓存的全局开关,默认值是 true,初始状态 为启用状态 。 如果把这个参数设置为 false,即使有后面 的 二级缓 存配置,也不会生效 。 189 | 190 | #### 25.**简述 Mybatis 的插件运行原理,以及如何编写一个插件?** 191 | 192 | 1)Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、 193 | Executor 这 4 种接口的插件,Mybatis 通过动态代理,为需要拦截的接口生成代理对象以实 194 | 现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是 195 | InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。 196 | 2)实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定 197 | 要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。 198 | 199 | #### 26.二级缓存的回收策略有哪些? 200 | 201 | eviction (收回策略) 202 | 203 | LRU(最近最少使用的) : 移除最长时间不被使用的对象,这是默认值 。 204 | 205 | IFO(先进先出〉 : 按对象进入缓存的顺序来移除它们 。 206 | 207 | SOFT(软引用) : 移除基于垃圾回收器状态和软引用规则的对象 。 208 | 209 | WEAK (弱引用) : 更积极地移除基于垃圾收集器状态和弱引用规则的对象 。 210 | 211 | #### 27.Mybatis的Xml文件中id可以重复吗? 212 | 213 | 同一namespace下,id不可重复。不同namespace下,可以重复。 214 | 215 | #### 28. 和Mybatis搭配java框架中比较好用的缓存框架?有哪些特点? 216 | 217 | EhCache是一个纯牌的 Java进程内的缓存框架,具有快速、精干等特点。 218 | 219 | 具体来说, EhCache主要的特性如下 。 220 | 221 | - 快速。 222 | - 简单。 223 | - 多种缓存策略 。 224 | - 缓存数据有内存和磁盘两级,无须担心容量问题 。 225 | - 缓存数据会在虚拟机重启 的过程中写入磁盘。 226 | - 可 以通过 RMI、可插入 API 等方式进行分布式缓存。 227 | - .具有缓存和缓存管理器的侦 昕接口。 228 | - 支持多缓存管理器实例 以及一个实例的多个缓存区域。 229 | 230 | #### 29.说一下resultMap和resultType 231 | 232 | resultmap是手动提交,人为提交,resulttype是自动提交 233 | MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。 234 | 在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。 235 | 1.当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。 236 | 2.当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。 237 | 238 | #### 30.Mybatis动态sql有什么用?执行原理?有哪些动态sql? 239 | 240 | 有九种动态sql标签:trim,where,set,foreach,if,choose,when,bind,otherwise 241 | Mybatis的动态sql可以在xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值,完成逻辑判断并动态拼接sql的功能! 242 | 243 | #### 参考 244 | 245 | 《 MyBatis从入门到精通》 246 | 247 | 《深入浅出 MyBatis技术原理与实战》 248 | 249 | 《MyBatis技术》 250 | 251 | https://zhuanlan.zhihu.com/p/60257737 252 | 253 | 254 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 255 | 256 | -------------------------------------------------------------------------------- /Nginx.md: -------------------------------------------------------------------------------- 1 | ## Nginx 2 | 3 | #### 1.什么是Nginx? 4 | 5 | Nginx是一个高性能的HTTP和反向代理服务器。同时也是一个 IMAP/POP3/SMTP 代理服务器。 官方网站:http://nginx.org。 6 | 7 | #### 2.Nginx主要特征? 8 | 9 | 处理静态文件,索引文件以及自动索引;打开文件描述符缓冲. 无缓存的反向代理加速,简单的负载均衡和容错. FastCGI,简单的负载均衡和容错.模块化的结构。包括 gzipping, byte ranges, chunked responses,以及 SSI-filter 等filter。如果由 FastCGI 或其它代理服务器处理单页中存在的多个 SSI,则这项处理可以并行 运行,而不需要相互等待。 10 | 11 | 支持 SSL 和 TLSSNI. 12 | 13 | Nginx 它支持内核 Poll 模型,能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数。 14 | 15 | Nginx 具有很高的稳定性。 例如当前 apache 一旦上到 200 个以上进程,web 响应速度就明显非常缓慢了。而 Nginx 采取了分阶段资源分配技术,使得它的 CPU 与内存占用率非常低。nginx 官方表示保持 10,000 个没有活动的连接,它只占 2.5M 内存,所以类似 DOS 这样的攻击对 nginx 来说基本上是毫无用处的。 16 | 17 | Nginx 支持热部署。它的启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运 行数个月也不需要重新启动。对软件版本进行进行热升级。 18 | 19 | Nginx 采用 master-slave 模型,能够充分利用 SMP 的优势,且能够减少工作进程在磁 盘 I/O 的阻塞延迟。当采用 select()/poll()调用时,还可以限制每个进程的连接数。 20 | 21 | Nginx 代码质量非常高,代码很规范,手法成熟, 模块扩展也很容易。特别值得一提的是强大的 Upstream 与 Filter 链。 22 | 23 | Nginx 采用了一些 os 提供的最新特性如对 sendfile (Linux2.2+),accept-filter (FreeBSD4.1+),TCP_DEFER_ACCEPT (Linux 2.4+)的支持,从而大大提高了性能。 24 | 25 | 免费开源,可以做高并发负载均衡。 26 | 27 | #### 3.Nginx 常用命令? 28 | 29 | 启动 nginx 。 30 | 停止 nginx -s stop 或 nginx -s quit 。 31 | 重载配置 ./sbin/nginx -s reload(平滑重启) 或 service nginx reload 。 32 | 重载指定配置文件 .nginx -c /usr/local/nginx/conf/nginx.conf 。 33 | 查看 nginx 版本 nginx -v 。 34 | 检查配置文件是否正确 nginx -t 。 35 | 显示帮助信息 nginx -h 。 36 | 37 | #### 4.工作模式及连接数上限? 38 | 39 | ```nginx 40 | events { 41 | 42 | use epoll; #epoll 是多路复用 IO(I/O Multiplexing)中的一种方 式,但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能 43 | 44 | worker_connections 1024;#单个后台 worker process 进程的最大并发链接数 45 | 46 | # multi_accept on; 47 | } 48 | ``` 49 | 50 | #### 5.Nginx负载均衡几种算法? 51 | 52 | 5种。 53 | 54 | 1.轮询模式(默认) 55 | 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 56 | 2.权重模式 57 | 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况 58 | 3.IP_hash模式 (IP散列) 59 | 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 60 | 4.url_hash模式 61 | 5.fair模式 62 | 按后端服务器的响应时间来分配请求,响应时间短的优先分配。 63 | 64 | #### 6.nginx有几种进程模型? 65 | 66 | 分为master-worker模式和单进程模式。在master-worker模式下,有一个master进程和至少一个的worker进程,单进程模式顾名思义只有一个进程。 67 | 68 | #### 7.如何定义错误提示页面? 69 | 70 | \# 定义错误提示页面 71 | 72 | ```nginx 73 | error_page 500 502 503 504 /50x.html; 74 | 75 | location = /50x.html { root /root; 76 | 77 | } 78 | ``` 79 | 80 | #### 8.如何精准匹配路径? 81 | 82 | location =开头表示精准匹配 83 | 84 | ```nginx 85 | location = /get { 86 | #规则 A } 87 | ``` 88 | 89 | #### 9.路径匹配优先级? 90 | 91 | 多个 location 配置的情况下匹配顺序为 92 | 首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当 有匹配成功时候,停止匹配,按当前匹配规则处理请求。 93 | 94 | #### 10.如何把请求转发给后端应用服务器? 95 | 96 | ```nginx 97 | location = / { 98 | 99 | proxy_pass http://tomcat:8080/index 100 | 101 | } 102 | ``` 103 | 104 | #### 11.如何根据文件类型设置过期时间? 105 | 106 | ```nginx 107 | location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ { 108 | if (-f $request_filename) { 109 | expires 1h; 110 | break; 111 | } 112 | } 113 | ``` 114 | 115 | #### 12.禁止访问某个目录? 116 | 117 | ```nginx 118 | location ^~/path/ { 119 | deny all; 120 | } 121 | 122 | 123 | ``` 124 | 125 | #### 13.Nginx负载均衡实现过程? 126 | 127 | 首先在 http 模块中配置使用 upstream 模块定义后台的 webserver 的池子,名为 proxy-web,在池子中我们可以添加多台后台 webserver,其中状态 检查、调度算法都是在池子中配置;然后在 serverr 模块中定义虚拟主机,但是这个虚拟主 机不指定自己的 web 目录站点,它将使用 location 匹配 url 然后转发到上面定义好的 web 池子中,最后根据调度策略再转发到后台 web server 上 。 128 | 129 | #### 14.负载均衡配置? 130 | 131 | ```nginx 132 | Upstream proxy_nginx { 133 | 134 | server 192.168.0.254 weight=1max_fails=2 fail_timeout=10s ; 135 | server 192.168.0.253 weight=2 max_fails=2fail_timeout=10s; 136 | server192.168.0.252 backup; server192.168.0.251 down; 137 | 138 | } 139 | 140 | server{ 141 | listen 80; 142 | server_name xiaoka.com; 143 | 144 | location / { 145 | 146 | proxy_pass http:// proxy_nginx; 147 | proxy_set_header Host 148 | proxy_set_header X-Real-IP 149 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 150 | 151 | } 152 | ``` 153 | 154 | #### 15.设置超时时间? 155 | 156 | ```nginx 157 | http { 158 | ………. 159 | keepalive_timeout 60; ###设置客户端连接保持会话的超时时间,超过这个时间,服务器会关闭该连接。 tcp_nodelay on; 160 | \####打开 tcp_nodelay,在包含了 keepalive 参数才有效 161 | client_header_timeout 15; ####设置客户端请求头读取超时时间,如果超过这个时间,客户端还没有发送任何数据, Nginx 将返回“Request time out(408)”错误 162 | client_body_timeout 15; 163 | 164 | \####设置客户端请求主体读取超时时间,如果超过这个时间,客户端还没有发送任何数据, Nginx 将返回“Request time out(408)”错误 165 | send_timeout 15; ####指定响应客户端的超时时间。这个超过仅限于两个连接活动之间的时间,如果超过这 个时间,客户端没有任何活动,Nginx 将会关闭连接。 166 | 167 | …… } 168 | ``` 169 | 170 | #### 16.开启压缩功能好处?坏处? 171 | 172 | 好处:压缩是可以节省带宽,提高传输效率 173 | 174 | 坏处:但是由于是在服务器上进行压缩,会消耗服务器起源 175 | 176 | #### 17.Nginx配置文件nginx.conf有哪些属性模块? 177 | 178 | ``` 179 | worker_processes 1; # worker进程的数量 180 | events { # 事件区块开始 181 | worker_connections 1024; # 每个worker进程支持的最大连接数 182 | } # 事件区块结束 183 | http { # HTTP区块开始 184 | include mime.types; # Nginx支持的媒体类型库文件 185 | default_type application/octet-stream; # 默认的媒体类型 186 | sendfile on; # 开启高效传输模式 187 | keepalive_timeout 65; # 连接超时 188 | server { # 第一个Server区块开始,表示一个独立的虚拟主机站点 189 | listen 80; # 提供服务的端口,默认80 190 | server_name localhost; # 提供服务的域名主机名 191 | location / { # 第一个location区块开始 192 | root html; # 站点的根目录,相当于Nginx的安装目录 193 | index index.html index.htm; # 默认的首页文件,多个用空格分开 194 | } # 第一个location区块结果 195 | error_page 500502503504 /50x.html; # 出现对应的http状态码时,使用50x.html回应客户 196 | location = /50x.html { # location区块开始,访问50x.html 197 | root html; # 指定对应的站点目录为html 198 | } 199 | } 200 | ...... 201 | 202 | ``` 203 | 204 | #### 18.Nginx静态资源? 205 | 206 | 静态资源访问,就是存放在nginx的html页面,我们也可以编写 207 | 208 | #### 19.如何用Nginx解决前端跨域问题? 209 | 210 | - 使用Nginx转发请求。把跨域的接口写成调本域的接口,然后将这些接口转发到真正的请求地址。 211 | 212 | #### 20.Nginx虚拟主机怎么配置? 213 | 214 | - 1、基于域名的虚拟主机,通过域名来区分虚拟主机——应用:外部网站 215 | - 2、基于端口的虚拟主机,通过端口来区分虚拟主机——应用:公司内部网站,外部网站的管理后台 216 | - 3、基于ip的虚拟主机。 217 | 218 | #### 参考: 219 | 220 | - 《Nginx从入门到精通》 221 | 222 | - 《Nginx高性能Web服务器详解》 223 | 224 | - 《深入理解nginx》 225 | 226 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 227 | -------------------------------------------------------------------------------- /RabbitMQ.md: -------------------------------------------------------------------------------- 1 | ## RabbitMQ 2 | 3 | 4 | 5 | #### 1、什么是 RabbitMQ?为什么使用 RabbitMQ? 6 | 7 | RabbitMQ 是一款开源的,Erlang 编写的,基于 AMQP 协议的,消息中间件; 8 | 9 | 可以用它来:解耦、异步、削峰。 10 | 11 | #### 2、RabbitMQ 有什么优缺点? 12 | 13 | 优点:解耦、异步、削峰; 14 | 15 | 缺点:降低了系统的稳定性:本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低; 16 | 17 | 增加了系统的复杂性:加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。 18 | 19 | #### 3.rabbitmq 的使用场景 20 | 21 | (1)服务间异步通信 22 | 23 | (2)顺序消费 24 | 25 | (3)定时任务 26 | 27 | (4)请求削峰 28 | 29 | #### 4.RabbitMQ基本概念 30 | 31 | Broker: 简单来说就是消息队列服务器实体 32 | Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列 33 | Queue: 消息队列载体,每个消息都会被投入到一个或多个队列 34 | Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来 35 | Routing Key: 路由关键字,exchange根据这个关键字进行消息投递 36 | VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。 37 | Producer: 消息生产者,就是投递消息的程序 38 | Consumer: 消息消费者,就是接受消息的程序 39 | Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务 40 | 由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。 41 | 42 | #### 5.RabbitMQ 中的 broker 是指什么?cluster 又是指什么? 43 | 44 | `broker` 是指一个或多个 `erlang node` 的逻辑分组,且 `node` 上运行着 `RabbitMQ` 应用程序。 45 | `cluster` 是在 `broker` 的基础之上,增加了 `node` 之间共享元数据的约束。 46 | 47 | #### 6、RabbitMQ 概念里的 channel、exchange 和 queue 是逻辑概念,还是对应着进程实体?分别起什么作用? 48 | 49 | **Queue** 具有自己的 **erlang** 进程;**exchange** 内部实现为保存 binding 关系的查找表;channel 是实际进行路由工作的实体,即负责按照 routing_key 将 message 投递给 queue 。由 AMQP 协议描述可知,channel 是真实 TCP 连接之上的虚拟连接,所有 AMQP 命令都是通过 channel 发送的,且每一个 channel 有唯一的 ID。一个 channel 只能被单独一个操作系统线程使用,故投递到特定 channel 上的 message 是有顺序的。但一个操作系统线程上允许使用多个 channel 。 50 | 51 | #### 7 vhost 是什么?起什么作用? 52 | 53 | `vhost` 可以理解为虚拟 `broker` ,即 `mini-RabbitMQ server`。其内部均含有独立的 `queue`、`exchange` 和 `binding` 等,但最最重要的是,其拥有独立的权限系统,可以做到 `vhost` 范围的用户控制。当然,从 `RabbitMQ` 的全局角度,`vhost` 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 `vhost` 中)。 54 | 55 | #### 8. 消息基于什么传输? 56 | 57 | 由于TCP连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ使用信道的方式来传输数据。信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制。 58 | 59 | #### 9. 消息如何分发? 60 | 61 | 若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。 62 | 63 | #### 10. 消息怎么路由? 64 | 65 | 从概念上来说,消息路由必须有三部分:**交换器**、**路由**、**绑定**。生产者把消息发布到交换器上;绑定决定了消息如何从路由器路由到特定的队列;消息最终到达队列,并被消费者接收。 66 | 67 | 消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。 68 | 通过队列路由键,可以把队列绑定到交换器上。 69 | 消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则)。如果能够匹配到队列,则消息会投递到相应队列中;如果不能匹配到任何队列,消息将进入 “黑洞”。 70 | 71 | 常用的交换器主要分为一下三种: 72 | 73 | - direct:如果路由键完全匹配,消息就被投递到相应的队列 74 | - fanout:如果交换器收到消息,将会广播到所有绑定的队列上 75 | - topic:可以使来自不同源头的消息能够到达同一个队列。使用topic交换器时,可以使用通配符。 76 | 比如:“*” 匹配特定位置的任意文本, “.” 把路由键分为了几部分,“#” 匹配所有规则等。 77 | 特别注意:发往topic交换器的消息不能随意的设置选择键(routing_key),必须是由"."隔开的一系列的标识符组成。 78 | 79 | #### 11. 什么是元数据?元数据分为哪些类型?包括哪些内容?与 cluster 相关的元数据有哪些?元数据是如何保存的?元数据在 cluster 中是如何分布的? 80 | 81 | 在非 `cluster` 模式下,元数据主要分为 `Queue` 元数据(queue 名字和属性等)、`Exchange`元数据(exchange 名字、类型和属性等)、`Binding` 元数据(存放路由关系的查找表)、`Vhost`元数据(vhost 范围内针对前三者的名字空间约束和安全属性设置)。 82 | 在 `cluster` 模式下,还包括 cluster 中 node 位置信息和 node 关系信息。元数据按照 erlang node 的类型确定是仅保存于 RAM 中,还是同时保存在 RAM 和 disk 上。元数据在 cluster 中是全 node 分布的。 83 | 84 | #### 12. 在单node 系统和多 node 构成的 cluster 系统中声明 queue、exchange ,以及进行 binding 会有什么不同? 85 | 86 | 答:当你在单 node 上声明 queue 时,只要该 node 上相关元数据进行了变更,你就会得到 Queue.Declare-ok 回应;而在 cluster 上声明 queue ,则要求 cluster 上的全部 node 都要进行元数据成功更新,才会得到 Queue.Declare-ok 回应。另外,若 node 类型为 RAM node 则变更的数据仅保存在内存中,若类型为 disk node 则还要变更保存在磁盘上的数据。 87 | 88 | 死信队列&死信交换器:DLX 全称(Dead-Letter-Exchange),称之为死信交换器,当消息变成一个死信之后,如果这个消息所在的队列存在x-dead-letter-exchange参数,那么它会被发送到x-dead-letter-exchange对应值的交换器上,这个交换器就称之为死信交换器,与这个死信交换器绑定的队列就是死信队列。 89 | 90 | #### 13. 如何确保消息正确地发送至RabbitMQ? 91 | 92 | **RabbitMQ**使用发送方确认模式,确保消息正确地发送到**RabbitMQ**。 93 | 发送方确认模式:将信道设置成`confirm`模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。如果`RabbitMQ`发生内部错误从而导致消息丢失,会发送一条`nack`(not acknowledged,未确认)消息。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。 94 | 95 | #### 14. 如何确保消息接收方消费了消息? 96 | 97 | 接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,`RabbitMQ`才能安全地把消息从队列中删除。这里并没有用到超时机制,`RabbitMQ`仅通过`Consumer`的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,`RabbitMQ`给了`Consumer`足够长的时间来处理消息。 98 | 99 | 下面罗列几种特殊情况: 100 | 101 | - 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要根据bizId去重) 102 | - 如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。 103 | 104 | #### 15、如何保证 RabbitMQ 不被重复消费? 105 | 106 | 先说为什么会重复消费:正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除; 107 | 108 | 但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。 109 | 110 | 针对以上问题,一个解决思路是:保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响;保证消息等幂性; 111 | 112 | 比如:在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过; 113 | 114 | #### 16、如何保证 RabbitMQ 消息的可靠传输? 115 | 116 | 消息不可靠的情况可能是消息丢失,劫持等原因; 117 | 118 | 丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息; 119 | 120 | 生产者丢失消息:从生产者弄丢数据这个角度来看,RabbitMQ 提供 transaction 和 confirm 模式来确保生产者不丢消息; 121 | 122 | transaction 机制就是说:发送消息前,开启事务(channel.txSelect()), 然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()), 如果发送成功则提交事务(channel.txCommit())。然而,这种方式有个缺点:吞吐量下降; 123 | 124 | confirm 模式用的居多:一旦 channel 进入 confirm 模式,所有在该信道上发布的消息都将会被指派一个唯一的 ID(从 1 开始),一旦消息被投递到所有匹配的队列之后; 125 | 126 | rabbitMQ 就会发送一个 ACK 给生产者(包含消息的唯一 ID),这就使得生产者知道消息已经正确到达目的队列了; 127 | 128 | 如果 rabbitMQ 没能处理该消息,则会发送一个 Nack 消息给你,你可以进行重试操作。 129 | 130 | 消息队列丢数据:消息持久化。 131 | 132 | 处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。 133 | 134 | 这个持久化配置可以和 confirm 机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个 Ack 信号。 135 | 136 | 这样,如果消息持久化磁盘之前,rabbitMQ 阵亡了,那么生产者收不到 Ack 信号,生产者会自动重发。 137 | 138 | 那么如何持久化呢? 139 | 140 | 这里顺便说一下吧,其实也很容易,就下面两步 141 | 142 | 1. 将 queue 的持久化标识 durable 设置为 true, 则代表是一个持久的队列 143 | 2. 发送消息的时候将 deliveryMode=2 144 | 145 | 这样设置以后,即使 rabbitMQ 挂了,重启后也能恢复数据 146 | 147 | 消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可! 148 | 149 | 消费者在收到消息之后,处理消息之前,会自动回复 RabbitMQ 已收到消息; 150 | 151 | 如果这时处理消息失败,就会丢失该消息; 152 | 153 | 解决方案:处理消息成功后,手动回复确认消息。 154 | 155 | #### 17、如何保证 RabbitMQ 消息的顺序性? 156 | 157 | 单线程消费保证消息的顺序性;对消息进行编号,消费者处理消息是根据编号处理消息; 158 | 159 | #### 18. 死信队列和延迟队列的使用? 160 | 161 | **死信消息:** 162 | 163 | 消息被拒绝(Basic.Reject或Basic.Nack)并且设置 requeue 参数的值为 false 164 | 消息过期了 165 | 队列达到最大的长度 166 | 167 | **过期消息:** 168 | 169 | 在 rabbitmq 中存在2种方可设置消息的过期时间,第一种通过对队列进行设置,这种设置后,该队列中所有的消息都存在相同的过期时间,第二种通过对消息本身进行设置,那么每条消息的过期时间都不一样。如果同时使用这2种方法,那么以过期时间小的那个数值为准。当消息达到过期时间还没有被消费,那么那个消息就成为了一个 死信 消息。 170 | 171 | **队列设置:**在队列申明的时候使用 x-message-ttl 参数,单位为 毫秒 172 | 173 | **单个消息设置:**是设置消息属性的 expiration 参数的值,单位为 毫秒 174 | 175 | **延时队列:**在rabbitmq中不存在延时队列,但是我们可以通过设置消息的过期时间和死信队列来模拟出延时队列。消费者监听死信交换器绑定的队列,而不要监听消息发送的队列。 176 | 177 | ------ 178 | 179 | 有了以上的基础知识,我们完成以下需求: 180 | 181 | 需求:用户在系统中创建一个订单,如果超过时间用户没有进行支付,那么自动取消订单。 182 | 183 | 分析: 184 | 185 | 1、上面这个情况,我们就适合使用延时队列来实现,那么延时队列如何创建 186 | 2、延时队列可以由 过期消息+死信队列 来时间 187 | 3、过期消息通过队列中设置 x-message-ttl 参数实现 188 | 4、死信队列通过在队列申明时,给队列设置 x-dead-letter-exchange 参数,然后另外申明一个队列绑定x-dead-letter-exchange对应的交换器。 189 | 190 | #### 19. 使用了消息队列会有什么缺点? 191 | 192 | 1.系统可用性降低:你想啊,本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低 193 | 194 | 2.系统复杂性增加:要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。 195 | 196 | #### 20. 多个消费者监听一个队列时,消息如何分发? 197 | 198 | - 轮询: 默认的策略,消费者轮流,平均地接收消息 199 | - 公平分发: 根据消费者的能力来分发消息,给空闲的消费者发送更多消息 200 | 201 | 当消费者有x条消息没有响应ACK时,不再给这个消费者发送消息 202 | 203 | ```java 204 | channel.basicQos(int x) 205 | ``` 206 | 207 | 208 | 209 | #### 参考 210 | 211 | https://www.cnblogs.com/woadmin/p/10537174.html 212 | 213 | https://blog.csdn.net/thinkwon/article/details/104588612/ 214 | 215 | https://www.cnblogs.com/coder-programming/p/12465314.html -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 最近很多小伙伴问我要面试题,但面试题大多都比较零散,所以博主整理了一下,有一部分是从互联网收集整理所得,还有一部分是小咖自己从专栏、书籍学习所得。 2 | 目前有31个专题,277页。全文阅读时间可能几个小时,但是整理和创作要花的时间就要比阅读的时间多出至少十倍。 3 | 4 | 小编后面阅读书籍以及专栏等所得的部分,请不要直接发到互联网申请原创,如果要发请注明来源。 5 | 小编会持续的更新维护。大家可以加我微信进入群内,vx:baiseyumaoxx。一旦更新,我会通知大家。 6 | 7 | 手册是第二个版本了已经,原来是17个专题,新增了14个专题,希望对大家有用。 8 | 9 | 目前有如下专题: 10 | 11 | Java基础、Java集合、异常&反射、IO&NIO、Java多线程、JVM、Linux、MySql、Spring、Mybatis、Nginx、Redis、Dubbo、SpringBoot、Kafka、Spring Cloud、简历 12 | 13 | Netty、计算机基础、MongoDB、JSP、Servlet、Elasticsearch、Web安全、Tomcat、Zookeeper、Maven、Git、RabbitMQ、Java8、JVM 14 | 15 | 16 | 具体大家需要看的部分点击目录即可查看。pdf给大家准备好了。小编会持续更新... 17 | 18 | 扫描二维码回复:“面试2”即可获取pdf 19 | 20 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 21 | -------------------------------------------------------------------------------- /Redis-上卷.md: -------------------------------------------------------------------------------- 1 | ## Redis 2 | 3 | #### 1.Redis是什么? 4 | 5 | Redis是一个开放源代码(BSD许可)的内存中数据结构存储,可用作数据库,缓存和消息代理,是一个基于键值对的NoSQl数据库。 6 | 7 | #### 2.Redis特性? 8 | 9 | - 速度快 10 | - 基于键值对的数据结构服务器 11 | - 丰富的功能、丰富的数据结构 12 | - 简单稳定 13 | - 客户端语言多 14 | - 持久化 15 | - 主从复制 16 | - 高可以 & 分布式 17 | 18 | #### 3.Redis合适的应用场景? 19 | 20 | - 缓存 21 | - 排行榜 22 | - 计数器 23 | - 分布式会话 24 | - 分布式锁 25 | - 社交网络 26 | - 最新列表 27 | - 消息系统 28 | 29 | #### 4.除了Redis你还知道哪些NoSQL数据库? 30 | 31 | MongoDB、MemcacheDB、Cassandra、CouchDB、Hypertable、Leveldb。 32 | 33 | #### 5.Redis和Memcache区别? 34 | 35 | 支持的存储类型不同,memcached只支持简单的k/v结构。redis支持更多类型的存储结构类型(详见问题6)。 36 | 37 | memcached数据不可恢复,redis则可以把数据持久化到磁盘上。 38 | 39 | 新版本的redis直接自己构建了VM 机制 ,一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。 40 | 41 | redis当物理内存用完时,可以将很久没用到的value交换到磁盘。 42 | 43 | #### 6.Redis的有几种数据类型? 44 | 45 | 基础:字符串(String)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)。 46 | 47 | 还有HyperLogLog、流、地理坐标等。 48 | 49 | #### 7.Redis有哪些高级功能? 50 | 51 | 消息队列、自动过期删除、事务、数据持久化、分布式锁、附近的人、慢查询分析、Sentinel 和集群等多项功能。 52 | 53 | #### 8.安装过Redis吗,简单说下步骤? 54 | 55 | 1.下载Redis指定版本源码安装包压缩到当前目录。 56 | 57 | 1. 解压缩Redis源码安装包。 58 | 59 | 2. 建立一个redis目录软链接,指向解压包。 60 | 61 | 3. 进入redis目录 62 | 63 | 4. 编译 64 | 65 | 5. 安装 66 | 67 | 对于使用docker的童靴来说就比较容易了。 68 | 69 | docker pull redis 70 | 71 | #### 9.redis几个比较主要的可执行文件?分别是? 72 | 73 | ![image-20200425221430652](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200425221430652.png) 74 | 75 | #### 10.启动Redis的几种方式? 76 | 77 | 1.默认配置 : 78 | 79 | ./redis-server 80 | 81 | 2.运行启动: redis-server 加上要修改配置名和值(可以是多对),没有配置的将使用默认配置。 82 | 83 | 例如: redis-server ———port 7359 84 | 85 | 3.指定配置文件启动: 86 | 87 | ./redis-server /opt/redis/redis.conf 88 | 89 | #### 11.Redis配置需要自己写?如何配置? 90 | 91 | redis目录下有一个redis.conf的模板配置。所以只需要复制模板配置然后修改即可。 92 | 93 | 一般来说大部分生产环境都会用指定配置文件的方式启动redis。 94 | 95 | #### 12.Redis客户端命令执行的方式? 96 | 97 | 1.交互方式: 98 | 99 | ``` 100 | redis-cli -h 127.0.0.1 -p 6379 101 | ``` 102 | 103 | 连接到redis后,后面执行的命令就可以通过交互方式实现了。 104 | 105 | 2.命令行方式: 106 | 107 | ``` 108 | redis-cli -h 127.0.0.1 -p 6379 get value 109 | ``` 110 | 111 | #### 13.如何停止redis服务? 112 | 113 | Kill -9 pid (粗暴,请不要使用,数据不仅不会持久化,还会造成缓存区等资源不能被优雅关闭) 114 | 115 | 可以用redis 的shutdown 命令,可以选择是否在关闭前持久化数据。 116 | 117 | ``` 118 | redis-cli shutdown nosave|save 119 | ``` 120 | 121 | #### 14.如何查看当前键是否存在? 122 | 123 | exists key 124 | 125 | #### 15.如何删除数据? 126 | 127 | del key 128 | 129 | #### 16.redis为什么快?单线程? 130 | 131 | - redis使用了单线程架构和I/O多路复用模型模型。 132 | - 纯内存访问。 133 | - 由于是单线程避免了线程上下文切换带来的资源消耗。 134 | 135 | #### 17.字符串最大不能超过多少? 136 | 137 | 512MB 138 | 139 | #### 18.redis默认分多少个数据库? 140 | 141 | 16 142 | 143 | #### 19.redis持久化的几种方式? 144 | 145 | RDB、AOF、混合持久化。 146 | 147 | #### 20.RDB持久化? 148 | 149 | RDB(Redis DataBase)持久化是把当前进程数据生成快照保存到硬盘的过程。 150 | 151 | Tips:是以二进制的方式写入磁盘。 152 | 153 | #### 21.RDB的持久化是如何触发的? 154 | 155 | 手动触发: 156 | 157 | save: 阻塞当前Redis服务器,直到RDB过程完成为止,如果数据比较大的话,会造成长时间的阻塞, 158 | 159 | 线上不建议。 160 | 161 | bgsave:redis进程执行 fork操作创作子进程,持久化由子进程负责,完成后自动结束,阻塞只发生在 162 | 163 | fork阶段,一半时间很短。 164 | 165 | 自动触发: 166 | 167 | save xsecends n: 168 | 169 | 表示在x秒内,至少有n个键发生变化,就会触发RDB持久化。也就是说满足了条件就会触发持久化。 170 | 171 | flushall : 172 | 173 | 主从同步触发 174 | 175 | #### 22.RDB的优点? 176 | 177 | - rdb是一个紧凑的二进制文件,代表Redis在某个时间点上的数据快照。 178 | - 适合于备份,全量复制的场景,对于灾难恢复非常有用。 179 | - Redis加载RDB恢复数据的速度远快于AOF方式。 180 | 181 | #### 23.RDB的缺点? 182 | 183 | - RDB没法做到实时的持久化。中途意外终止,会丢失一段时间内的数据。 184 | - RDB需要fork()创建子进程,属于重量级操作,可能导致Redis卡顿若干秒。 185 | 186 | #### 24.如何禁用持久化? 187 | 188 | 一般来说生成环境不会用到,了解一下也有好处的。 189 | 190 | ``` 191 | config set save "" 192 | ``` 193 | 194 | #### 25.AOF持久化? 195 | 196 | AOF(append only file)为了解决rdb不能实时持久化的问题,aof来搞定。以独立的日志方式记录把每次命令记录到aof文件中。 197 | 198 | #### 26.如何查询AOF是否开启? 199 | 200 | ``` 201 | config get appendonly 202 | ``` 203 | 204 | #### 27.如何开启AOF? 205 | 206 | 命令行方式: 实时生效,但重启后失效。 207 | 208 | ``` 209 | config set appendonly 210 | ``` 211 | 212 | 配置文件:需要重启生效,重启后依然生效。 213 | 214 | ``` 215 | appendonly yes 216 | ``` 217 | 218 | #### 28.AOF工作流程? 219 | 220 | 1.所有写入命令追加到aof_buf缓冲区。 221 | 222 | 2.AOF缓冲区根据对应的策略向硬盘做同步操作。 223 | 224 | 3.随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。 225 | 226 | 4.当redis服务器重启时,可以加载AOF文件进行数据恢复。 227 | 228 | #### 29.为什么AOF要先把命令追加到缓存区(aof_buf)中? 229 | 230 | Redis使用单线程响应命令,如果每次写入文件命令都直接追加到硬盘,性能就会取决于硬盘的负载。如果使用缓冲区,redis提供多种缓冲区策略,在性能和安全性方面做出平衡。 231 | 232 | #### 30.AOF持久化如何触发的? 233 | 234 | 自动触发:满足设置的策略和满足重写触发。 235 | 236 | 策略:(在配置文件中配置) 237 | 238 | ![image-20200427101221526](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200427101221526.png 239 | 240 | 手动触发:(执行命令) 241 | 242 | ``` 243 | bgrewriteaof 244 | ``` 245 | 246 | #### 31.AOF优点? 247 | 248 | - AOF提供了3种保存策略:每秒保存、跟系统策略、每次操作保存。实时性比较高,一般来说会选择每秒保存,因此意外发生时顶多失去一秒的数据。 249 | - 文件追加写形式,所以文件很少有损坏问题,如最后意外发生少写数据,可通过redis-check-aof工具修复。 250 | - AOF由于是文本形式,直接采用协议格式,避免二次处理开销,另外对于修改也比较灵活。 251 | 252 | #### 32.AOF缺点? 253 | 254 | - AOF文件要比RDB文件大。 255 | - AOF冷备没RDB迅速。 256 | - 由于执行频率比较高,所以负载高时,性能没有RDB好。 257 | 258 | #### 33.混合持久化?优缺点? 259 | 260 | 一般来说我们的线上都会采取混合持久化。redis4.0以后添加了新的混合持久化方式。 261 | 262 | 优点: 263 | 264 | - 在快速加载的同时,避免了丢失过更多的数据。 265 | 266 | 缺点: 267 | 268 | - 由于混合了两种格式,所以可读性差。 269 | - 兼容性,需要4.0以后才支持。 270 | 271 | #### 34.Redis的Java客户端官方推荐?实际选择? 272 | 273 | 官方推荐的有3种:Jedis、Redisson和lettuce。 274 | 275 | 一般来说用的比较多的有:Jedis|Redisson。 276 | 277 | Jedis:更轻量、简介、不支持读写分离需要我们来实现,文档比较少。API提供了比较全面的Redis命令的支持。 278 | 279 | Redisson:基于Netty实现,性能高,支持异步请求。提供了很多分布式相关操作服务。高级功能能比较多,文档也比较丰富,但实用上复杂度也相对高。和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。 280 | 281 | #### 35.Redis事务? 282 | 283 | 事务提供了一种将多个命令请求打包,一次性、按顺序的执行多个命令的机制。并且在事务执行期间,服务器不会中断事务而改去执行其他客户端命令请求,它会 284 | 285 | #### 36.Redis事务开始到结束的几个阶段? 286 | 287 | - 开启事务 288 | - 命令入队 289 | - 执行事务/放弃事务 290 | 291 | #### 37.Redis中key的过期操作? 292 | 293 | ​ 设置key的生存时间为n秒 294 | 295 | ``` 296 | expire key nseconds 297 | ``` 298 | 299 | ​ 设置key的生存时间为nmilliseconds 300 | 301 | ``` 302 | pxpire key milliseconds 303 | ``` 304 | 305 | ​ 设置过期时间为timestamp所指定的秒数时间戳 306 | 307 | ``` 308 | expireat key timespamp 309 | ``` 310 | 311 | 设置过期时间为timestamp毫秒级时间戳 312 | 313 | ``` 314 | pexpireat key millisecondsTimestamp 315 | ``` 316 | 317 | #### 38.Redis过期键删除策略? 318 | 319 | 定时删除:在设置的过期时间同时,创建一个定时器在键的过期时间来临时,立即执行队键的操作删除。 320 | 321 | 惰性删除:放任过期键不管,但每次从键空间中获取键时,都检查取得的键是否过期,如果过期就删除,如果没有就返回该键。 322 | 323 | 定期删除:每隔一段时间执行一次删除过期键操作,并通过先吃删除操作执行的时长和频率来减少删除操作对cpu时间的影响。 324 | 325 | #### 39.Pipeline是什么?为什么要它? 326 | 327 | 命令批处理技术,对命令进行组装,然后一次性执行多个命令。 328 | 329 | 可以有效的节省RTT(Round Trip Time 往返时间)。 330 | 331 | 经过测试验证: 332 | 333 | - pipeline执行速度一般比逐条执行快。 334 | - 客户端和服务的网络延越大,pipeline效果越明显。 335 | 336 | #### 40.如何获取当前最大内存?如何动态设置? 337 | 338 | 获取最大内存: 339 | 340 | ``` 341 | config get maxmemory 342 | ``` 343 | 344 | 设置最大内存: 345 | 346 | 命令设置: 347 | 348 | ``` 349 | config set maxmemory 1GB 350 | ``` 351 | 352 | #### 41.Redis内存溢出控制? 353 | 354 | 当Redis所用内存达到maxmemory上限时,会出发相应的溢出策略。 355 | 356 | #### 42.Redis内存溢出策略? 357 | 358 | 1.noeviction(默认策略):拒绝所有写入操作并返回客户端错误信息(error) OOM command not allowed when used memory,只响应读操作。 359 | 360 | 1. volatile-lru:根据LRU算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略。 361 | 2. allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性, 直到腾出足够空间为止。 362 | 3. allkeys-random:随机删除所有键,直到腾出足够空间为止。 363 | 4. volatile-random:随机删除过期键,直到腾出足够空间为止。 364 | 5. volatile-tth根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略。 365 | 366 | #### 43.Redis高可用方案? 367 | 368 | Redis Sentinel(哨兵)能自动完成故障发现和转移。 369 | 370 | #### 44.Redis集群方案? 371 | 372 | Twemproxy、Redis Cluster、Codis。 373 | 374 | #### 45.Redis Cluster槽范围? 375 | 376 | 0~16383 377 | 378 | #### 46.Redis锁实现思路? 379 | 380 | setnx (set if not exists),如果创建成功则表示获取到锁。 381 | 382 | setnx lock true 创建锁 383 | 384 | del lock 释放锁 385 | 386 | 如果中途崩溃,无法释放锁? 387 | 388 | 此时需要考虑到超时时间的问题。比如 :expire lock 300 389 | 390 | 由于命令是非原子的,所以还是会死锁,如何解决? 391 | 392 | Redis 支持 set 并设置超时时间的功能。 393 | 394 | 比如: set lock true ex 30 nx 395 | 396 | #### 47.什么是布隆过滤器? 397 | 398 | 是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。 399 | 400 | Tips:当判断一定存在时,可能会误判,当判断不存在时,就一定不存在。 401 | 402 | #### 48.什么是缓存穿透?处理问题? 403 | 404 | 缓存穿透:缓存层不命中,存储层不命中。 405 | 406 | 处理方式1:缓存空对象,不过此时会占用更多内存空间,所以根据大家业务特性去设置超时时间来控制内存占用的问题。 407 | 408 | 处理方式2:布隆过滤器。 409 | 410 | #### 49.什么是缓存预热? 411 | 412 | 就是系统上线后,提前将相关数据加载到缓存系统,避免用户先查库,然后在缓存。 413 | 414 | #### 50.什么是缓存雪崩?处理问题? 415 | 416 | 缓存雪崩:由于缓存层承载着大量请求,有效的保护了存储层,但如果存储层由于某些原因不能提供服务,存储层调用暴增,造成存储层宕机。 417 | 418 | 处理: 419 | 420 | - 保证缓存层服务高可用性。 421 | - 对缓存系统做实时监控,报警等。 422 | - 依赖隔离组件为后端限流并降级。 423 | - 做好持久化,以便数据的快速恢复。 424 | 425 | 参考: 426 | 427 | - 《Redis深度历险:核心原理和应用实践》 428 | - 《Redis开发与运维》 429 | - 《Redis设计与实现》 430 | - https://redis.io/ 431 | - 百度百科 432 | 433 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) -------------------------------------------------------------------------------- /Redis-下卷.md: -------------------------------------------------------------------------------- 1 | ## Redis 2 | 3 | #### 1.查看配置语法 4 | 5 | ``` 6 | CONFIG GET CONFIG_SETTING_NAME 7 | ``` 8 | 9 | #### 2.获取所有配置项 10 | 11 | ``` 12 | 127.0.0.1:6379> config get * 13 | 1) "dbfilename" 14 | 2) "dump.rdb" 15 | 3) "requirepass" 16 | 4) "" 17 | 5) "masterauth" 18 | 6) "" 19 | 7) "cluster-announce-ip" 20 | 8) "" 21 | 9) "unixsocket" 22 | 10) "" 23 | 11) "logfile" 24 | 12) "" 25 | ... 26 | ``` 27 | 28 | #### 3.设置字符串 29 | 30 | ``` 31 | 127.0.0.1:6379> set xk www.javaxks.com 32 | OK 33 | ``` 34 | 35 | #### 4.获取字符串 36 | 37 | ``` 38 | 127.0.0.1:6379> get xk 39 | "www.javaxks.com" 40 | ``` 41 | 42 | #### 5.获取随机key 43 | 44 | ``` 45 | 127.0.0.1:6379> randomkey 46 | "xk" 47 | ``` 48 | 49 | #### 6.获取key存储的类型 50 | 51 | ``` 52 | 127.0.0.1:6379> randomkey 53 | "xk" 54 | ``` 55 | 56 | #### 7.判断key是否存在 57 | 58 | ``` 59 | 127.0.0.1:6379> randomkey 60 | "xk" 61 | ``` 62 | 63 | #### 8.修改key的名称 64 | 65 | ``` 66 | 127.0.0.1:6379> randomkey 67 | "xk" 68 | ``` 69 | 70 | #### 9.返回key存储的字符串的长度 71 | 72 | ``` 73 | 127.0.0.1:6379> randomkey 74 | "xk" 75 | ``` 76 | 77 | #### 10.同时设置多个kv对 78 | 79 | ``` 80 | 127.0.0.1:6379> mset date 5.21 mood haha 81 | OK 82 | ``` 83 | 84 | #### 11.获取多个key的值 85 | 86 | ``` 87 | 127.0.0.1:6379> mget date mood 88 | 1) "5.21" 89 | 2) "haha" 90 | ``` 91 | 92 | #### 12.设置key 10秒后过期 93 | 94 | ``` 95 | 127.0.0.1:6379> expire date 10 96 | (integer) 1 97 | ``` 98 | 99 | #### 13.查看当前还剩几秒过期 100 | 101 | ``` 102 | 127.0.0.1:6379> ttl date 103 | (integer) 4 104 | ``` 105 | 106 | #### 14.过期后获取key 107 | 108 | ``` 109 | 127.0.0.1:6379> get date 110 | (nil) 111 | ``` 112 | 113 | #### 15.列表最多可以存多少元素 114 | 115 | 2的32次方 - 1 116 | 117 | #### 16.从左向列表中添加元素 118 | 119 | ``` 120 | 127.0.0.1:6379> lpush fruit apple 121 | (integer) 1 122 | 127.0.0.1:6379> lpush fruit strawberry 123 | (integer) 2 124 | 127.0.0.1:6379> lpush fruit pear 125 | (integer) 3 126 | 127.0.0.1:6379> lpush fruit orange 127 | (integer) 4 128 | ``` 129 | 130 | #### 17.获取列表中所有的元素 131 | 132 | ``` 133 | 127.0.0.1:6379> lrange fruit 0 -1 134 | 1) "orange" 135 | 2) "pear" 136 | 3) "strawberry" 137 | 4) "apple" 138 | ``` 139 | 140 | #### 18.从左弹出元素 141 | 142 | ``` 143 | 127.0.0.1:6379> lpop fruit 144 | "orange" 145 | 127.0.0.1:6379> lrange fruit 0 -1 146 | 1) "pear" 147 | 2) "strawberry" 148 | 3) "apple" 149 | ``` 150 | 151 | #### 19.获取指定位置的元素 152 | 153 | ``` 154 | 127.0.0.1:6379> lindex fruit 2 155 | "apple" 156 | ``` 157 | 158 | #### 20.获取列表长度 159 | 160 | ``` 161 | 127.0.0.1:6379> llen fruit 162 | (integer) 3 163 | ``` 164 | 165 | #### 21.集合 166 | 167 | set是string类型的无序集合,集合中的元素都是唯一的。 168 | 169 | #### 22.向集合中添加元素 170 | 171 | ``` 172 | 127.0.0.1:6379> sadd books java 173 | (integer) 1 174 | 127.0.0.1:6379> sadd books python 175 | (integer) 1 176 | 127.0.0.1:6379> sadd books php 177 | (integer) 1 178 | 127.0.0.1:6379> sadd books go 179 | (integer) 1 180 | 127.0.0.1:6379> sadd books ruby 181 | (integer) 1 182 | ``` 183 | 184 | #### 23.获取集合中的元素 185 | 186 | ``` 187 | 127.0.0.1:6379> smembers books 188 | 1) "go" 189 | 2) "python" 190 | 3) "java" 191 | 4) "php" 192 | 5) "ruby" 193 | ``` 194 | 195 | #### 24.删除集合中的指定元素 196 | 197 | ``` 198 | 127.0.0.1:6379> srem books ruby 199 | (integer) 1 200 | 127.0.0.1:6379> smembers books 201 | 1) "php" 202 | 2) "java" 203 | 3) "python" 204 | 4) "go" 205 | ``` 206 | 207 | #### 25.zset类型 208 | 209 | 有序的集合 210 | 211 | 元素为string类型 212 | 213 | 元素唯一,不重复。每个元素有自己的权重。 214 | 215 | #### 26.向有序集合中添加元素 216 | 217 | ``` 218 | 127.0.0.1:6379> zadd animal 1 monkey 219 | (integer) 1 220 | 127.0.0.1:6379> zadd animal 2 chicken 221 | (integer) 1 222 | 127.0.0.1:6379> zadd animal 3 mouse 223 | (integer) 1 224 | 127.0.0.1:6379> zadd animal 4 horse 225 | (integer) 1 226 | ``` 227 | 228 | #### 27.获取有序集合元素个数 229 | 230 | ``` 231 | 127.0.0.1:6379> zcard animal 232 | (integer) 4 233 | ``` 234 | 235 | #### 28.获取所有元素 236 | 237 | ``` 238 | 127.0.0.1:6379> zrange animal 0 -1 239 | 1) "monkey" 240 | 2) "chicken" 241 | 3) "mouse" 242 | 4) "horse" 243 | ``` 244 | 245 | #### 29.获取所有元素并带上分值 246 | 247 | ``` 248 | 127.0.0.1:6379> zrange animal 0 -1 withscores 249 | 1) "monkey" 250 | 2) "1" 251 | 3) "chicken" 252 | 4) "2" 253 | 5) "mouse" 254 | 6) "3" 255 | 7) "horse" 256 | 8) "4" 257 | ``` 258 | 259 | #### 30.HyperLogLog 260 | 261 | Redis 在 2.8.9 版本添加了 HyperLogLog 结构。 262 | 263 | Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。 264 | 265 | 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。 266 | 267 | 但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。 268 | 269 | #### 31.向HyperLogLog中添加元素 270 | 271 | ``` 272 | 127.0.0.1:6379> pfadd color blue 273 | (integer) 1 274 | 127.0.0.1:6379> pfadd color yellow 275 | (integer) 1 276 | 127.0.0.1:6379> pfadd color pink 277 | (integer) 1 278 | 127.0.0.1:6379> pfadd color white 279 | (integer) 1 280 | 127.0.0.1:6379> pfadd color black 281 | (integer) 1 282 | ``` 283 | 284 | #### 32.获取HyperLogLog元素个数 285 | 286 | ``` 287 | 127.0.0.1:6379> pfcount color 288 | (integer) 5 289 | ``` 290 | 291 | #### 33.发布订阅 292 | 293 | 种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。 294 | 295 | Redis 客户端可以订阅任意数量的频道。 296 | 297 | #### 34.创建订阅频道 298 | 299 | ``` 300 | 127.0.0.1:6379> subscribe everydayNews 301 | Reading messages... (press Ctrl-C to quit) 302 | 1) "subscribe" 303 | 2) "everydayNews" 304 | 3) (integer) 1 305 | 1) "message" 306 | ``` 307 | 308 | #### 35.在对应频道发布消息 309 | 310 | ``` 311 | 127.0.0.1:6379> publish everydayNews "morning" 312 | (integer) 1 313 | ``` 314 | 315 | 订阅者收到: 316 | 317 | ``` 318 | Reading messages... (press Ctrl-C to quit) 319 | 1) "subscribe" 320 | 2) "everydayNews" 321 | 3) (integer) 1 322 | 1) "message" 323 | 2) "everydayNews" 324 | 3) "morning" 325 | ``` 326 | 327 | #### 36.非后台执行备份 328 | 329 | ``` 330 | 127.0.0.1:6379> save 331 | OK 332 | ``` 333 | 334 | #### 37.后台执行备份 335 | 336 | ``` 337 | 127.0.0.1:6379> BGSAVE 338 | Background saving started 339 | ``` 340 | 341 | #### 38.查看是否需要密码验证 342 | 343 | ``` 344 | 127.0.0.1:6379> config get requirepass 345 | 1) "requirepass" 346 | 2) "" 347 | ``` 348 | 349 | 350 | 351 | #### 参考: 352 | 353 | https://redis.io/ 354 | 355 | http://redisdoc.com/ 356 | 357 | https://www.runoob.com/redis/ 358 | 359 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) -------------------------------------------------------------------------------- /Servlet.md: -------------------------------------------------------------------------------- 1 | ## Servlet 2 | 3 | #### 1.Servlet生命周期 4 | 5 | servlet的生命周期是初始化(init)、服务(service)、销毁(destroy) 6 | 7 | 初始化(init):默认第一次请求前,只初始化一次。修改web.xml,允许服务器启动时初始化。 8 | 服务(service):方法被调用时进行服务,在项目启动期间可以进行多次服务(请求一次执行一次) 9 | 销毁(destory):当服务器关闭时进行销毁。只销毁一次 10 | Servlet接口中声明3个方法,tomcat在不同的时候将调用不同的方法。 11 | init 初始化方法,2种情况被调用 12 | 情况1:默认,第一次请求前 13 | 情况2:在web项目核心配置文件web.xml中,配置初始化,将在服务器启动时初始化。 14 | 每次请求时,调用服务 15 | 服务器关闭时,调用销毁。 16 | 17 | #### 2.什么是jsp?jsp和Servlet有什么区别? 18 | 19 | Servlet是服务器端的程序 20 | JSP是服务器页面程序 21 | JSP本质上就是一个Servlet,在访问jsp时,在服务器端会将jsp先转换成servlet,再将生产的servlet的结果响应给浏览器。 22 | jsp是html页面中内嵌Java代码,侧重页面显示;Servlet是中书写Java代码,侧重逻辑控制; 23 | 24 | ![img](https://img-blog.csdnimg.cn/20200910144535754.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI1ODU0NTk5,size_16,color_FFFFFF,t_70#pic_center) 25 | 26 | #### 3.Servlet 接口中有哪些方法? 27 | 28 | 1. init(ServletConfig):初始化方法,默认第一次请求前执行,完成 servlet 初始化工作 29 | 30 | 2. service(ServletRequest,ServletResponse):执行方法,一次请求执行一次。 31 | 32 | 3. destroy():销毁方法,Servlet 对象应该从服务中被移除的时候,容器会调用该方法进行销毁操作 33 | 34 | 4. getServletConfig():获得 ServletConfig 配置对象,包括初始化参数等。 35 | 36 | 5. getServletInfo():获得 Servlet 描述,一般没有用。 37 | 38 | ![img](https://img-blog.csdnimg.cn/20200910144604142.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI1ODU0NTk5,size_16,color_FFFFFF,t_70#pic_center) 39 | 40 | 41 | 42 | #### 4.Servlet 3.0 中的异步处理指的是什么? 43 | 44 | 异步处理允许 Servlet 重新发起一条新线程去调用 耗时业务方法,这样就可以避免等待 45 | 46 | ![img](https://img-blog.csdnimg.cn/2020091014463133.png#pic_center) 47 | 48 | #### 5.Servlet 中如何获取用户提交的查询参数或表单数据? 49 | 50 | 1. request.getParameterValues(“参数”); // 获得指定参数名的一组参数值 (String[]) 51 | 2. request.getParameter(“参数”); // 获得指定参数名的一个参数值(String) , UserServlet?username=jack , 通过 username 获得值 jack 52 | 53 | ``` 54 | public class TestRequestParam { 55 | private HttpServletRequest request; 56 | 57 | public void testDemo01(){ 58 | //请求数据:index.html?username=jack&hobby=抽烟&hobby=喝酒&hobby=烫头 59 | 60 | // 获得username的值,一个值 61 | String username = request.getParameter("username"); 62 | 63 | // 获得hobby的值,一组值 64 | String[] hobbyArr = request.getParameterValues("hobby"); 65 | 66 | // 所有值 , map.key 参数名称,map.value 参数的值 67 | Map map = request.getParameterMap(); 68 | 69 | } 70 | } 71 | ``` 72 | 73 | #### 6.区别请求的转发与重定向? 74 | 75 | 可以从以下三个方面进行比较 76 | 77 | 1.地址栏: 78 | 79 | 转发: 显示的是请求的URL 80 | 81 | 重定向: 显示的不是请求的URL, 而是重定向指向的新的URL 82 | 83 | 2.浏览器发了几次请求? 84 | 85 | 转发: 1次请求 86 | 87 | 重定向: 2次请求 88 | 89 | 1. 是否可以进行Request的数据共享? 90 | 91 | 转发: 两个资源之间是同一个request对象, 可以共享request中的数据 92 | 93 | 重定向: 两个资源之间不是同一个request对象, 不可以共享 94 | 95 | **经典现实案例:** 96 | 97 | ![Servlet相关技术常见面试题](https://img-blog.csdnimg.cn/img_convert/48ff7f8346d74c66da6806855a4b4cb7.png) 98 | 99 | #### 7. 比较一下Servlet与Filter 100 | 101 | 从四个方面来区分: 102 | 103 | **概念** 104 | 105 |   servlet是一种运行在服务器端的Java应用程序,独立于平台和协议,可以动态的生成web页面,它工作于客户端请求和服务器的中间层 106 | 107 |   filter是一个可以复用的代码片段,可以用来转换请求,响应以及头信息,filter不能产生请求和响应,他只能在请求到达servlet之前对请求进行修改,或者在请求返回客户端之前对响应进行处理 108 | 109 | **生命周期** 110 | 111 |   servlet是在系统启动或者请求到达servlet时,通过init()方法进行初始化,一旦被装入了web服务器,一般不会从Web服务器删除,直到服务器关闭才会调用  destroy()方法进行销毁。每次请求,Request都会被初始化,响应请求后,请求被销毁。但是servlet不会随着请求的销毁而销毁 112 | 113 |   如果某个Servlet配置了 1 ,该Servlet也是在Tomcat(Servlet容器)启动时初始化。 114 |   如果Servlet没有配置1 ,该Servlet不会在Tomcat启动时初始化,而是在请求到来时初始化。 115 | 116 |   filter 117 | 118 |     是在系统启动的时候通过init()初始化的,每次请求都只会调用dofiter方法进行处理,服务器停止的时候调用destroy()进行销毁 119 | 120 | **注意**:服务器关闭时,servlet和filter依次销毁 121 | 122 | **职责** 123 | 124 |   **servlet** 125 | 126 |     可以动态创建基于客户请求的页面;可以读取客户端发来的隐藏数据和显示数据;可以和其他的服务器资源进行通讯;通过状态代码和响应头向客户端返回数据。 127 | 128 |   **filter** 129 | 130 |     主要是对请求到达servlet之前对请求和请求头信息进行前处理,和对数据返回客户端之前进行后处理 131 | 132 | **区别** 133 | 134 |   servlet的流程比较短,url来了之后就对其进行处理,处理完就返回数据或者转向另一个页面 135 | 136 |   filter的流程比较长,在一个filter处理之后还可以转向另一个filter进行处理,然后再交给servlet,但是servlet处理之后不能向下传递了。 137 | 138 |   filter可用来进行字符编码的过滤,检测用户是否登陆的过滤,禁止页面缓存等 139 | 140 | #### 8.我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串? 141 | 142 | ``` 143 |  Public String translate (String str) { 144 |     String tempStr = ""; 145 | 146 |     try { 147 |       tempStr = new String(str.getBytes("ISO-8859-1"), "GBK"); 148 | 149 |       tempStr = tempStr.trim(); 150 | 151 |     } 152 | 153 |     catch (Exception e) { 154 |       System.err.println(e.getMessage()); 155 | 156 |     } 157 | 158 |     return tempStr; 159 | 160 |   } 161 | ``` 162 | 163 | #### 9.Servlet执行时一般实现哪几个方法? 164 | 165 | public void init(ServletConfig config) 166 | 167 | public ServletConfig getServletConfig() 168 | 169 | public String getServletInfo() 170 | 171 | public void service(ServletRequest request,ServletResponse response) 172 | 173 | public void destroy() 174 | 175 | 176 | #### 10.描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理。 177 | 178 | 1)cookie 是一种发送到客户浏览器的文本串句柄,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据。 179 | 180 | 2)session其实指的就是访问者从到达某个特定主页到离开为止的那段时间。 Session其实是利用Cookie进行信息处理的,当用户首先进行了请求后,服务端就在用户浏览器上创建了一个Cookie,当这个Session结束时,其实就是意味着这个Cookie就过期了。 181 | 182 | 注:为这个用户创建的Cookie的名称是aspsessionid。这个Cookie的唯一目的就是为每一个用户提供不同的身份认证。 183 | 184 | 3)cookie和session的共同之处在于:cookie和session都是用来跟踪浏览器用户身份的会话方式。 185 | 186 | 4)cookie 和session的区别是:cookie数据保存在客户端,session数据保存在服务器端。 187 | 188 | 5)session工作原理:session技术中所有的数据都保存在服务器上,客户端每次请求服务器的时候会发送当前会话的sessionid,服务器根据当前sessionid判断相应的用户数据标志,以确定用户是否登录或具有某种权限。 189 | 190 | #### 11.Applet和Servlet有什么区别? 191 | 192 | Applet是运行在客户端主机的浏览器上的客户端Java程序。而Servlet是运行在web服务器上的服务端的组件。applet可以使用用户界面类,而Servlet没有用户界面,相反,Servlet是等待客户端的HTTP请求,然后为请求产生响应。 193 | 194 | #### 12.GenericServlet和HttpServlet有什么区别? 195 | 196 | GenericServlet是一个通用的协议无关的Servlet,它实现了Servlet和ServletConfig接口。继承自GenericServlet的Servlet应该要覆盖service()方法。最后,为了开发一个能用在网页上服务于使用HTTP协议请求的Servlet,你的Servlet必须要继承自HttpServlet。这里有Servlet的例子。 197 | 198 | #### 13.什么是服务端包含(Server Side Include)? 199 | 200 | 服务端包含(SSI)是一种简单的解释型服务端脚本语言,大多数时候仅用在Web上,用servlet标签嵌入进来。SSI最常用的场景把一个或多个文件包含到Web服务器的一个Web页面中。当浏览器访问Web页面的时候,Web服务器会用对应的servlet产生的文本来替换Web页面中的servlet标签。 201 | 202 | #### 14.什么是Servlet链(Servlet Chaining)? 203 | 204 | Servlet链是把一个Servlet的输出发送给另一个Servlet的方法。第二个Servlet的输出可以发送给第三个Servlet,依次类推。链条上最后一个Servlet负责把响应发送给客户端。 205 | 206 | #### 15.如何知道是哪一个客户端的机器正在请求你的Servlet 207 | 208 | ServletRequest类可以找出客户端机器的IP地址或者是主机名。getRemoteAddr()方法获取客户端主机的IP地址,getRemoteHost()可以获取主机名。看下这里的例子。 209 | 210 | #### 16.什么是cookie?session和cookie有什么区别? 211 | 212 | cookie是Web服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个Web服务器存储cookie。以后浏览器在给特定的Web服务器发请求的时候,同时会发送所有为该服务器存储的cookie。下面列出了session和cookie的区别: 213 | 214 | • 无论客户端浏览器做怎么样的设置,session都应该能正常工作。客户端可以选择禁用cookie,但是,session仍然是能够工作的,因为客户端无法禁用服务端的session。 215 | 216 | • 在存储的数据量方面session和cookies也是不一样的。session能够存储任意的Java对象,cookie只能存储String类型的对象。 217 | 218 | #### 17.浏览器和Servlet通信使用的是什么协议? 219 | 220 | 浏览器和Servlet通信使用的是HTTP协议。 221 | 222 | #### 18.什么是URL编码和URL解码? 223 | 224 | URL编码是负责把URL里面的空格和其他的特殊字符替换成对应的十六进制表示,反之就是解码。 225 | 226 | JSP 227 | 228 | #### 19.什么是Scriptlets? 229 | 230 | JSP技术中,scriptlet是嵌入在JSP页面中的一段Java代码。scriptlet是位于标签内部的所有的东西,在标签与标签之间,用户可以添加任意有效的scriplet。 231 | 232 | #### 20.声明(Decalaration)在哪里? 233 | 234 | 声明跟Java中的变量声明很相似,它用来声明随后要被表达式或者scriptlet使用的变量。添加的声明必须要用开始和结束标签包起来。 235 | 236 | #### 237 | 238 | #### 参考: 239 | 240 | https://blog.csdn.net/qq_25854599/article/details/108513815 241 | 242 | https://blog.csdn.net/msjhw_com/article/details/113240556 243 | 244 | https://www.cnblogs.com/htyj/p/8619198.html 245 | 246 | https://blog.csdn.net/Jeff_Seid/article/details/80761076 247 | 248 | -------------------------------------------------------------------------------- /Spring.md: -------------------------------------------------------------------------------- 1 | ## Spring 2 | 3 | #### 1.Spring框架? 4 | 5 | Spring框架是由于软件开发的复杂性而创建的,Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事。从简单性、可测性和松耦合性角度而言,绝大部分Java应用都可以用Spring。 6 | 7 | #### 2.Spring的整体架构? 8 | 9 | ![image-20200425151510055](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200425151510055.png) 10 | 11 | 12 | 13 | 大约分为20个模块。 14 | 15 | #### 3.Spring可以做什么? 16 | 17 | ![image-20200425152654798](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200425152654798.png) 18 | 19 | #### 4.Spring的优点?缺点? 20 | 21 | 优点: 22 | 23 | - Spring属于低侵入设计。 24 | - IOC将对象之间的依赖关系交给Spring,降低组件之间的耦合,实现各个层之间的解耦,让我们更专注于业务逻辑。 25 | - 提供面向切面编程。 26 | - 对各种主流插件提供很好的集成支持。 27 | - 对事务支持的很好,只要配置即可,无须手动控制。 28 | 29 | 缺点: 30 | 31 | - 依赖反射,影响性能。 32 | 33 | #### 5.你能说几个Spring5的新特性吗? 34 | 35 | - spring5整个框架基于java8 36 | - 支持http/2 37 | - Spring Web MVC支持最新API 38 | - Spring WebFlux 响应式编程 39 | - 支持Kotlin函数式编程 40 | 41 | #### 6.IOC? 42 | 43 | 负责创建对象、管理对象(通过依赖注入)、整合对象、配置对象以及管理这些对象的生命周期。 44 | 45 | #### 7.什么是依赖注入? 46 | 47 | 依赖注入是Spring实现IoC的一种重要手段,将对象间的依赖关系的控制权从开发人员手里转移到容器。 48 | 49 | #### 8.IOC注入哪几种方式? 50 | 51 | 1.构造器注入 52 | 53 | 2.setter注入 54 | 55 | 3.接口注入(我们几乎不用) 56 | 57 | #### 9.IOC优点?缺点? 58 | 59 | 优点: 60 | 61 | - 组件之间的解耦,提高程序可维护性、灵活性。 62 | 63 | 缺点: 64 | 65 | - 创建对象步骤复杂,有一定学习成本。 66 | - 利用反射创建对象,效率上有损。(对于代码的灵活性和可维护性来看,Spring对于我们的开发带来了很大的便利,这点损耗不算什么哦) 67 | 68 | #### 10.bean的生命周期? 69 | 70 | 1.Spring 对bean进行实例化。 71 | 72 | 2.Spring将值和bean的引用注入到 bean对应的属性中。 73 | 74 | 3.如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()方法。 75 | 76 | 4.如果bean实现了BeanFactoryAware接口, Spring将调用setBeanFactory()方法,将 bean所在的应用引用传入进来。 77 | 78 | 5.如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用引用传入进来。 79 | 80 | 6.如果bean实现了BeanPostProcessor 接口,Spring将调用他们的post-ProcessBeforeInitalization()方法。 81 | 82 | 7.如果bean实现了InitializingBean接口,Spring将调用他们的after-PropertiesSet()方法,类似地,如果bean使用init-method声明了初始化方法,该方法也会被调用。 83 | 84 | 8.如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialization()方法。 85 | 86 | 9.此时, bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用被销毁。 87 | 88 | 10.如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。 89 | 90 | #### 11.Spring有几种配置方式? 91 | 92 | - 基于xml 93 | - 基于注解 94 | - 基于Java 95 | 96 | #### 12.Spring中的bean有几种scope? 97 | 98 | - singleton: 单例,每一个bean只创建一个对象实例。 99 | - prototype,原型,每次对该bean请求调用都会生成各自的实例。 100 | - request,请求,针对每次HTTP请求都会生成一个新的bean。表示在一次 HTTP 请求内有效。 101 | - session,在一个http session中,一个bean定义对应一个bean实例。 102 | - global session:在一个全局http session中,一个bean定义对应一个bean实例。 103 | 104 | #### 13.什么是AOP(面向切面编程)? 105 | 106 | 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 107 | 108 | #### 14.切面有几种类型的通知?分别是? 109 | 110 | 前置通知(Before): 目标方法被调用之前调用通知功能。 111 | 112 | 后置通知(After): 目标方法完成之后调用通。 113 | 114 | 返回通知(After-returning): 目标方法成功执行之后调用通知。 115 | 116 | 异常通知(After-throwing): 目标方法抛出异常后调用通知。 117 | 118 | 环绕通知(Around): 在被通知的方法调用之前和调用之后执行自定义的行为。 119 | 120 | #### 15.什么是连接点 (Join point)? 121 | 122 | 连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。 123 | 124 | #### 16.什么是切点(Pointcut)? 125 | 126 | 切点的定义会匹配通知所要织入的一个或多个连接点。我们通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。有些AOP框架允许我们创建动态的切点,可以根据运行时的决策(比如方法的参数值)来决定是否应用通知。 127 | 128 | #### 17.什么是切面(Aspect)? 129 | 130 | 切面是通知和切点的结合。通知和切点共同定义了切面的全部内容。 131 | 132 | #### 18.织入(Weaving)? 133 | 134 | 织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。 135 | 136 | #### 19.引入(Introduction)? 137 | 138 | 􏶸􏰫􏶹􏵡􏰸􏱲􏰇􏲘􏱴􏰉􏵇􏶺􏶻􏶼􏰽􏱸􏵼􏶽􏶾􏱎􏶸􏰫􏶹􏵡􏰸􏱲􏰇􏲘􏱴􏰉􏵇􏶺􏶻􏶼􏰽􏱸􏵼􏶽􏶾􏱎引入允许我们向现有的类添加新方法或属性。 139 | 140 | #### 20.在目标对象的生命周期里有多个点可以进行织入? 141 | 142 | - 编译期:切面在目标类编译时被织入。AspectJ的织入编译器就是以这种方式织入切面的。 143 | - 类加载期:切面在目标类加载到JVM时被织入。它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ 5的加载时织入(load-time weaving,LTW)就支持以这种方式织入切面。 144 | - 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的。 145 | 146 | #### 21.AOP动态代理策略? 147 | 148 | - 如果目标对象实现了接口,默认采用JDK 动态代理。可以强制转为CgLib实现AOP。 149 | - 如果没有实现接口,采用CgLib进行动态代理。 150 | 151 | #### 22.什么是MVC框架? 152 | 153 | MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。 154 | 155 | MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。 156 | 157 | #### 23.什么是SpringMVC? 158 | 159 | SpringMVC是Spring框架的一个模块。是一个基于MVC的框架。 160 | 161 | #### 24.SpringMVC的核心? 162 | 163 | DispatcherServlet 164 | 165 | #### 25.SpringMVC的几个组件? 166 | 167 | DispatcherServlet : 前端控制器,也叫中央控制器。相关组件都是它来调度。 168 | 169 | HandlerMapping : 处理器映射器,根据URL路径映射到不同的Handler。 170 | 171 | HandlerAdapter : 处理器适配器,按照HandlerAdapter的规则去执行Handler。 172 | 173 | Handler : 处理器,由我们自己根据业务开发。 174 | 175 | ViewResolver : 视图解析器,把逻辑视图解析成具体的视图。 176 | 177 | View : 一个接口,它的实现支持不同的视图类型(freeMaker,JSP等) 178 | 179 | #### 26.SpringMVC工作流程? 180 | 181 | 1.用户请求旅程的第一站是DispatcherServlet。 182 | 183 | 2.收到请求后,DispatcherServlet调用HandlerMapping,获取对应的Handler。 184 | 185 | 3.如果有拦截器一并返回。 186 | 187 | 4.拿到Handler后,找到HandlerAdapter,通过它来访问Handler,并执行处理器。 188 | 189 | 5.执行Handler的逻辑。 190 | 191 | 6.Handler会返回一个ModelAndView对象给DispatcherServlet。 192 | 193 | 7.将获得到的ModelAndView对象返回给DispatcherServlet。 194 | 195 | 8.请求ViewResolver解析视图,根据逻辑视图名解析成真正的View。 196 | 197 | 9.返回View给DispatcherServlet。 198 | 199 | 10.DispatcherServlet对View进行渲染视图。 200 | 201 | 11.DispatcherServlet响应用户。 202 | 203 | #### 27.SpringMVC的优点? 204 | 205 | 1.具有Spring的特性。 206 | 207 | 2.可以支持多种视图(jsp,freemaker)等。 208 | 209 | 3.配置方便。 210 | 211 | 4.非侵入。 212 | 213 | 5.分层更清晰,利于团队开发的代码维护,以及可读性好。 214 | 215 | Tips:Jsp目前很少有人用了。 216 | 217 | #### 28.单例bean是线程安全的吗? 218 | 219 | 不是。具体线程问题需要开发人员来处理。 220 | 221 | #### 29.Spring从哪两个角度实现自动装配? 222 | 223 | 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。 224 | 225 | 自动装配(autowiring):Spring自动满足bean之间的依赖。 226 | 227 | #### 30.自动装配有几种方式?分别是? 228 | 229 | no - 默认设置,表示没有自动装配。 230 | 231 | byName : 根据名称装配。 232 | 233 | byType : 根据类型装配。 234 | 235 | constructor : 把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。 236 | 237 | autodetect :先尝试constructor装配,失败再尝试byType方式。 238 | 239 | default:由上级标签的default-autowire属性确定。 240 | 241 | #### 31.说几个声明Bean 的注解? 242 | 243 | - @Component 244 | - @Service 245 | - @Repository 246 | - @Controller 247 | 248 | #### 32.注入Java集合的标签? 249 | 250 | - 允许有相同的值。 251 | - 不允许有相同的值。 252 | - 键和值都只能为String类型。 253 | - < map > 键和值可以是任意类型。 254 | 255 | #### 33.**Spring支持的ORM**? 256 | 257 | 1. Hibernate 258 | 2. iBatis 259 | 3. JPA (Java Persistence API) 260 | 4. TopLink 261 | 5. JDO (Java Data Objects) 262 | 6. OJB 263 | 264 | #### 34.@Repository注解? 265 | 266 | Dao 层实现类注解,扫描注册 bean。 267 | 268 | #### 35.@Value注解? 269 | 270 | 讲常量、配置中的变量值、等注入到变量中。 271 | 272 | #### 36.@Controller注解? 273 | 274 | 定义控制器类。 275 | 276 | #### 37.声明一个切面注解是哪个? 277 | 278 | @Aspect 279 | 280 | #### 38.映射web请求的注解是? 281 | 282 | @RequestMapping 283 | 284 | #### 39.@ResponseBody注解? 285 | 286 | 作用是将返回对象通过适当的转换器转成置顶格式,写进response的body区。通常用来返回json、xml等。 287 | 288 | #### 40.@ResponseBody + @Controller =? 289 | 290 | @RestController 291 | 292 | #### 41.接收路径参数用哪个注解? 293 | 294 | @PathVariable 295 | 296 | #### 42.@Cacheable注解? 297 | 298 | 用来标记缓存查询。 299 | 300 | #### 43.清空缓存是哪个注解? 301 | 302 | @CacheEvict 303 | 304 | #### 44.@Component注解? 305 | 306 | 泛指组件,不好归类时,可以用它。 307 | 308 | #### 45.**BeanFactory 和 ApplicationContext**区别? 309 | 310 | ![image-20200428210402245](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200428210402245.png) 311 | 312 | #### 46.@Qualifier注解? 313 | 314 | 当创建多个相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。 315 | 316 | #### 47.事务的注解是? 317 | 318 | @Transaction 319 | 320 | #### 48.Spring事务实现方式有? 321 | 322 | 声明式:声明式事务也有两种实现方式。 323 | 324 | - xml 配置文件的方式。 325 | - 注解方式(在类上添加 @Transaction 注解)。 326 | 327 | 编码式:提供编码的形式管理和维护事务。 328 | 329 | #### 49.什么是事务传播? 330 | 331 | 事务在嵌套方法调用中如何传递,具体如何传播,取决于事务传播行为。 332 | 333 | #### 50.Spring事务传播行为有哪些? 334 | 335 | ![image-20200428223544334](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200428223544334.png) 336 | 337 | 参考: 338 | 339 | - 《Spring in action 4》 340 | - 《SPRING技术内幕》 341 | - 《Spring源码深度解析》 342 | - 《Spring5企业级开发实战》 343 | - https://spring.io 344 | - 百度百科 -------------------------------------------------------------------------------- /SpringBoot.md: -------------------------------------------------------------------------------- 1 | ## SpringBoot 2 | 3 | #### 1.什么是SpringBoot? 4 | 5 | 通过Spring Boot,可以轻松地创建独立的,基于生产级别的Spring的应用程序,您可以“运行”它们。大多数Spring Boot应用程序需要最少的Spring配置。 6 | 7 | #### 2.SpringBoot的特征? 8 | 9 | - 创建独立的Spring应用程序 10 | - 直接嵌入Tomcat,Jetty或Undertow(无需部署WAR文件) 11 | - 提供固化的“starter”依赖项,以简化构建配置 12 | - 尽可能自动配置Spring和3rd Party库 13 | - 提供可用于生产的功能,例如指标,运行状况检查和外部化配置 14 | - 完全没有代码生成,也不需要XML配置 15 | 16 | #### 3.如何快速构建一个SpringBoot项目? 17 | 18 | - 通过Web界面使用。http://start.spring.io 19 | - 通过Spring Tool Suite使用。 20 | - 通过IntelliJ IDEA使用。 21 | - 使用Spring Boot CLI使用。 22 | 23 | #### 4.SpringBoot启动类注解?它是由哪些注解组成? 24 | 25 | @SpringBootApplication 26 | 27 | - @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。 28 | - @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项。 29 | - @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) 30 | - @ComponentScan:Spring组件扫描 31 | 32 | #### 5.什么是yaml? 33 | 34 | YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl。更具有结构性。 35 | 36 | #### 6.SpringBoot支持配置文件的格式? 37 | 38 | 1.properties 39 | 40 | ```properties 41 | java.xiaokaxiu.name = xiaoka 42 | ``` 43 | 44 | 2.yml 45 | 46 | ```yaml 47 | java: 48 | xiaokaxiu: 49 | name: xiaoka 50 | ``` 51 | 52 | #### 7.SpringBoot启动方式? 53 | 54 | 1. main方法 55 | 56 | 2. 命令行 java -jar 的方式 57 | 58 | 3. mvn/gradle 59 | 60 | #### 8.SpringBoot需要独立的容器运行? 61 | 62 | 不需要,内置了 Tomcat/Jetty。 63 | 64 | #### 9.SpringBoot配置途径? 65 | 66 | 1. 命令行参数 67 | 2. java:comp/env里的JNDI属性 68 | 3. JVM系统属性 69 | 4. 操作系统环境变量 70 | 5. 随机生成的带random.*前缀的属性(在设置其他属性时,可以引用它们,比如${random. long}) 71 | 6. 应用程序以外的application.properties或者appliaction.yml文件 72 | 7. 打包在应用程序内的application.properties或者appliaction.yml文件 73 | 8. 通过@PropertySource标注的属性源 74 | 9. 默认属性 75 | 76 | tips:这个列表按照优先级排序,也就是说,任何在高优先级属性源里设置的属性都会覆盖低优先级的相同属性。 77 | 78 | #### 10.application.properties和application.yml文件可放位置?优先级? 79 | 80 | 1. 外置,在相对于应用程序运行目录的/config子目录里。 81 | 82 | 2. 外置,在应用程序运行的目录里。 83 | 84 | 3. 内置,在config包内。 85 | 86 | 4. 内置,在Classpath根目录。 87 | 88 | 这个列表按照优先级排序,优先级高的会覆盖优先级低的。 89 | 90 | 当然我们可以自己指定文件的位置来加载配置文件。 91 | 92 | ```powershell 93 | java -jar xiaoka.jar ———spring.config.location=/home/application.yml 94 | ``` 95 | 96 | #### 11.SpringBoot自动配置原理? 97 | 98 | @EnableAutoConfiguration (开启自动配置) 99 | 该注解引入了AutoConfigurationImportSelector,该类中的方法会扫描所有存在META-INF/spring.factories的jar包。 100 | 101 | #### 12.SpringBoot热部署方式? 102 | 103 | - spring-boot-devtools 104 | 105 | - Spring Loaded 106 | 107 | - Jrebel 108 | 109 | - 模版热部署 110 | 111 | 112 | #### 13.**bootstrap.yml** 和**application.yml**? 113 | 114 | bootstrap.yml 优先于application.yml 115 | 116 | #### 14.SpringBoot如何修改端口号? 117 | 118 | yml中: 119 | 120 | ```yaml 121 | server : 122 | port : 8888 123 | 124 | ``` 125 | 126 | properties: 127 | 128 | ```properties 129 | server.port = 8888 130 | ``` 131 | 132 | 命令1: 133 | 134 | ```powershell 135 | java -jar xiaoka.jar ——— server.port=8888 136 | ``` 137 | 138 | 命令2: 139 | 140 | ```powershell 141 | java - Dserver.port=8888 -jar xiaoka.jar 142 | ``` 143 | 144 | #### 15.开启SpringBoot特性的几种方式? 145 | 146 | 1. 继承spring-boot-starter-parent项目 147 | 2. 导入spring-boot-dependencies项目依赖 148 | 149 | #### 16.SpringBoot如何兼容Spring项目? 150 | 151 | 在启动类加: 152 | 153 | @ImportResource(locations = {"classpath:spring.xml"}) 154 | 155 | #### 17.SpringBoot配置监控? 156 | 157 | ```xml 158 | 159 | org.springframework.boot 160 | spring-boot-starter-actuator 161 | 162 | ``` 163 | 164 | #### 18.获得Bean装配报告信息访问哪个端点? 165 | 166 | /beans 端点 167 | 168 | #### 19.关闭应用程序访问哪个端点? 169 | 170 | /shutdown 171 | 172 | 该端点默认是关闭的,如果开启,需要如下设置。 173 | 174 | ```yaml 175 | endpoints: 176 | shutdown: 177 | enabled: true 178 | ``` 179 | 180 | 或者properties格式也是可以的。 181 | 182 | #### 20.查看发布应用信息访问哪个端点? 183 | 184 | /info 185 | 186 | #### 21.针对请求访问的几个组合注解? 187 | 188 | @PatchMapping 189 | 190 | @PostMapping 191 | 192 | @GetMapping 193 | 194 | @PutMapping 195 | 196 | @DeleteMapping 197 | 198 | #### 22.SpringBoot 中的starter? 199 | 200 | 可以理解成对依赖的一种合成,starter会把一个或一套功能相关依赖都包含进来,避免了自己去依赖费事,还有各种包的冲突问题。大大的提升了开发效率。 201 | 202 | 并且相关配置会有一个默认值,如果我们自己去配置,就会覆盖默认值。 203 | 204 | #### 23.SpringBoot集成Mybatis? 205 | 206 | mybatis-spring-boot-starter 207 | 208 | #### 24.什么是SpringProfiles? 209 | 210 | 一般来说我们从开发到生产,经过开发(dev)、测试(test)、上线(prod)。不同的时刻我们会用不同的配置。Spring Profiles 允许用户根据配置文件(dev,test,prod 等)来注册 bean。它们可以让我们自己选择什么时候用什么配置。 211 | 212 | #### 25.不同的环境的配置文件? 213 | 214 | 可以是 application-{profile}.properties/yml ,但默认是启动主配置文件application.properties,一般来说我们的不同环境配置如下。 215 | 216 | - `application.properties`:主配置文件 217 | - `application-dev.properties`:开发环境配置文件 218 | - `application-test.properties`:测试环境配置文件 219 | - `application.prop-properties`:生产环境配置文件 220 | 221 | #### 26.如何激活某个环境的配置? 222 | 223 | 比如我们激活开发环境。 224 | 225 | yml: 226 | 227 | ```yaml 228 | spring: 229 | profiles: 230 | active: dev 231 | ``` 232 | 233 | properties: 234 | 235 | ```properties 236 | spring.profiles.active=dev 237 | ``` 238 | 239 | 命令行: 240 | 241 | ```powershell 242 | java -jar xiaoka-v1.0.jar ———spring.profiles.active=dev 243 | ``` 244 | 245 | #### 27.编写测试用例的注解? 246 | 247 | @SpringBootTest 248 | 249 | #### 28.SpringBoot异常处理相关注解? 250 | 251 | @ControllerAdvice 252 | 253 | @ExceptionHandler 254 | 255 | #### 29.SpringBoot 1.x 和 2.x区别?······· 256 | 257 | 1. SpringBoot 2基于Spring5和JDK8,Spring 1x用的是低版本。 258 | 2. 配置变更,参数名等。 259 | 3. SpringBoot2相关的插件最低版本很多都比原来高 260 | 4. 2.x配置中的中文可以直接读取,不用转码 261 | 5. Actuator的变化 262 | 6. CacheManager 的变化 263 | 264 | #### 30.SpringBoot读取配置相关注解有? 265 | 266 | - @PropertySource 267 | - @Value 268 | - @Environment 269 | - @ConfigurationProperties 270 | 271 | 参考: 272 | 273 | - 《SpringBoot实战(第4版)》 274 | 275 | - 《Spring Boot编程思想》 276 | 277 | - 《深入浅出Spring Boot 2.x》 278 | 279 | - https://spring.io/projects/spring-boot 280 | 281 | - 百度百科 282 | 283 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 284 | 285 | ## -------------------------------------------------------------------------------- /SpringCloud.md: -------------------------------------------------------------------------------- 1 | ## SpringCloud 2 | 3 | #### 1.什么是SpringCloud? 4 | 5 | Spring Cloud为开发人员提供了工具,以快速构建分布式系统中的一些常见模式(例如,配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,群集状态)。它们可以在任何分布式环境中正常工作,包括开发人员自己的笔记本电脑,裸机数据中心以及Cloud Foundry等托管平台。 6 | 7 | #### 2.什么是微服务? 8 | 9 | 所谓的微服务是SOA架构下的最终产物,该架构的设计目标是为了肢解业务,使得服务能够独立运行。微服务设计原则: 10 | 11 | 1、各司其职 。 12 | 13 | 2、服务高可用和可扩展性。 14 | 15 | #### 3.SpringCloud有哪些特征? 16 | 17 | Spring Cloud专注于为典型的用例和可扩展性机制(包括其他用例)提供良好的开箱即用体验。 18 | 19 | - 分布式/版本化配置 20 | - 服务注册和发现 21 | - 路由 22 | - 服务到服务的调用 23 | - 负载均衡 24 | - 断路器 25 | - 全局锁 26 | - 领导选举和集群状态 27 | - 分布式消息传递 28 | 29 | #### 4.SpringCloud核心组件? 30 | 31 | Eureka : 注册中心 32 | 33 | Ribbon :客服端负载均衡 34 | 35 | Hystrix : 服务容错处理 36 | 37 | Feign: 声明式REST客户端 38 | 39 | Zuul : 服务网关 40 | 41 | Config : 分布式配置 42 | 43 | #### 5.SpringCloud基于什么协议? 44 | 45 | HTTP 46 | 47 | #### 6.SpringCloud和Dubbo区别? 48 | 49 | ![image-20200429230443620](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200429230443620.png) 50 | 51 | #### 7.Eureka是什么? 52 | 53 | 云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。 54 | 55 | #### 8.服务治理的基础角色? 56 | 57 | 服务注册中心:提供服务注册与发现的能力。 58 | 59 | 服务提供者:提供服务的应用,会把自己提供的服务注册到注册中心。 60 | 61 | 服务消费者:服务的消费者,从注册中心获取服务列表。 62 | 63 | #### 9.什么是服务续约? 64 | 65 | 在注册完服务以后,服务提供者会维护一个心跳来向注册中心证明自己还活着,以此防止被“剔除服务”。 66 | 67 | #### 10.什么是服务下线? 68 | 69 | 当服务实例进行正常关闭时,会发送一个REST请求(我要下线了)给注册中心,收到请求后,将该服务状态设置下线(DOWN),并把这事件传播出去。 70 | 71 | #### 11.什么是失效剔除? 72 | 73 | 当服务非正常下线时,可能服务注册中心没有收到下线请求,注册中心会创建一个定时任务(默认60s)将没有在固定时间(默认90s)内续约的服务剔除掉。 74 | 75 | #### 12.什么是自我保护机制? 76 | 77 | 在运行期间,注册中心会统计心跳失败比例在15分钟之内是否低于85%,如果低于的情况,注册中心会将当前注册实例信息保护起来,不再删除这些实例信息,当网络恢复后,退出自我保护机制。 78 | 79 | 自我保护机制让服务集群更稳定、健壮。 80 | 81 | #### 13.Ribbon是什么? 82 | 83 | 提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用。 84 | 85 | #### 14.Ribbon负载均衡的注解是? 86 | 87 | @LoadBalanced 88 | 89 | #### 15.Ribbon负载均衡策略有哪些? 90 | 91 | RandomRule : 随机。 92 | 93 | RoundRobinRule : 轮询。 94 | 95 | RetryRule : 重试。 96 | 97 | WeightedResponseTimeRule : 权重。 98 | 99 | ClientConfigEnabledRoundRobinRule : 一般不用,通过继承该策略,默认的choose就实现了线性轮询机制。可以基于它来做扩展。 100 | 101 | BestAvailableRule : 通过便利负载均衡器中维护的所有服务实例,会过滤到故障的,并选择并发请求最小的一个。 102 | 103 | PredicateBasedRule : 先过滤清单,再轮询。 104 | 105 | AvailabilityFilteringRule :继承了父类的先过滤清单,再轮询。调整了算法。 106 | 107 | ZoneAvoidanceRule : 该类也是PredicateBasedRule的子类,它可以组合过滤条件。以ZoneAvoidancePredicate为主过滤条件,以AvailabilityPredicate为次过滤条件。 108 | 109 | #### 16.什么是服务熔断? 110 | 111 | 服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。 112 | 113 | #### 17.什么是服务降级? 114 | 115 | 服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。 116 | 117 | #### 18.什么是Hystrix? 118 | 119 | 熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。 120 | 121 | #### 19.断路器Hystrix的有哪些功能? 122 | 123 | - 通过第三方客户端访问依赖服务出现高延迟或者失败时,为系统提供保护和控制 。 124 | - 在复杂的分布式系统中防止级联失败(服务雪崩效应) 。 125 | - 快速失败 (Failfast) 同时能快速恢复。 126 | - 提供失败回滚 (Fallback) 和优雅的服务降级机制。 127 | - 提供近实时的监控、 报警和运维控制手段。 128 | 129 | #### 20.Hystrix将远程调用封装到? 130 | 131 | HystrixCommand 或者 HystrixObservableCommand对象中。 132 | 133 | #### 21.启动熔断降级服务的注解? 134 | 135 | @EnableHystrix 136 | 137 | #### 22.什么是Feign? 138 | 139 | Feign是一种声明式、模板化的HTTP客户端。 140 | 141 | #### 23.Feign优点? 142 | 143 | 1.feign采用的是基于接口的注解。 2.feign整合了ribbon,具有负载均衡的能力。 3.整合了Hystrix,具有熔断的能力。 144 | 145 | #### 24.什么是Config? 146 | 147 | 配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git以及Subversion。 148 | 149 | #### 25.Config组件中的两个角色? 150 | 151 | Config Server : 配置中心服务端。 152 | 153 | Config Client : 配置中心客户端。 154 | 155 | #### 26.什么是Zuul? 156 | 157 | Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。 158 | 159 | #### 27.使用Zuul的优点? 160 | 161 | - 方便监控。可以在微服务网管手机监控数据并将其推送到外部系统进行分析。 162 | - 方便认证。可在网关进行统一认证,然后在讲请求转发到后端服务。 163 | - 隐藏架构实现细节,提供统一的入口给客户端请求,减少了客户端和每个微服务的交互次数。 164 | - 可以统一处理切面任务,避免每个微服务自己开发,提升效率。 165 | - 高可用高伸缩性的服务,避免单点失效。 166 | 167 | #### 28.Zuul的核心是? 168 | 169 | 过滤器。 170 | 171 | #### 29.Zuul有几种过滤器类型?分别是? 172 | 173 | 4种。 174 | 175 | pre : 可以在请求被路由之前调用。 176 | 177 | 适用于身份认证的场景,认证通过后再继续执行下面的流程。 178 | 179 | route : 在路由请求时被调用。 180 | 181 | 适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。 182 | 183 | post :在 route 和 error 过滤器之后被调用。 184 | 185 | 这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。 186 | 187 | error : 处理请求时发生错误时被调用。 188 | 189 | 在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。 190 | 191 | #### 30.什么是Sleuth? 192 | 193 | 日志收集工具包,封装了Dapper和log-based追踪以及Zipkin和HTrace操作,为SpringCloud应用实现了一种分布式追踪解决方案。 194 | 195 | #### 31.Sleuth帮助我们做了哪些工作? 196 | 197 | - 可以方便的了解到每个采样的请求耗时,分析出哪些服务调用比较耗时。 198 | - 对于程序未捕捉的异常,可以在集成Zipkin服务页面上看到。 199 | - 识别调用比较频繁的服务,从而进行优化。 200 | 201 | #### 32.什么是Bus? 202 | 203 | 事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与Spring Cloud Config联合实现热部署。 204 | 205 | #### 33.eureka比zookeeper的优势在? 206 | 207 | A:高可用 C:一致性,P:分区容错性 208 | 209 | Zookeeper保证了CP,Eureka保证了AP。 210 | 211 | Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个微服务瘫痪。 212 | 213 | #### 34.什么是Stream? 214 | 215 | 数据流操作开发包,封装了与Redis,Rabbit、Kafka等发送接收消息。 216 | 217 | #### 35.更多知识? 218 | 219 | SpringCloud这个体系东西还是挺大的,小编会不断的丰富内容以及优化。欢迎大家关注我的公众号获得最新动态《Java小咖秀》。 220 | 221 | 参考: 222 | 223 | - 《Spring Cloud微服务实战》 224 | 225 | - 《Spring Cloud微服务全栈技术与案例解析》 226 | 227 | - 《Spring Cloud微服务架构开发实战》 228 | 229 | - ​ https://spring.io/projects/spring-cloud 230 | 231 | - ​ https://www.springcloud.cc/ 232 | 233 | - ​ 百度百科 234 | 235 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) -------------------------------------------------------------------------------- /Tomcat.md: -------------------------------------------------------------------------------- 1 | ## Tomcat 2 | 3 | #### 1.Tomcat的缺省端口是多少,怎么修改? 4 | 5 | 1)找到Tomcat目录下的conf文件夹 6 | 7 | 2)进入conf文件夹里面找到server.xml文件 8 | 9 | 3)打开server.xml文件 10 | 11 | 4)在server.xml文件里面找到下列信息 12 | 13 | 14 | port="8080"改成你想要的端口 15 | 16 | #### 2.tomcat 有哪几种Connector 运行模式(优化)? 17 | 18 | bio:传统的Java I/O操作,同步且阻塞IO。 19 | maxThreads="150"//Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。默认值200。可以根据机器的时期性能和内存大小调整,一般可以在400-500。最大可以在800左右。 20 | minSpareThreads="25"---Tomcat初始化时创建的线程数。默认值4。如果当前没有空闲线程,且没有超过maxThreads,一次性创建的空闲线程数量。Tomcat初始化时创建的线程数量也由此值设置。 21 | maxSpareThreads="75"--一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。默认值50。一旦创建的线程超过此数值,Tomcat会关闭不再需要的线程。线程数可以大致上用 “同时在线人数*每秒用户操作次数*系统平均操作时间” 来计算。 22 | acceptCount="100"----指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。默认值10。如果当前可用线程数为0,则将请求放入处理队列中。这个值限定了请求队列的大小,超过这个数值的请求将不予处理。 23 | connectionTimeout="20000" --网络连接超时,默认值20000,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。 24 | 25 | nio:JDK1.4开始支持,同步阻塞或同步非阻塞IO。 26 | 指定使用NIO模型来接受HTTP请求 27 | protocol="org.apache.coyote.http11.Http11NioProtocol" 指定使用NIO模型来接受HTTP请求。默认是BlockingIO,配置为protocol="HTTP/1.1" 28 | acceptorThreadCount="2" 使用NIO模型时接收线程的数目 29 | 30 | aio(nio.2):JDK7开始支持,异步非阻塞IO。 31 | 32 | apr:Tomcat将以JNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作,从而大大地 提高Tomcat对静态文件的处理性能。 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 其他配置 54 | 55 | maxHttpHeaderSize="8192" http请求头信息的最大程度,超过此长度的部分不予处理。一般8K。 56 | URIEncoding="UTF-8" 指定Tomcat容器的URL编码格式。 57 | disableUploadTimeout="true" 上传时是否使用超时机制 58 | enableLookups="false"--是否反查域名,默认值为true。为了提高处理能力,应设置为false 59 | compression="on" 打开压缩功能 60 | compressionMinSize="10240" 启用压缩的输出内容大小,默认为2KB 61 | noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩 62 | compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" 哪些资源类型需要压缩 63 | 64 | #### 3.Tomcat有几种部署方式? 65 | 66 | 1)直接把Web项目放在webapps下,Tomcat会自动将其部署 67 | 68 | 2)在server.xml文件上配置节点,设置相关的属性即可 69 | 70 | 3)通过Catalina来进行配置:进入到conf\Catalina\localhost文件下,创建一个xml文件,该文件的名字就是站点的名字。 71 | 72 | 编写XML的方式来进行设置。 73 | 74 | #### 4.tomcat容器是如何创建servlet类实例?用到了什么原理? 75 | 76 | 当容器启动时,会读取在webapps目录下所有的web应用中的web.xml文件,然后对xml文件进行解析, 77 | 78 | 并读取servlet注册信息。然后,将每个应用中注册的servlet类都进行加载,并通过反射的方式实例化。 79 | 80 | (有时候也是在第一次请求时实例化)在servlet注册时加上如果为正数,则在一开始就实例化, 81 | 82 | 如果不写或为负数,则第一次请求实例化。 83 | 84 | #### 5.tomcat 如何优化? 85 | 86 | 1、优化连接配置.这里以tomcat7的参数配置为例,需要修改conf/server.xml文件,修改连接数,关闭客户端dns查询。 87 | 88 | 参数解释: 89 | 90 | URIEncoding=”UTF-8″ :使得tomcat可以解析含有中文名的文件的url,真方便,不像apache里还有搞个mod_encoding,还要手工编译 91 | 92 | maxSpareThreads : 如果空闲状态的线程数多于设置的数目,则将这些线程中止,减少这个池中的线程总数。 93 | 94 | minSpareThreads : 最小备用线程数,tomcat启动时的初始化的线程数。 95 | 96 | enableLookups : 这个功效和Apache中的HostnameLookups一样,设为关闭。 97 | 98 | connectionTimeout : connectionTimeout为网络连接超时时间毫秒数。 99 | 100 | maxThreads : maxThreads Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数,即最大并发数。 101 | 102 | acceptCount : acceptCount是当线程数达到maxThreads后,后续请求会被放入一个等待队列,这个acceptCount是这个队列的大小,如果这个队列也满了,就直接refuse connection 103 | 104 | maxProcessors与minProcessors : 在 Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最 大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。 105 | 106 | 通常Windows是1000个左右,Linux是2000个左右。 107 | 108 | useURIValidationHack: 109 | 110 | 我们来看一下tomcat中的一段源码: 111 | 112 | 【security】 113 | 114 | ``` 115 | if (connector.getUseURIValidationHack()) { 116 | 117 | String uri = validate(request.getRequestURI()); 118 | 119 | if (uri == null) { 120 | 121 | res.setStatus(400); 122 | 123 | res.setMessage(“Invalid URI”); 124 | 125 | throw new IOException(“Invalid URI”); 126 | 127 | } else { 128 | 129 | req.requestURI().setString(uri); 130 | 131 | // Redoing the URI decoding 132 | 133 | req.decodedURI().duplicate(req.requestURI()); 134 | 135 | req.getURLDecoder().convert(req.decodedURI(), true); 136 | ``` 137 | 138 | 可以看到如果把useURIValidationHack设成”false”,可以减少它对一些url的不必要的检查从而减省开销。 139 | 140 | enableLookups=”false” : 为了消除DNS查询对性能的影响我们可以关闭DNS查询,方式是修改server.xml文件中的enableLookups参数值。 141 | 142 | disableUploadTimeout :类似于Apache中的keeyalive一样 143 | 144 | 给Tomcat配置gzip压缩(HTTP压缩)功能 145 | 146 | compression=”on” compressionMinSize=”2048″ 147 | 148 | compressableMimeType=”text/html,text/xml,text/JavaScript,text/css,text/plain” 149 | 150 | HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML,CSS,javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,压缩效率惊人。 151 | 152 | 1)compression=”on” 打开压缩功能 153 | 154 | 2)compressionMinSize=”2048″ 启用压缩的输出内容大小,这里面默认为2KB 155 | 156 | 3)noCompressionUserAgents=”gozilla, traviata” 对于以下的浏览器,不启用压缩 157 | 158 | 4)compressableMimeType=”text/html,text/xml” 压缩类型 159 | 160 | 最后不要忘了把8443端口的地方也加上同样的配置,因为如果我们走https协议的话,我们将会用到8443端口这个段的配置,对吧? 161 | 162 | ``` 163 | 164 | 165 | 188 | ``` 189 | 190 | 191 | 192 | #### 6.内存调优 193 | 194 | 内存方式的设置是在catalina.sh中,调整一下JAVA_OPTS变量即可,因为后面的启动参数会把JAVA_OPTS作为JVM的启动参数来处理。 195 | 具体设置如下: 196 | JAVA_OPTS="$JAVA_OPTS -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4" 197 | 其各项参数如下: 198 | -Xmx3550m:设置JVM最大可用内存为3550M。 199 | -Xms3550m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。 200 | -Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。 201 | -Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。 202 | -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 203 | -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6 204 | -XX:MaxPermSize=16m:设置持久代大小为16m。 205 | -XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。 206 | 207 | 208 | 209 | #### 7.垃圾回收策略调优 210 | 211 | 垃圾回收的设置也是在catalina.sh中,调整JAVA_OPTS变量。 212 | 具体设置如下: 213 | JAVA_OPTS="$JAVA_OPTS -Xmx3550m -Xms3550m -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100" 214 | 具体的垃圾回收策略及相应策略的各项参数如下: 215 | 串行收集器(JDK1.5以前主要的回收方式) 216 | -XX:+UseSerialGC:设置串行收集器 217 | 并行收集器(吞吐量优先) 218 | 示例: 219 | java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 220 | 221 | -XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。 222 | -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。 223 | -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集 224 | -XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。 225 | -XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。 226 | 并发收集器(响应时间优先) 227 | 示例:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC 228 | -XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。 229 | -XX:+UseParNewGC: 设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。 230 | -XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。 231 | 232 | #### 8.添加JMS远程监控 233 | 234 | 对于部署在局域网内其它机器上的Tomcat,可以打开JMX监控端口,局域网其它机器就可以通过这个端口查看一些常用的参数(但一些比较复杂的功能不支持),同样是在JVM启动参数中配置即可,配置如下: 235 | -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false 236 | -Djava.rmi.server.hostname=192.168.71.38 设置JVM的JMS监控监听的IP地址,主要是为了防止错误的监听成127.0.0.1这个内网地址 237 | -Dcom.sun.management.jmxremote.port=1090 设置JVM的JMS监控的端口 238 | -Dcom.sun.management.jmxremote.ssl=false 设置JVM的JMS监控不实用SSL 239 | -Dcom.sun.management.jmxremote.authenticate=false 设置JVM的JMS监控不需要认证 240 | 241 | #### 9.专业点的分析工具有 242 | 243 | IBM ISA,JProfiler、probe 等,具体监控及分析方式去网上搜索即可 244 | 245 | #### 10.关于Tomcat的session数目 246 | 247 | 这个可以直接从Tomcat的web管理界面去查看即可 ; 或者借助于第三方工具Lambda Probe来查看,它相对于Tomcat自带的管理稍微多了点功能,但也不多 ; 248 | 249 | #### 11.监视Tomcat的内存使用情况 250 | 251 | 使用JDK自带的jconsole可以比较明了的看到内存的使用情况,线程的状态,当前加载的类的总量等; JDK自带的jvisualvm可以下载插件(如GC等),可以查看更丰富的信息。如果是分析本地的Tomcat的话,还可以进行内存抽样等,检查每个类的使用情况 252 | 253 | #### 12.打印类的加载情况及对象的回收情况 254 | 255 | 这个可以通过配置JVM的启动参数,打印这些信息(到屏幕(默认也会到catalina.log中)或者文件),具体参数如下: 256 | 257 | ``` 258 | -XX:+PrintGC:输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs] 259 | -XX:+PrintGCDetails:输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs] 260 | -XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用,输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] 261 | -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用。输出形式:Application time: 0.5291524 seconds 262 | -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。可与上面混合使用。输出形式:Total time for which application threads were stopped: 0.0468229 seconds 263 | -XX:PrintHeapAtGC: 打印GC前后的详细堆栈信息 264 | -Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析 265 | -verbose:class 监视加载的类的情况 266 | -verbose:gc 在虚拟机发生内存回收时在输出设备显示信息 267 | -verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用错误信息 268 | ``` 269 | 270 | #### 13.Tomcat一个请求的完整过程 271 | 272 | Ng:(nginx) 273 | 274 | upstream yy_001{ 275 | server 10.99.99.99:8080; 276 | server 10.99.99.100:8080; 277 | 278 | hash $**; 279 | 280 | healthcheck_enabled; 281 | healthcheck_delay 3000; 282 | healthcheck_timeout 1000; 283 | healthcheck_failcount 2; 284 | healthcheck_send 'GET /healthcheck.html HTTP/1.0' 'Host: wo.com' 'Connection: close'; 285 | } 286 | 287 | server { 288 | include base.conf; 289 | server_name wo.de.tian; 290 | ... 291 | location /yy/ { 292 | proxy_pass http://yy_001; 293 | } 294 | 295 | 首先 dns 解析 wo.de.tian机器,一般是ng服务器ip地址 296 | 然后 ng根据server的配置,寻找路径为 yy/的机器列表,ip和端口 297 | 最后 选择其中一台机器进行访问—->下面为详细过程 298 | 299 | 1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得 300 | 2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应 301 | 3) Engine获得请求localhost/yy/index.jsp,匹配它所拥有的所有虚拟主机Host 302 | 4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机) 303 | 5) localhost Host获得请求/yy/index.jsp,匹配它所拥有的所有Context 304 | 6) Host匹配到路径为/yy的Context(如果匹配不到就把该请求交给路径名为”“的Context去处理) 305 | 7) path=”/yy”的Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet 306 | 8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类 307 | 9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法 308 | 10)Context把执行完了之后的HttpServletResponse对象返回给Host 309 | 11)Host把HttpServletResponse对象返回给Engine 310 | 12)Engine把HttpServletResponse对象返回给Connector 311 | 13)Connector把HttpServletResponse对象返回给客户browser 312 | 313 | 314 | #### 14.Tomcat工作模式? 315 | 316 | 笔者回答:Tomcat是一个JSP/Servlet容器。其作为Servlet容器,有三种工作模式:独立的Servlet容器、进程内的Servlet容器和进程外的Servlet容器。 317 | 318 | 进入Tomcat的请求可以根据Tomcat的工作模式分为如下两类: 319 | 320 | Tomcat作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等; 321 | 322 | Tomcat作为独立服务器:请求来自于web浏览器; 323 | 324 | #### 15.tomcat结构目录有哪些? 325 | 326 | ①bin:启动和关闭tomcat的bat文件。 327 | 328 | ②conf:配置文件。 329 | 330 | ③server.xml该文件用于配置server相关的信息,比如tomcat启动的端口号,配置主机(Host)。 331 | 332 | ④web.xml文件配置与web应用(web应用相当于一个web站点) 333 | 334 | ⑤tomcat-user.xml配置用户名密码和相关权限。 335 | 336 | ⑥lib:该目录放置运行tomcat运行需要的jar包。 337 | 338 | ⑦logs:存放日志,当我们需要查看日志的时候,可以查询信息。 339 | 340 | ⑧webapps:放置我们的web应用。 341 | 342 | ⑨work工作目录:该目录用于存放jsp被访问后生成对应的server文件和.class文件。 343 | 344 | #### 16.如何配置Tomcat虚拟目录? 345 | 346 | 1、在server.xml中的节点下添加如下代码。path表示的是访问时输入的web项目名,docBase表示的是站点目录的绝对路径。 347 | 348 | 2、进入到confCatalinalocalhost文件下,创建一个xml文件,该文件的名字就是站点的名字。 349 | 350 | #### 17.Tomcat体系结构是怎样的? 351 | 352 | 浏览器 -> tomcat server-> service ->connector -> engine(引擎) -> host(主机) -> web应用。 353 | 354 | #### 18.Web请求在Tomcat请求中的请求流程是怎么样的? 355 | 356 | ①浏览器输入URL地址; 357 | 358 | ②查询本机hosts文件寻找IP; 359 | 360 | ③查询DNS服务器寻找IP; 361 | 362 | ④向该IP发送Http请求; 363 | 364 | ⑤Tomcat容器解析主机名; 365 | 366 | ⑥Tomcat容器解析Web应用; 367 | 368 | ⑦Tomcat容器解析资源名称; 369 | 370 | ⑧Tomcat容器获取资源; 371 | 372 | ⑨Tomcat响应浏览器。 373 | 374 | #### 19.如何在tomcat集群中实现Session共享 375 | 376 | Apache集群实现Tomcat的Session共享配置其实很简单,在Tomcat自带的文档中有详细的说明( /docs/cluster-howto.html ),只不过是英语的,所以联合下面根据说下怎么配置吧: 377 | 378 | 1、既然是集群肯定要多准备几个Tomcat来模拟,比如分别为Tomcat01、Tomcat02、Tomcat03。 379 | 380 | 如果各Tomcat程序放在不同的机器上,那么就不会有端口的冲突。如果是放在同一台机器上的话,那就简单改几个端口,防止端口占用造成的冲突。打开conf文件夹中的server.xml文件,需要修改的端口有: 381 | 382 | 1、 383 | 384 | 2、 385 | 386 | 3、 387 | 388 | 以上port需要修改,至于修改成什么样子,看你自己了,只要不出现端口冲突就可以了,要保证各个Tomcat实例间没有端口冲突。 389 | 390 | #### 20.tomcat有哪些Connector? 391 | 392 | Tomcat的Web服务器连接器支持两种协议:AJP和HTTP,它们均定义了以二进制格式在Web服务器和Tomcat之间进行数据传输,并提供相应的控制命令。 393 | 394 | AJP(Apache JServ Protocol)协议:目前正在使用的AJP协议的版本是通过JK和JK2连接器提供支持的AJP13,它基于二进制的格式在Web服务器和Tomcat之间传输数据,而此前的版本AJP10和AJP11则使用文本格式传输数据。 395 | 396 | HTTP协议:诚如其名称所表示,其是使用HTTP或HTTPS协议在Web服务器和Tomcat之间建立通信,此时,Tomcat就是一个完全功能的HTTP服务器,它需要监听在某端口上以接收来自于商前服务器的请求。 397 | 398 | #### 21.tomcat的Valve的作用是什么? 399 | 400 | Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。 401 | 402 | #### 22.Webserver和 Application Server的区别是什么? 403 | 404 | 最大区别,WebServer 一般仅仅指Web(如servlet,jsp)的应用服务器,ApplicationServer不仅可以是Web,还可以是Ejb等其它的应用服务器。 405 | 406 | web server可以是application server的一部分,也可以是单独存在。 407 | 408 | #### 23.Tomcat的缺省端口是多少,怎么修改? 409 | 410 | 1)找到Tomcat目录下的conf文件夹; 411 | 412 | 2)进入conf文件夹里面找到server.xml文件; 413 | 414 | 3)打开server.xml文件; 415 | 416 | 4)在server.xml文件里面找到下列信息; 417 | 418 | port=“8080”改成你想要的端口 419 | 420 | #### 24.Tomcat 有几种部署方式? 421 | 422 | 1)直接把Web项目放在webapps下,Tomcat会自动将其部署 423 | 424 | 2)在server.xml文件上配置节点,设置相关的属性即可 425 | 426 | 3)通过Catalina来进行配置:进入到conf\Catalina\localhost文件下,创建一个xml文件,该文件的名字就是站点的名字。编写XML的方式来进行设置。 427 | 428 | #### 25.tomcat容器是如何创建servlet类实例?用到了什么原理? 429 | 430 | 当容器启动时,会读取在webapps 目录下所有的web应用中的web.xml 文件,然后对xml文件进行解析,并读取servlet注册信息。然后,将每个应用中注册的servlet类都进行加载,并通过反射的方式实例化。(有时候也是在第一次请求时实例化)在servlet注册时加上如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。 431 | 432 | #### 参考 433 | 434 | https://blog.csdn.net/qq_25934401/article/details/81536958 435 | 436 | http://blog.itpub.net/69902581/viewspace-2673221/ 437 | 438 | 439 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 440 | 441 | -------------------------------------------------------------------------------- /Zookeeper.md: -------------------------------------------------------------------------------- 1 | ## Zookeeper 2 | 3 | #### 1.ZooKeeper 是什么? 4 | 5 | ZooKeeper 是一个开源的分布式协调服务。它是一个为分布式应用提供一致性服务的软件,分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。 6 | 7 | ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。 8 | 9 | Zookeeper 保证了如下分布式一致性特性: 10 | 11 | (1)顺序一致性 12 | 13 | (2)原子性 14 | 15 | (3)单一视图 16 | 17 | (4)可靠性 18 | 19 | (5)实时性(最终一致性) 20 | 21 | 客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的 zookeeper 机器来处理。对于写请求,这些请求会同时发给其他 zookeeper 机器并且达成一致后,请求才会返回成功。因此,随着 zookeeper 的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。 22 | 23 | 有序性是 zookeeper 中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为 zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个zookeeper 最新的 zxid。 24 | 25 | 26 | #### 2.ZooKeeper 提供了什么? 27 | 28 | - 文件系统 29 | - 通知机制 30 | 31 | #### 3.Zookeeper 文件系统 32 | 33 | Zookeeper 提供一个多层级的节点命名空间(节点称为 znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。 34 | 35 | Zookeeper 为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得 Zookeeper 不能用于存放大量的数据,每个节点的存放数据上限为1M。 36 | 37 | 38 | #### 4.Zookeeper 怎么保证主从节点的状态同步? 39 | 40 | Zookeeper 的核心是原子广播机制,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式。 41 | 42 | ##### 恢复模式 43 | 44 | 当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。 45 | 46 | ##### 广播模式 47 | 48 | 一旦 leader 已经和多数的 follower 进行了状态同步后,它就可以开始广播消息了,即进入广播状态。这时候当一个 server 加入 ZooKeeper 服务中,它会在恢复模式下启动,发现 leader,并和 leader 进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper 服务一直维持在 Broadcast 状态,直到 leader 崩溃了或者 leader 失去了大部分的 followers 支持。 49 | 50 | 51 | #### 5.四种类型的数据节点 Znode 52 | 53 | (1)PERSISTENT-持久节点 54 | 除非手动删除,否则节点一直存在于 Zookeeper 上 55 | 56 | (2)EPHEMERAL-临时节点 57 | 临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与zookeeper 连接断开不一定会话失效),那么这个客户端创建的所有临时节点都会被移除。 58 | 59 | (3)PERSISTENT_SEQUENTIAL-持久顺序节点 60 | 基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。 61 | 62 | (4)EPHEMERAL_SEQUENTIAL-临时顺序节点 63 | 基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。 64 | 65 | #### 6.Zookeeper Watcher 机制 – 数据变更通知 66 | 67 | Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。 68 | 69 | 工作机制: 70 | 71 | (1)客户端注册 watcher 72 | 73 | (2)服务端处理 watcher 74 | 75 | (3)客户端回调 watcher 76 | 77 | #### 7.Watcher 特性总结 78 | 79 | ##### 一次性 80 | 81 | 无论是服务端还是客户端,一旦一个 Watcher 被 触 发 ,Zookeeper 都会将其从相应的存储中移除。这样的设计有效的减轻了服务端的压力,不然对于更新非常频繁的节点,服务端会不断的向客户端发送事件通知,无论对于网络还是服务端的压力都非常大。 82 | 83 | ##### 客户端串行执行 84 | 85 | 客户端 Watcher 回调的过程是一个串行同步的过程。 86 | 87 | ##### 轻量 88 | 89 | 3.1、Watcher 通知非常简单,只会告诉客户端发生了事件,而不会说明事件的具体内容。 90 | 3.2、客户端向服务端注册 Watcher 的时候,并不会把客户端真实的 Watcher 对象实体传递到服务端,仅仅是在客户端请求中使用 boolean 类型属性进行了标记。 91 | 92 | watcher event 异步发送 watcher 的通知事件从 server 发送到 client 是异步的,这就存在一个问题,不同的客户端和服务器之间通过 socket 进行通信,由于网络延迟或其他因素导致客户端在不通的时刻监听到事件,由于 Zookeeper 本身提供了 ordering guarantee,即客户端监听事件后,才会感知它所监视 znode发生了变化。所以我们使用 Zookeeper 不能期望能够监控到节点每次的变化。Zookeeper 只能保证最终的一致性,而无法保证强一致性。 93 | 94 | 注册 watcher getData、exists、getChildren 95 | 96 | 触发 watcher create、delete、setData 97 | 98 | 当一个客户端连接到一个新的服务器上时,watch 将会被以任意会话事件触发。当与一个服务器失去连接的时候,是无法接收到 watch 的。而当 client 重新连接时,如果需要的话,所有先前注册过的 watch,都会被重新注册。通常这是完全透明的。只有在一个特殊情况下,watch 可能会丢失:对于一个未创建的 znode的 exist watch,如果在客户端断开连接期间被创建了,并且随后在客户端连接上之前又删除了,这种情况下,这个 watch 事件可能会被丢失。 99 | 100 | #### 8.客户端注册 Watcher 实现 101 | 102 | (1)调用 getData()/getChildren()/exist()三个 API,传入 Watcher 对象 103 | 104 | (2)标记请求 request,封装 Watcher 到 WatchRegistration 105 | 106 | (3)封装成 Packet 对象,发服务端发送 request 107 | 108 | (4)收到服务端响应后,将 Watcher 注册到 ZKWatcherManager 中进行管理 109 | 110 | (5)请求返回,完成注册。 111 | 112 | #### 9.服务端处理 Watcher 实现 113 | 114 | ##### 1.服务端接收 Watcher 并存储 115 | 116 | 接收到客户端请求,处理请求判断是否需要注册 Watcher,需要的话将数据节点的节点路径和 ServerCnxn(ServerCnxn 代表一个客户端和服务端的连接,实现了 Watcher 的 process 接口,此时可以看成一个 Watcher 对象)存储在WatcherManager 的 WatchTable 和 watch2Paths 中去。 117 | 118 | ##### 2.Watcher 触发 119 | 120 | 以服务端接收到 setData() 事务请求触发 NodeDataChanged 事件为例: 121 | 122 | 2.1 封装 WatchedEvent 123 | 将通知状态(SyncConnected)、事件类型(NodeDataChanged)以及节点路径封装成一个 WatchedEvent 对象 124 | 125 | 2.2 查询 Watcher 126 | 从 WatchTable 中根据节点路径查找 Watcher 127 | 128 | 2.3 没找到;说明没有客户端在该数据节点上注册过 Watcher 129 | 130 | 2.4 找到;提取并从 WatchTable 和 Watch2Paths 中删除对应 Watcher(从这里可以看出 Watcher 在服务端是一次性的,触发一次就失效了) 131 | 132 | ##### 3.调用 process 方法来触发 Watcher 133 | 134 | 这里 process 主要就是通过 ServerCnxn 对应的 TCP 连接发送 Watcher 事件通知。 135 | 136 | #### 10.客户端回调 Watcher 137 | 138 | - 客户端 SendThread 线程接收事件通知,交由 EventThread 线程回调 Watcher。 139 | - 客户端的 Watcher 机制同样是一次性的,一旦被触发后,该 Watcher 就失效了。 140 | 141 | #### 11.ACL 权限控制机制 142 | 143 | UGO(User/Group/Others) 144 | 145 | 目前在 Linux/Unix 文件系统中使用,也是使用最广泛的权限控制方式。是一种粗粒度的文件系统权限控制模式。 146 | 147 | ACL(Access Control List)访问控制列表 148 | 149 | 包括三个方面: 150 | 151 | 权限模式(Scheme) 152 | (1)IP:从 IP 地址粒度进行权限控制 153 | (2)Digest:最常用,用类似于 username:password 的权限标识来进行权限配置,便于区分不同应用来进行权限控制 154 | (3)World:最开放的权限控制方式,是一种特殊的 digest 模式,只有一个权限标识“world:anyone” 155 | (4)Super:超级用户 156 | 157 | 授权对象 158 | 授权对象指的是权限赋予的用户或一个指定实体,例如 IP 地址或是机器灯。 159 | 160 | 权限 Permission 161 | (1)CREATE:数据节点创建权限,允许授权对象在该 Znode 下创建子节点 162 | (2)DELETE:子节点删除权限,允许授权对象删除该数据节点的子节点 163 | (3)READ:数据节点的读取权限,允许授权对象访问该数据节点并读取其数据内容或子节点列表等 164 | (4)WRITE:数据节点更新权限,允许授权对象对该数据节点进行更新操作 165 | (5)ADMIN:数据节点管理权限,允许授权对象对该数据节点进行 ACL 相关设置操作 166 | 167 | #### 12.Chroot 特性 168 | 169 | 3.2.0 版本后,添加了 Chroot 特性,该特性允许每个客户端为自己设置一个命名空间。如果一个客户端设置了 Chroot,那么该客户端对服务器的任何操作,都将会被限制在其自己的命名空间下。 170 | 171 | 通过设置 Chroot,能够将一个客户端应用于 Zookeeper 服务端的一颗子树相对应,在那些多个应用公用一个 Zookeeper 进群的场景下,对实现不同应用间的相互隔离非常有帮助。 172 | 173 | #### 13.会话管理 174 | 175 | 分桶策略:将类似的会话放在同一区块中进行管理,以便于 Zookeeper 对会话进行不同区块的隔离处理以及同一区块的统一处理。 176 | 177 | 分配原则:每个会话的“下次超时时间点”(ExpirationTime) 178 | 179 | 计算公式: 180 | 181 | ExpirationTime_ = currentTime + sessionTimeout 182 | 183 | ExpirationTime = (ExpirationTime_ / ExpirationInrerval + 1) * 184 | 185 | ExpirationInterval , ExpirationInterval 是指 Zookeeper 会话超时检查时间间隔,默认 tickTime 186 | 187 | #### 14.服务器角色 188 | 189 | Leader 190 | 191 | (1)事务请求的唯一调度和处理者,保证集群事务处理的顺序性 192 | 193 | (2)集群内部各服务的调度者 194 | 195 | Follower 196 | 197 | (1)处理客户端的非事务请求,转发事务请求给 Leader 服务器 198 | 199 | (2)参与事务请求 Proposal 的投票 200 | 201 | (3)参与 Leader 选举投票 202 | 203 | Observer 204 | 205 | (1)3.0 版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力 206 | 207 | (2)处理客户端的非事务请求,转发事务请求给 Leader 服务器 208 | 209 | (3)不参与任何形式的投票 210 | 211 | 212 | #### 15.Zookeeper 下 Server 工作状态 213 | 214 | 服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。 215 | 216 | (1)LOOKING:寻 找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。 217 | 218 | (2)FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。 219 | 220 | (3)LEADING:领导者状态。表明当前服务器角色是 Leader。 221 | 222 | (4)OBSERVING:观察者状态。表明当前服务器角色是 Observer。 223 | 224 | #### 16.Leader 选举 225 | 226 | Leader 选举是保证分布式数据一致性的关键所在。当 Zookeeper 集群中的一台服务器出现以下两种情况之一时,需要进入 Leader 选举。 227 | 228 | 229 | 230 |   (1) 服务器初始化启动。 231 | 232 |   (2) 服务器运行期间无法和 Leader 保持连接。 233 | 234 |   下面就两种情况进行分析讲解。 235 | 236 |   1. 服务器启动时期的 Leader 选举 237 | 238 |   若进行 Leader 选举,则至少需要两台机器,这里选取 3 台机器组成的服务器集群为例。在集群初始化阶段,当有一台服务器 Server1 启动时,其单独无法进行和完成 Leader 选举,当第二台服务器 Server2 启动时,此时两台机器可以相互通信,每台机器都试图找到 Leader,于是进入 Leader 选举过程。选举过程如下 239 | 240 |   (1) 每个 Server 发出一个投票。由于是初始情况,Server1 和 Server2 都会将自己作为 Leader 服务器来进行投票,每次投票会包含所推举的服务器的 myid 和 ZXID,使用 (myid, ZXID) 来表示,此时 Server1 的投票为(1, 0),Server2 的投票为(2, 0),然后各自将这个投票发给集群中其他机器。 241 | 242 |   (2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自 LOOKING 状态的服务器。 243 | 244 |   (3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行 PK,PK 规则如下 245 | 246 |     · 优先检查 ZXID。ZXID 比较大的服务器优先作为 Leader。 247 | 248 |     · 如果 ZXID 相同,那么就比较 myid。myid 较大的服务器作为 Leader 服务器。 249 | 250 |   对于 Server1 而言,它的投票是 (1, 0),接收 Server2 的投票为 (2, 0),首先会比较两者的 ZXID,均为 0,再比较 myid,此时 Server2 的 myid 最大,于是更新自己的投票为 (2, 0),然后重新投票,对于 Server2 而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。 251 | 252 |   (4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于 Server1、Server2 而言,都统计出集群中已经有两台机器接受了 (2, 0) 的投票信息,此时便认为已经选出了 Leader。 253 | 254 |   (5) 改变服务器状态。一旦确定了 Leader,每个服务器就会更新自己的状态,如果是 Follower,那么就变更为 FOLLOWING,如果是 Leader,就变更为 LEADING。 255 | 256 |   2. 服务器运行时期的 Leader 选举 257 | 258 |   在 Zookeeper 运行期间,Leader 与非 Leader 服务器各司其职,即便当有非 Leader 服务器宕机或新加入,此时也不会影响 Leader,但是一旦 Leader 服务器挂了,那么整个集群将暂停对外服务,进入新一轮 Leader 选举,其过程和启动时期的 Leader 选举过程基本一致。假设正在运行的有 Server1、Server2、Server3 三台服务器,当前 Leader 是 Server2,若某一时刻 Leader 挂了,此时便开始 Leader 选举。选举过程如下 259 | 260 |   (1) 变更状态。Leader 挂后,余下的非 Observer 服务器都会讲自己的服务器状态变更为 LOOKING,然后开始进入 Leader 选举过程。 261 | 262 |   (2) 每个 Server 会发出一个投票。在运行期间,每个服务器上的 ZXID 可能不同,此时假定 Server1 的 ZXID 为 123,Server3 的 ZXID 为 122;在第一轮投票中,Server1 和 Server3 都会投自己,产生投票 (1, 123),(3, 122),然后各自将投票发送给集群中所有机器。 263 | 264 |   (3) 接收来自各个服务器的投票。与启动时过程相同。 265 | 266 |   (4) 处理投票。与启动时过程相同,此时,Server1 将会成为 Leader。 267 | 268 |   (5) 统计投票。与启动时过程相同。 269 | 270 |   (6) 改变服务器的状态。与启动时过程相同。 271 | 272 |   2.2 Leader 选举算法分析 273 | 274 |   在 3.4.0 后的 Zookeeper 的版本只保留了 TCP 版本的 FastLeaderElection 选举算法。当一台机器进入 Leader 选举时,当前集群可能会处于以下两种状态 275 | 276 |     · 集群中已经存在 Leader。 277 | 278 |     · 集群中不存在 Leader。 279 | 280 |   对于集群中已经存在 Leader 而言,此种情况一般都是某台机器启动得较晚,在其启动之前,集群已经在正常工作,对这种情况,该机器试图去选举 Leader 时,会被告知当前服务器的 Leader 信息,对于该机器而言,仅仅需要和 Leader 机器建立起连接,并进行状态同步即可。而在集群中不存在 Leader 情况下则会相对复杂,其步骤如下 281 | 282 |   (1) 第一次投票。无论哪种导致进行 Leader 选举,集群的所有机器都处于试图选举出一个 Leader 的状态,即 LOOKING 状态,LOOKING 机器会向所有其他机器发送消息,该消息称为投票。投票中包含了 SID(服务器的唯一标识)和 ZXID(事务 ID),(SID, ZXID) 形式来标识一次投票信息。假定 Zookeeper 由 5 台机器组成,SID 分别为 1、2、3、4、5,ZXID 分别为 9、9、9、8、8,并且此时 SID 为 2 的机器是 Leader 机器,某一时刻,1、2 所在机器出现故障,因此集群开始进行 Leader 选举。在第一次投票时,每台机器都会将自己作为投票对象,于是 SID 为 3、4、5 的机器投票情况分别为 (3, 9),(4, 8), (5, 8)。 283 | 284 |   (2) 变更投票。每台机器发出投票后,也会收到其他机器的投票,每台机器会根据一定规则来处理收到的其他机器的投票,并以此来决定是否需要变更自己的投票,这个规则也是整个 Leader 选举算法的核心所在,其中术语描述如下 285 | 286 |     · vote_sid:接收到的投票中所推举 Leader 服务器的 SID。 287 | 288 |     · vote_zxid:接收到的投票中所推举 Leader 服务器的 ZXID。 289 | 290 |     · self_sid:当前服务器自己的 SID。 291 | 292 |     · self_zxid:当前服务器自己的 ZXID。 293 | 294 |   每次对收到的投票的处理,都是对 (vote_sid, vote_zxid) 和(self_sid, self_zxid)对比的过程。 295 | 296 |     规则一:如果 vote_zxid 大于 self_zxid,就认可当前收到的投票,并再次将该投票发送出去。 297 | 298 |     规则二:如果 vote_zxid 小于 self_zxid,那么坚持自己的投票,不做任何变更。 299 | 300 |     规则三:如果 vote_zxid 等于 self_zxid,那么就对比两者的 SID,如果 vote_sid 大于 self_sid,那么就认可当前收到的投票,并再次将该投票发送出去。 301 | 302 |     规则四:如果 vote_zxid 等于 self_zxid,并且 vote_sid 小于 self_sid,那么坚持自己的投票,不做任何变更。 303 | 304 |   结合上面规则,给出下面的集群变更过程。 305 | 306 |   (3) 确定 Leader。经过第二轮投票后,集群中的每台机器都会再次接收到其他机器的投票,然后开始统计投票,如果一台机器收到了超过半数的相同投票,那么这个投票对应的 SID 机器即为 Leader。此时 Server3 将成为 Leader。 307 | 308 |   由上面规则可知,通常那台服务器上的数据越新(ZXID 会越大),其成为 Leader 的可能性越大,也就越能够保证数据的恢复。如果 ZXID 相同,则 SID 越大机会越大。 309 | 310 |   2.3 Leader 选举实现细节 311 | 312 |   1. 服务器状态 313 | 314 |   服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。 315 | 316 |   LOOKING:寻找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。 317 | 318 |   FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。 319 | 320 |   LEADING:领导者状态。表明当前服务器角色是 Leader。 321 | 322 |   OBSERVING:观察者状态。表明当前服务器角色是 Observer。 323 | 324 |   2. 投票数据结构 325 | 326 |   每个投票中包含了两个最基本的信息,所推举服务器的 SID 和 ZXID,投票(Vote)在 Zookeeper 中包含字段如下 327 | 328 |   id:被推举的 Leader 的 SID。 329 | 330 |   zxid:被推举的 Leader 事务 ID。 331 | 332 |   electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加 1 操作。 333 | 334 |   peerEpoch:被推举的 Leader 的 epoch。 335 | 336 |   state:当前服务器的状态。 337 | 338 |   3. QuorumCnxManager:网络 I/O 339 | 340 |   每台服务器在启动的过程中,会启动一个 QuorumPeerManager,负责各台服务器之间的底层 Leader 选举过程中的网络通信。 341 | 342 |   (1) 消息队列。QuorumCnxManager 内部维护了一系列的队列,用来保存接收到的、待发送的消息以及消息的发送器,除接收队列以外,其他队列都按照 SID 分组形成队列集合,如一个集群中除了自身还有 3 台机器,那么就会为这 3 台机器分别创建一个发送队列,互不干扰。 343 | 344 |     · recvQueue:消息接收队列,用于存放那些从其他服务器接收到的消息。 345 | 346 |     · queueSendMap:消息发送队列,用于保存那些待发送的消息,按照 SID 进行分组。 347 | 348 |     · senderWorkerMap:发送器集合,每个 SenderWorker 消息发送器,都对应一台远程 Zookeeper 服务器,负责消息的发送,也按照 SID 进行分组。 349 | 350 |     · lastMessageSent:最近发送过的消息,为每个 SID 保留最近发送过的一个消息。 351 | 352 |   (2) 建立连接。为了能够相互投票,Zookeeper 集群中的所有机器都需要两两建立起网络连接。QuorumCnxManager 在启动时会创建一个 ServerSocket 来监听 Leader 选举的通信端口 (默认为 3888)。开启监听后,Zookeeper 能够不断地接收到来自其他服务器的创建连接请求,在接收到其他服务器的 TCP 连接请求时,会进行处理。为了避免两台机器之间重复地创建 TCP 连接,Zookeeper 只允许 SID 大的服务器主动和其他机器建立连接,否则断开连接。在接收到创建连接请求后,服务器通过对比自己和远程服务器的 SID 值来判断是否接收连接请求,如果当前服务器发现自己的 SID 更大,那么会断开当前连接,然后自己主动和远程服务器建立连接。一旦连接建立,就会根据远程服务器的 SID 来创建相应的消息发送器 SendWorker 和消息接收器 RecvWorker,并启动。 353 | 354 |   (3) 消息接收与发送。消息接收:由消息接收器 RecvWorker 负责,由于 Zookeeper 为每个远程服务器都分配一个单独的 RecvWorker,因此,每个 RecvWorker 只需要不断地从这个 TCP 连接中读取消息,并将其保存到 recvQueue 队列中。消息发送:由于 Zookeeper 为每个远程服务器都分配一个单独的 SendWorker,因此,每个 SendWorker 只需要不断地从对应的消息发送队列中获取出一个消息发送即可,同时将这个消息放入 lastMessageSent 中。在 SendWorker 中,一旦 Zookeeper 发现针对当前服务器的消息发送队列为空,那么此时需要从 lastMessageSent 中取出一个最近发送过的消息来进行再次发送,这是为了解决接收方在消息接收前或者接收到消息后服务器挂了,导致消息尚未被正确处理。同时,Zookeeper 能够保证接收方在处理消息时,会对重复消息进行正确的处理。 355 | 356 |   4. FastLeaderElection:选举算法核心 357 | 358 |   · 外部投票:特指其他服务器发来的投票。 359 | 360 |   · 内部投票:服务器自身当前的投票。 361 | 362 |   · 选举轮次:Zookeeper 服务器 Leader 选举的轮次,即 logicalclock。 363 | 364 |   · PK:对内部投票和外部投票进行对比来确定是否需要变更内部投票。 365 | 366 |   (1) 选票管理 367 | 368 |   · sendqueue:选票发送队列,用于保存待发送的选票。 369 | 370 |   · recvqueue:选票接收队列,用于保存接收到的外部投票。 371 | 372 |   · WorkerReceiver:选票接收器。其会不断地从 QuorumCnxManager 中获取其他服务器发来的选举消息,并将其转换成一个选票,然后保存到 recvqueue 中,在选票接收过程中,如果发现该外部选票的选举轮次小于当前服务器的,那么忽略该外部投票,同时立即发送自己的内部投票。 373 | 374 |   · WorkerSender:选票发送器,不断地从 sendqueue 中获取待发送的选票,并将其传递到底层 QuorumCnxManager 中。 375 | 376 |   (2) 算法核心 377 | 378 | ![img](https://images2018.cnblogs.com/blog/632316/201808/632316-20180803082744195-266416769.png) 379 | 380 |   上图展示了 FastLeaderElection 模块是如何与底层网络 I/O 进行交互的。Leader 选举的基本流程如下 381 | 382 |   1. 自增选举轮次。Zookeeper 规定所有有效的投票都必须在同一轮次中,在开始新一轮投票时,会首先对 logicalclock 进行自增操作。 383 | 384 |   2. 初始化选票。在开始进行新一轮投票之前,每个服务器都会初始化自身的选票,并且在初始化阶段,每台服务器都会将自己推举为 Leader。 385 | 386 |   3. 发送初始化选票。完成选票的初始化后,服务器就会发起第一次投票。Zookeeper 会将刚刚初始化好的选票放入 sendqueue 中,由发送器 WorkerSender 负责发送出去。 387 | 388 |   4. 接收外部投票。每台服务器会不断地从 recvqueue 队列中获取外部选票。如果服务器发现无法获取到任何外部投票,那么就会立即确认自己是否和集群中其他服务器保持着有效的连接,如果没有连接,则马上建立连接,如果已经建立了连接,则再次发送自己当前的内部投票。 389 | 390 |   5. 判断选举轮次。在发送完初始化选票之后,接着开始处理外部投票。在处理外部投票时,会根据选举轮次来进行不同的处理。 391 | 392 |     · 外部投票的选举轮次大于内部投票。若服务器自身的选举轮次落后于该外部投票对应服务器的选举轮次,那么就会立即更新自己的选举轮次 (logicalclock),并且清空所有已经收到的投票,然后使用初始化的投票来进行 PK 以确定是否变更内部投票。最终再将内部投票发送出去。 393 | 394 |     · 外部投票的选举轮次小于内部投票。若服务器接收的外选票的选举轮次落后于自身的选举轮次,那么 Zookeeper 就会直接忽略该外部投票,不做任何处理,并返回步骤 4。 395 | 396 |     · 外部投票的选举轮次等于内部投票。此时可以开始进行选票 PK。 397 | 398 |   6. 选票 PK。在进行选票 PK 时,符合任意一个条件就需要变更投票。 399 | 400 |     · 若外部投票中推举的 Leader 服务器的选举轮次大于内部投票,那么需要变更投票。 401 | 402 |     · 若选举轮次一致,那么就对比两者的 ZXID,若外部投票的 ZXID 大,那么需要变更投票。 403 | 404 |     · 若两者的 ZXID 一致,那么就对比两者的 SID,若外部投票的 SID 大,那么就需要变更投票。 405 | 406 |   7. 变更投票。经过 PK 后,若确定了外部投票优于内部投票,那么就变更投票,即使用外部投票的选票信息来覆盖内部投票,变更完成后,再次将这个变更后的内部投票发送出去。 407 | 408 |   8. 选票归档。无论是否变更了投票,都会将刚刚收到的那份外部投票放入选票集合 recvset 中进行归档。recvset 用于记录当前服务器在本轮次的 Leader 选举中收到的所有外部投票(按照服务队的 SID 区别,如 {(1, vote1), (2, vote2)...})。 409 | 410 |   9. 统计投票。完成选票归档后,就可以开始统计投票,统计投票是为了统计集群中是否已经有过半的服务器认可了当前的内部投票,如果确定已经有过半服务器认可了该投票,则终止投票。否则返回步骤 4。 411 | 412 |   10. 更新服务器状态。若已经确定可以终止投票,那么就开始更新服务器状态,服务器首选判断当前被过半服务器认可的投票所对应的 Leader 服务器是否是自己,若是自己,则将自己的服务器状态更新为 LEADING,若不是,则根据具体情况来确定自己是 FOLLOWING 或是 OBSERVING。 413 | 414 |   以上 10 个步骤就是 FastLeaderElection 的核心,其中步骤 4-9 会经过几轮循环,直到有 Leader 选举产生。 415 | 416 | #### 17.zookeeper 负载均衡和 nginx 负载均衡区别 417 | 418 | - zk 的负载均衡是可以调控,nginx 只是能调权重,其他需要可控的都需要自己写插件;但是 nginx 的吞吐量比 zk 大很多,应该说按业务选择用哪种方式。 419 | 420 | #### 18.集群支持动态添加机器吗? 421 | 422 | 其实就是水平扩容了,Zookeeper 在这方面不太好。两种方式: 423 | 424 | 全部重启:关闭所有 Zookeeper 服务,修改配置之后启动。不影响之前客户端的会话。 425 | 426 | 逐个重启:在过半存活即可用的原则下,一台机器重启不影响整个集群对外提供服务。这是比较常用的方式。 427 | 428 | 3.5 版本开始支持动态扩容。 429 | 430 | #### 19.集群最少要几台机器,集群规则是怎样的?集群中有 3 台服务器,其中一个节点宕机,这个时候 Zookeeper 还可以使用吗? 431 | 432 | 集群规则为 2N+1 台,N>0,即 3 台。可以继续使用,单数服务器只要没超过一半的服务器宕机就可以继续使用 433 | 434 | #### 20.Zookeeper 对节点的 watch 监听通知是永久的吗?为什么不是永久的? 435 | 436 | 不是。官方声明:一个 Watch 事件是一个一次性的触发器,当被设置了 Watch 的数据发生了改变的时候,则服务器将这个改变发送给设置了 Watch 的客户端,以便通知它们。 437 | 438 | 439 | 440 | 为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,给网络和服务器造成很大压力。 441 | 一般是客户端执行 getData(“/ 节点 A”,true),如果节点 A 发生了变更或删除,客户端会得到它的 watch 事件,但是在之后节点 A 又发生了变更,而客户端又没有设置 watch 事件,就不再给客户端发送。 442 | 在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,我只要最新的数据即可。 443 | 444 | #### 参考 445 | 446 | https://blog.csdn.net/weixin_43122090/article/details/103645642 447 | 448 | https://www.cnblogs.com/lanqiu5ge/p/9405601.html -------------------------------------------------------------------------------- /异常&反射.md: -------------------------------------------------------------------------------- 1 | ## 异常&反射 2 | 3 | ![image-20200414175020396](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/image-20200414175020396.png) 4 | 5 | #### 1.**error和exception有什么区别**? 6 | 7 | error表示系统级的错误,是java运行环境内部错误或者硬件问题,不能指望程序来处理这样的问题,除了退出运行外别无选择,它是Java虚拟机抛出的。 8 | 9 | exception 表示程序需要捕捉、需要处理的异常,是由与程序设计的不完善而出现的问题,程序必须处理的问题。 10 | 11 | #### 2.说出5个常见的**RuntimeException**? 12 | 13 | (1)Java.lang.NullPointerException 空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。 14 | 15 | (2)Java.lang.NumberFormatException 字符串转换为数字异常;出现原因:字符型数据中包含非数字型字符。 16 | 17 | (3)Java.lang.IndexOutOfBoundsException 数组角标越界异常,常见于操作数组对象时发生。 18 | 19 | (4)Java.lang.IllegalArgumentException 方法传递参数错误。 20 | 21 | (5)Java.lang.ClassCastException 数据类型转换异常。 22 | 23 | #### 3.**throw和throws的区别**? 24 | 25 | throw: 26 | 27 |   (1)throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。 28 | 29 |   (2)throw 是具体向外抛出异常的动作,所以它抛出的是一个异常实例,执行 throw 一定是抛出了某种异常。 30 | 31 | throws: 32 | 33 | ​ (1)@throws 语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理。 34 | 35 | ​ (2)throws 主要是声明这个方法会抛出某种类型的异常,让它的使用者要知道需要捕获的异常的类型。 36 | 37 | ​ (3)throws 表示出现异常的一种可能性,并不一定会发生这种异常。 38 | 39 | #### 4.Java中异常分类 40 | 41 | 按照异常处理时机: 42 | 43 | 编译时异常(受控异常(CheckedException))和运行时异常(非受控异常(UnCheckedException)) 44 | 45 | #### 5.如何自定义异常 46 | 47 | 继承Exception是检查性异常,继承RuntimeException是非检查性异常,一般要复写两个构造方法,用throw抛出新异常 48 | 49 | 如果同时有很多异常抛出,那可能就是异常链,就是一个异常引发另一个异常,另一个异常引发更多异常,一般我们会找它的原始异常来解决问题,一般会在开头或结尾,异常可通过initCause串起来,可以通过自定义异常 50 | 51 | #### 6.Java中异常处理 52 | 53 | 首先处理异常主要有两种方式:一种try catch,一种是throws。 54 | 55 | 1. try catch: 56 | 57 | - try{} 中放入可能发生异常的代码。catch{}中放入对捕获到异常之后的处理。 58 | 59 | 2.throw throws: 60 | 61 | - throw是语句抛出异常,出现于函数内部,用来抛出一个具体异常实例,throw被执行后面的语句不起作用,直接转入异常处理阶段。 62 | - throws是函数方法抛出异常,一般写在方法的头部,抛出异常,给方法的调用者进行解决。 63 | 64 | #### 7.常见的异常 65 | 66 | NullPointException:空指针异常,对象是null时会抛出,在调用传入对象时尽量判断是否为null,Jdk8里面可以用Optional对象来避免 67 | 68 | IndexOutOfBoundsException:数组下标越界,数组的下标超过了最大值时会抛出,在迭代循环时检查下标是否越界 69 | 70 | NumberFormatException:数字类型转化异常,将非数字类型转成数字类型,将类型转化的代码catch住 71 | 72 | ClassCastException:类型转换异常,发生在强转时,将不同类型转成同一类型,尽量少用强转,或用instanceof(判断继承中子类的实例是否是父类的实现)做类型判断,或多用泛型 73 | 74 | FileNotFoundException:找不到指定文件,文件路径错误或文件不存在,可能用了绝对路径检查文件是否存在,路径是否写错,多用相对路径 75 | 76 | ClassNotFoundException:在classpath中找不到引用的类缺乏引用当前类的jar或没有设置classpath或jar损坏-,找到jar并放入classpath中或检查jar是否损坏 77 | 78 | OutOfMemoryError:内存溢出异常,产生对象太多,内存不够->不要在循环体重创建大量对象,或对象及时回收,增大初始化堆:-Xms 增加最大值:-Xmx 79 | 80 | NoClassDefFoundError:找不到相应的类错误,缺乏当前引用类的jar或jar版本不对->找到jar并放入classpath中或找到合适的版本 81 | 82 | ConcurrentModificationException:并发修改异常,在集合迭代时修改里面的元素->在迭代时不要修改集合或用并发集合做遍历(如:ConcurrentHashMap) 83 | 84 | NoSuchMethodError:类里找不到相应的方法,一般是jar版本不对,当前引用的jar版本中没有这个方法->检查jar版本是否正确 85 | 86 | UnsupportedClassVersionError:版本不支持错误,编译class的jdk和运行时候的jdk版本不一致或比较高->将低版本换成高版本 87 | 88 | StackOverflowError:栈溢出错误,一般是函数的死循环,或递归调用无法退出->检查死循环的代码,或让递归有退出值,或加大栈初始化参数 89 | 90 | #### 8.异常打印信息组成 91 | 92 | 所处线程名字、异常类名、异常信息、异常堆栈、异常的源码,包名,类名,方法名,行数 93 | 94 | #### 9.常见方法 95 | 96 | getMessage:错误信息的字符串解释 97 | 98 | getCause:返回异常产生的原因,一般是原始异常如果不知道原因返回null 99 | 100 | printStackTrace:打印异常出现的位置或原因 101 | 102 | toString:返回String格式的Throwable信息,此信息包括Throwable的名字和本地化信息 103 | 104 | initCause:初始化原始异常 105 | 106 | PrintStream和PrintWriter作为产生实现重载,这样就能实现打印栈轨迹到文件或流中 107 | 108 | #### 10.如何自定义异常 109 | 110 | 继承Exception是检查性异常,继承RuntimeException是非检查性异常,一般要复写两个构造方法,用throw抛出新异常 111 | 112 | 如果同时有很多异常抛出,那可能就是异常链,就是一个异常引发另一个异常,另一个异常引发更多异常,一般我们会找它的原始异常来解决问题,一般会在开头或结尾,异常可通过initCause串起来,可以通过自定义异常 113 | 114 | #### 11.什么是Java反射机制? 115 | 116 | Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。 117 | 118 | #### 12.举例什么地方用到反射机制? 119 | 120 | 1. JDBC中,利用反射动态加载了数据库驱动程序。 121 | 2. Web服务器中利用反射调用了Sevlet的服务方法。 122 | 3. Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。 123 | 4. 很多框架都用到反射机制,注入属性,调用方法,如Spring。 124 | 125 | #### 13.java反射机制的作用 126 | 127 | - 在运行时判定任意一个对象所属的类 128 | - 在运行时构造任意一个类的对象; 129 | - 在运行时判定任意一个类所具有的成员变量和方法; 130 | - 在运行时调用任意一个对象的方法; 131 | - 生成动态代理; 132 | 133 | #### 14.Java反射机制类 134 | 135 | ``` 136 | java.lang.Class; //类 137 | java.lang.reflect.Constructor;//构造方法 138 | java.lang.reflect.Field; //类的成员变量 139 | java.lang.reflect.Method;//类的方法 140 | java.lang.reflect.Modifier;//访问权限 141 | ``` 142 | 143 | #### 15.反射机制优缺点? 144 | 145 | 优点:运行期类型的判断,动态加载类,提高代码灵活度。 146 | 147 | 缺点:性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。 148 | 149 | #### 16.利用反射创建对象? 150 | 151 | 1.通过一个全限类名创建一个对象 Class.forName(“全限类名”); 152 | 153 | 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了 类名.class; 获取Class<?> clz 对象 对象.getClass(); 154 | 155 | 2.获取构造器对象,通过构造器new出一个对象 Clazz.getConstructor([String.class]); Con.newInstance([参数]); 3.通过class对象创建一个实例对象(就相当与new类名()无参构造器) Cls.newInstance(); 156 | 157 | 158 | 159 | #### 参考: 160 | 161 | https://blog.csdn.net/qq_37875585/article/details/89340495 162 | 163 | https://www.cnblogs.com/whoislcj/p/6038511.html 164 | 165 | https://blog.csdn.net/Yang_Hui_Liang/article/details/90238678 166 | 167 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) -------------------------------------------------------------------------------- /简历.md: -------------------------------------------------------------------------------- 1 | ## 简历 2 | 3 | 4 | 5 | 原文链接:https://www.zhihu.com/question/25002833 ThoughtWorks中国回答 6 | 7 | 大家伙让一让,这个问题让老司机先答!作为一个潜入IT圈五年之久、看过数万份简历的HR,在这个问题上还是有点发言权的。HR在筛选简历时主要从公司需求出发,重点不一,不过还是有很多“通用”的套路,为了在30秒内判断出这份简历是否值得跟进,我认为程序员写简历的正确姿势是这样的: 8 | 9 | #### **一、基本格调** 10 | 11 | 即打开简历之后的第一印象。就好比我们看见一个人,会有一个整体的感觉,他是fashion的、小清新的还是老道的?有了第一印象之后再慢慢分解来看。 12 | 13 | **加分写法:** 14 | 15 | - 简洁明了,逻辑结构清晰。 16 | - 字体,排版,顺畅,清晰整齐就好。 17 | - 最好是PDF格式,兼容性强且不易乱序。 18 | 19 | **减分写法:** 20 | 21 | - 设计的过于浮夸或者过于简单的。(eg.有的简历五颜六色、非常酷炫,却半天找不到联系方式,抑或是只有个人基本信息和公司名称) 22 | - 写了十几页,半天打不开的,或者加载了半天,打开还乱码。 23 | 24 | #### **二、基本信息(姓名/性别/毕业院校/电话/邮箱/居住地/期望地)** 25 | 26 | **加分写法:** 27 | 28 | - 清晰罗列出以上信息,这样HR就不用在接下来的电话沟通或面试中再去追问这些内容,建立我们接下来电话沟通对你的熟悉度。 29 | - 再额外能加上QQ或者微信就更好了(以防有时候电话打不通哦,时不时会遇到这种情况) 30 | 31 | **减分写法:** 32 | 33 | - 大部分的基本信息没有写 34 | - 甩给我一个Github链接,极致简洁的几句描述,需要通过你的链接来找你的联系方式。(如果不是博客写的特别好,基本是要放弃你了) 35 | 36 | #### **三、工作经历&项目经历** 37 | 38 | **加分写法:** 39 | 40 | - 工作经历项目经历可参照万能的STAR法则来写,STAR不清楚的童鞋点[这里](https://link.zhihu.com/?target=http%3A//www.xuexila.com/success/story/509956.html)啦 41 | - 效力过哪些公司,我们匹配的公司? BAT? 知名大型互联网公司? 42 | - 做过什么行业领域,和我们目前的行业是否匹配 43 | - 擅长的技术语言,应用了哪些技术栈,(Java, Scala,Ruby, React, Vue, Microservice…) 44 | - 经历的项目复杂度,及在项目中承担什么样的角色(人的变化/技术的变化/环境的变化/不同工作经历相同角色的不同点) 45 | - 时间节点(空档期) 46 | 47 | **减分写法:** 48 | 49 | - 看了半天,不知所云,没有任何亮点,没有让人有去和你聊一聊深扒的信息。 50 | 51 | **来几个栗子** 52 | 53 | 栗子1错误打开方式: 54 | 55 | - XX(全栈工程师)2013.06 — 至今 56 | - 参与需求分析及实现方案设计。 57 | - 设计数据库表结构,实现后台功能及web页面展示。 58 | - 产品线上部署及运维。 59 | - ay 配置管理工程师 2010.03 — 2013.03 60 | - 负责公司产品性能测试,及线上数据分析 61 | - 负责公司配置管理,环境维护等工作 62 | 63 | **点评:看不出来他做的什么事情,没有逻辑性,甚至不知道他做的什么技术语言。** 64 | 65 | **栗子2正确打开方式:** 66 | 67 | **西安XXX公司 Java工程师 — 2016.2月-2017.2月** 68 | 69 | 1、MOGU推荐架构数据与缓存层设计开发 70 | 71 | - MOGU是一款时尚资讯app,负责推荐页面资讯feed流的展示及用户历史的展示 72 | - 负责数据层,处理前端逻辑整个开发工作,分布式rpc服务搭建 73 | - 负责进行压测监测、缓存处理,对接又进行改进优化,主用redis缓存 74 | 75 | 2、基于JAVA的电商爬虫开发 76 | 77 | - 使用java搭建爬虫server平台,进行配置和开发,进行网页改版监测功能开发 78 | - 爬取淘宝时尚品牌与其他电商网站商品品牌与详情等 79 | - 通过频率、ip池、匿名代理等应对一些网站的反爬 80 | 81 | 3、同图搜索Solr服务开发 82 | 83 | 基于算法组的同图策略,使用solr做java接又实现rpc服务搭建,进行索引构建和solr实现 84 | 85 | **北京XXX** 86 | 87 | java大数据工程师— 2013.4月-2015.12月 88 | 89 | 1、负责实时流消息处理应用系统构建和实现 90 | 91 | - 在调研了kafka的优势和我们的具体需求之后,用kafka作为消费者,保证高吞吐处理消息,并持久化消息的同时供其它服务使用,进行了系统的设计和搭建使用。 本地日志保证消息不丢失,并通过记录游标滑动重复读取数据。 92 | - 使用storm 负责搭建消息处理架构,并完成基于业务的消息落地,提供后续的数据 统计分析实时和离线任务,诸如pv、uv等数据,为运营做决策 93 | - 网站用户行为埋点和基于js的日志收集器开发,定义接又和前端部门配合。主用go 2、hadoop集群搭建和数据分析处理 94 | 95 | 2、基于CDH的集群搭建工作,后期进行维护 96 | 97 | 编写MapReduce程序,能将复杂工作逻辑化,尽最大能力发挥大数据应用的特点, 对程序高要求,监控自己程序运行情况,使用内存合理,注重增量和全量运算的利弊 98 | 99 | 3、调度系统设计与实现 基于quartz2搭建调度平台,带徒弟实现相关功能并定期review代码 100 | 101 | 4、数据库调优 负责主从搭建,并掌握主从搭建的利弊,了解业界mycat原理,有数据库优化经验,能 正确并擅长使用索引,对锁有深刻的认识 102 | 103 | 5、网站开发 java web网站业务开发,并能很好的使用缓存技术,对重构有实际的经验,并对面向对 象开发有全面的实战经验。了解java数据结构的使用场景,虽然对于大并发没有太大的 发挥余地,但是掌握了数据结构,对于并发和阻塞等有自己的见解。 104 | 105 | **点评:非常清晰的告诉简历阅读者自己做了什么事情,负责了什么样的事情,用了什么技术栈,且逻辑连贯。** 106 | 107 | #### **四、工作期望&个人评价** 108 | 109 | 加分写法: 110 | 111 | - 对自己有一个全方位的一个描述总结,让别人更好的解读你。或者在此处,高亮你的优点特长有哪些。 112 | - 即使不写个人评价,也一定记得写上工作期望。 113 | 114 | 减分写法: 115 | 116 | 完全看不出个性特点,写和没写没什么区别。 来几个栗子 117 | 118 | **栗子1 错误打开方式** 119 | 120 | 为人性格,诚实谦虚,勤奋,能吃苦耐劳,有耐心,有团队意识,能和同学和谐相处,能虚心接受别人的建议的人。 121 | 122 | 责任心强,善于沟通,具有良好的团队合作精神;专业扎实,具有较强的钻研精神和学习能力;性格比较乐观外向,喜欢打羽毛球。 123 | 124 | **栗子2正确打开方式** 125 | 126 | - 我对自己的定位: 主攻前端,同时在其他方面打打辅助。我不希望过于依赖别人,即使没有后端没有设计没有产品经理,我依然想要把这个产品做到完美。毕竟全栈才能最高效地解决问题。 127 | - 我对工作的态度: 第一,要高效完成自己的本职工作。第二,要在完成的基础上寻找完美。第三,要在完美的基础上,与其他同事 互相交流学习,互相提升。工作是一种生活方式,不是一份养家糊口的差事。 128 | - 我怎样克服困难: 不用百度是第一原则,在遇到技术问题时我往往会去Google、Stack over flow上寻找答案。但通常很多问题 并不一定已经被人解决,所以熟练地阅读源码、在手册、规范甚至 REPL的环境自己做实验才是最终解决问题的办法。相信事实的结果,自己动手去做。 129 | - 怎样保持自己的视野:我一直认为软件开发中视野极其重要,除了在 Twitter 上关注业界大牛,Github Trending 也是每周必刷。 另外 Podcast、Hacker News、Reddit 以及TechRadar 也是重要的一手资料。保持开阔视野才能找到更酷的解决方案。 130 | - 我的优势: 热爱技术、自学能力强,有良好的自我认知。全面的技能树与开阔的视野,良好的心态、情商与沟通能力。 131 | - 我的劣势: 非科班出身没有科班同学对算法的熟练掌握,但我决定死磕技术,弥补不足。 132 | 133 | **栗子3正确打开方式** 134 | 135 | - 极客、热爱技术、热爱开源 136 | - Ruby on Rails:精通 137 | - Agile/Lean:精通 138 | - ReactJS:掌握 139 | - Docker:掌握 140 | - AWS:掌握 141 | 142 | #### **五、 是否有博客,个人技术栈点等** 143 | 144 | 1. 看到有这项的HR两眼已经放光了,加分加分项,说明你真正的热爱技术,善于学习总结,乐于分享,且有投入自己的业余时间到软件事业中。 145 | 2. 我喜欢的书籍:《重构》《卓有成效的程序员》《代码整洁之道》等 146 | 3. 我喜欢的社区: 图灵社区,知乎,博客园,Stack Over flow,Google Developer Group等 147 | 4. 我的博客链接、个人作品链接如下: 148 | 149 | - [https://github.com/github](https://link.zhihu.com/?target=https%3A//github.com/github) 150 | - [http://www.oschina.net/](https://link.zhihu.com/?target=http%3A//www.oschina.net/) 151 | - [https://www.cnblogs.com/](https://link.zhihu.com/?target=https%3A//www.cnblogs.com/) 152 | - [https://itunes.apple.com/app/battle-of-crab/id1121917063?l=en&amp;mt=8](https://link.zhihu.com/?target=https%3A//itunes.apple.com/app/battle-of-crab/id1121917063%3Fl%3Den%26mt%3D8) 153 | 154 | #### **六、简历内容真实性** 155 | 156 | 老司机提醒你,你简历的任意一个细节将会是后面面试中的呈堂证供。 157 | 158 | 基本就这些了,希望对大家能有帮助,看起简历来几十秒,码字还是个体力活。 159 | 160 | ##### 微信搜索Java小咖秀 回复 “简历1” 获取404份简历模版 161 | 162 | 163 | 164 | 写在最后: 希望大家都能拿到自己心仪的offer。面试笔记会继续更新优化。 165 | 166 | ![WechatIMG360](https://gitee.com/yizhibuerdai/Imagetools/raw/master/images/common1.png) 167 | 168 | -------------------------------------------------------------------------------- /计算机基础.md: -------------------------------------------------------------------------------- 1 | # 计算机基础 2 | 3 | #### 1.ICMP 是什么协议?处于哪一层? 4 | 5 | ICMP是(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。属于网络层协议 6 | 7 | 控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。 8 | 9 | 10 | 11 | #### 2.什么是程序局部性?为什么会有程序的空间局部性? 12 | 13 | 程序局部性是指程序在运行时呈现出局部性规律,在一段时间间隔内,程序的执行是局限在某个部份,所访问的存储空间也只局限在某个区域。 14 | 15 | 程序的空间局部性是指若一个存储单元被访问,那么它附近的单元也可能被访问,这是由于程序的顺序执行引起的。 16 | 17 | 18 | 19 | #### 3.谈一谈 TCP 与 UDP 的区别。 20 | 21 | TCP与UDP都是传输层的协议,且都用端口号标识数据所达的进程。 22 | 23 | TCP提供的是面向连接服务,提供可靠交付。且具有流量控制和拥塞控制。可用于可靠要求高的场合如:SMTP,FTP,HTTP等 24 | 25 | UDP提供的是无连接服务,提供不可靠交付,且无确认机制。主要用于即时强的场合如:视频聊天,语音电话等。 26 | 27 | 28 | 29 | #### 4.网络协议的三个核心要素是什么?各有什么作用? 30 | 31 | 答: 32 | 33 | 语法,定义了数据与控制信息的格式; 34 | 35 | 语义,定义了需要发出何种控制信息,完成何种响应动作以及作出何种响应; 36 | 37 | 同步,定义了事件实现顺序的详细说明; 38 | 39 | 40 | 41 | #### 5.为了实现重定位,需要哪些硬件? 42 | 43 | 答: 44 | 45 | 最简单的方式是在系统中增设一个重定位寄存器,用来存放正在执行作业的内存地址,每次访问数据时,由硬件自动将相对地址与重定位寄存器中的起始地址相加,形成实际的特理地址。当然在分页式与分段式系统中,具地址变换机构,以及快表等硬件。 46 | 47 | 48 | 49 | #### 6.在交互式系统中,非剥夺是不是一个好的策略?为什么? 50 | 51 | 答: 52 | 53 | 非剥夺方式:分派程序一旦把处理机分配给某进程后便让它一直运行下去,直到进程完成或发生某事件而阻塞时,才把处理机分配给另一个进程。 54 | 55 | 剥夺方式:当一个进程正在运行时,系统可以基于某种原则,剥夺已分配给它的处理机,将之分配给其它进程。剥夺原则有:优先权原则、短进程、优先原则、时间片原则。 56 | 57 | 在分时系统中不剥夺并不是一个好的策略。因为,在分时系统中,除了交互性以外,及时性是很重要的性能因素。当一个作业被阻塞后,CPU就完全空闲了,别的用户的及时性就无法保证了,而完全可以把这些时间分配给别的作业运行。以提高整体的吞吐量。 58 | 59 | 60 | 61 | #### 7.何为死锁?何为系统调用? 62 | 63 | 答: 64 | 65 | 死锁:指多个有关进程由于争夺资源而造成的一种僵局,在无外力的情况下这些进程都将无法再向前推进的状态。 66 | 67 | 系统调用:系统调用是OS与应用程序之间的接口,它是用户程序取得OS服务的惟一途径。 68 | 69 | 它与一般的过程调用的区别: 70 | 71 | 运行在不同的系统状态。调用程序在运行在用户态,而被调用的程序运行在系统态; 72 | 73 | 通过软中断机制,先由用户态转为系统态,经枋心分析后,才能转向相应的系统调用处理子程序;一般的过程调用返回后继续执行,但对系统调用,当调用的进程仍具有最高优先权时,才返回到调用进程继续处理;否则只能等被重新调度; 74 | 75 | 76 | 77 | #### 8.CPU 不执行程序的时候在干什么? 78 | 79 | 答: 80 | 81 | 当没有被任何程序使用的时候,计算机的处理器被认为是空闲的。当然下面提到的空闲任务不在此列中。当有程序利用CPU空闲时间的时候,就意味着它以较低的优先权运行着,以便不会影响那有正常优先权的程序运行。一般来讲,这会引起CPU消耗更多的电能,而大多数的现代CPU当它们空闲的时候是能够进入省电模式的。大多数操作系统都有个空闲任务,它是一个特殊的任务。仅当CPU无事可做的时候由操作系统调度器载入它。在现代的处理器中,HLT停机指令节省了大量的电能与执量,而空闲任务几乎总是由一个重复执行HLT停机指令的循环组成。 82 | 83 | 84 | 85 | #### 9.试举例解释一下同步和互斥 86 | 87 | 答: 88 | 89 | 同步表现为直接制约,如管道通信,一个进程写,一个进程读,它们是相互制约的。 90 | 91 | 互斥表现为间接制约,比如多个进程同时请求打印机(没使用SPOOLing技术)、多个进程同时请求一张网卡发送数据包等。 92 | 93 | 94 | 95 | #### 10.在可变分区管理中,需要哪些硬件机制? 96 | 97 | 答: 98 | 99 | 采用可变分区方式管理时,一般均采用动态重定位方式装入作业。地址变换要靠硬件支持,主要是两个寄存器:基址寄存器和限长寄存器,限长寄存器存放作业所占分区的长度,基址寄存器则存放作业所占分区的起始地址,这两个值确定了一个分区的位置和大小。 100 | 101 | 转换时根据逻辑地址与限长值比较,如果不有超过这个值,表示访问地址合法,再加上基址寄存器中的值就得到了绝对地址了,否则形成“地址越界”中断。 102 | 103 | #### 11.谈一谈中断和陷入的区别 104 | 105 | 外中断时指来自处理机和内存外部的中断,如I/O中断、定时器中断、外部信号中断等。狭义上也叫中断; 106 | 107 | 内中断主要指在处理机和内存内部产生的中断,也称陷入,如校验错、页面失效、溢出、除数为零等; 108 | 109 | 中断和陷阱的主要区别: 110 | 111 | (1)陷入通常由处理机正在执行的现行指令引起,而中断则是由与现行指令无关的中断源引起的。 112 | 113 | (2) 陷阱处理程序提供的服务为当前进程所用,而中断处理程序提供的服务则不是为了当前进程的。 114 | 115 | (3) CPU在执行完一条指令之后,下一条指令开始之前响应中断,而在一条指令执行中也可以响应陷阱。 116 | 117 | #### 12.数据库系统和文件系统相比有什么优点? 118 | 119 | 答: 120 | 121 | 文件系统 122 | 123 | 数据库管理系统 124 | 125 | 某一应用 126 | 127 | 现实世界 128 | 129 | 共享性差,冗余度大 130 | 131 | 共享性高,冗余度小 132 | 133 | 记录内有结构,整体无结构 134 | 135 | 整体结构化,用数据模型描述 136 | 137 | 应用程序自己控制 138 | 139 | 由数据库管理系统提供数据安全性,完整性,并发控制和恢复能力 140 | 141 | 独立性差 142 | 143 | 具有高度的物理独立性和一定的逻辑独立性 144 | 145 | #### 13.谈一谈计算机网络和分布式计算机系统的区别 146 | 147 | 两者在计算机硬件连接、系统拓朴结构和通信控制等方面基本都是一样的,它们都具有通信和资源共享的功能。 148 | 149 | 区别关键在于:分布式计算机系统是在分布式计算机操作系统支持下,进行分布式数据库处理的,也就是说各互联的计算机可以互相协调工作,共同完成一项任务,多台计算机上并行运行。且具有透明性,用户不知道数据、资源的具体位置,整个网络中所有计算机就像是一台计算机一样;而计算机网络却不具备这种功能,计算机网络系统中的各计算机通常是各自独立进行工作的。 150 | 151 | #### 14.为什么要引入多道程序技术? 152 | 153 | 因为引入多道程序技术后,可以进一步提高了CPU利用率(阻塞),提高内存和I/O设备利用率(小作业把内存浪费了),增加系统吞吐量(两都提高后的必然)。 154 | 155 | #### 15.何为管态和目态?它们与进程运行状态的关系是什么? 156 | 157 | CPU交替执行操作系统程序和用户程序。管态又叫特权态,系统态或核心态。CPU在管态下可以执行指令系统的全集。通常,操作系统在管态下运行。 158 | 159 | 目态又叫常态或用户态。机器处于目态时,程序只能执行非特权指令。用户程序只能在目态下运行,如果用户程序在目态下执行特权指令,硬件将发生中断,由操作系统获得控制,特权指令执行被禁止,这样可以防止用户程序有意或无意的破坏系统。 160 | 161 | #### 16.何为网络延时?何为完整性约束? 162 | 163 | 时延(delay或latency)是指一个报文或分组从一个网络(或一条链路)的一端传送到另一端所需的时间。 164 | 165 | 数据完整性约束指的是为了防止不符合规范的数据进入数据库,在用户对数据进行插入、修改、删除等操作时,DBMS自动按照一定的约束条件对数据进行监测,使不符合规范的数据不能进入数据库,以确保数据库中存储的数据正确、有效、相容。 166 | 167 | 简单理解:按照一定的约束条件防止不符合规范的数据进入数据库 168 | 169 | #### 17.谈一谈你对当前 5G 技术和云计算技术的理解 170 | 171 | 5G,第五代移动通信技术,有三个关键特征,超高速率,实现每秒10Gb的下载速率,是4G的100倍。超可靠超低时延,实现1ms的低时延,是4G时延的40分之一;超大连接,实现每平方公里100万的连接数,是4G的100倍。 172 | 173 | 云计算技术:分布式计算的一种,指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,然后,通过多部服务器组成的系统进行处理和分析这些小程序得到结果并返回给用户。云计算具有很强的扩展性和需要性,可以为用户提供一种全新的体验,云计算的核心是可以将很多的计算机资源协调在一起,因此,使用户通过网络就可以获取到无限的资源,同时获取的资源不受时间和空间的限制。 174 | 175 | #### 18.点对点和端对端工作在哪层?工作机制是什么? 176 | 177 | 点对点协议(Point to Point Protocol)的缩写为PPP,是TCP/IP网络协议包的一个成员。PPP是TCP/IP的扩展,它增加了两个额外的功能组: 178 | 179 | (1)它可以通过串行接口传输TCP/IP包; 180 | 181 | (2)它可以安全登录。 182 | 183 | 数据传输的可靠性是通过数据链路层和网络层的点对点和传输层的端对端保证的。点对点是基于MAC地址或者IP地址,是指一个设备发数据给另外一个设备,这些设备是指直连设备包括网卡,路由器,交换机。端对端是网络连接,应用程序之间的远程通信。端对端不需要知道底层是如何传输的,是一条逻辑链路。 184 | 185 | 端到端与点到点是针对网络中传输的两端设备间的关系而言的。端到端传输指的是在数据传输前,经过各种各样的交换设备,在两端设备问建立一条链路,就像它们是直接相连的一样,链路建立后,发送端就可以发送数据,直至数据发送完毕,接收端确认接收成功。点到点系统指的是发送端把数据传给与它直接相连的设备,这台设备在合适的时候又把数据传给与之直接相连的下一台设备,通过一台一台直接相连的设备,把数据传到接收端。 端到端传输的优点是链路建立后,发送端知道接收设备一定能收到,而且经过中间交换设备时不需要进行存储转发,因此传输延迟小。端到端传输的缺点是直到接收端收到数据为止,发送端的设备一直要参与传输。如果整个传输的延迟很长,那么对发送端的设备造成很大的浪费。端到端传输的另一个缺点是如果接收设备关机或故障,那么端到端传输不可能实现。 点到点传输的优点是发送端设备送出数据后,它的任务已经完成,不需要参与整个传输过程,这样不会浪费发送端设备的资源。另外,即使接收端设备关机或故障,点到点传输也可以采用存储转发技术进行缓冲。点到点传输的缺点是发送端发出数据后,不知道接收端能否收到或何时能收到数据。 在一个网络系统的不同分层中,可能用到端到端传输,也可能用到点到点传输。如Internet网,IP及以下各层采用点到点传输,IP层以上采用端到端传输。 186 | 187 | 端对端,点对点,只是称为问题,本质区别很小 188 | 189 | 端对端,主要服务于Application Layer,是说两台主机(终端),跨过网络直接连接 190 | 191 | 点对点,是说两台主机(终端)在局域网中传输。 192 | 193 | #### 19.DBMS 支持哪几种数据模型?SQL 的四个组成部分是什么? 194 | 195 | 常用的是层次模型,网状模型和关系模型(最重要) 196 | 197 | SQL的四个组成部分: 198 | 199 | 1、数据库模式定义语言DDL:create用来创建数据库中的各种对象——表、视图、索引、同义词、聚簇等 200 | 201 | 2、数据查询语言dql:基本结构是由SELECT子句,FROM子句和WHERE子句组成的查询块 202 | 203 | 3、数据操纵语言dml:插入INSERT、更新UPDATE和删除DELETE 204 | 205 | 4、数据控制语言dcl:用来授予或回收访问数据库的某种特权,并控制数据库操纵事物发生的时间和效果,对数据库实行监视等 206 | 207 | #### 20.谈一谈网络时延由哪几个部分组成?各产生于何处? 208 | 209 | 网络时延主要由发送时延,传播时延,处理时延组成。发送时延是指结点在发送数据时使数据块从结点进入到传输媒体所需的时间,也就是从数据块的第一个比特开始发送算起,到最后一个比特发送完毕所需的时间。发送时延又称为传输时延,它的计算公式是: 210 | 211 | 发送时延=数据块长度/信道带宽 212 | 213 | 信道带宽就是数据在信道上的发送速率,它也常称为数据在信道上的传输速率。 214 | 215 | 传播时延是指从发送端发送数据开始,到接收端收到数据(或者从接收端发送确认帧,到发送端收到确认帧),总共经历的时间。 216 | 217 | 传播时延 = d/s 218 | 219 | d = 物理链路的长度 220 | 221 | s = 介质的信号传播速度 (~2x108 m/sec) 222 | 223 | 处理时延是指计算机处理数据所需的时间,与计算机CPU的性能有关。 224 | 225 | #### 21.TCP/IP 网络协议的核心是什么?如何引出"over everything"和"everythingover"。 226 | 227 | TCP/IP协议的核心是TCP、UDP和IP协议 228 | 229 | 分层次画出具体的协议来表示TCP/IP协议族,它的特点是上下两头大而中间小:应用层和网络接口都有很多协议,而中间的IP层很小,上层的各种协议都向下汇聚到一个IP协议中。这种很像沙漏计时器形状的TCP/IP协议族表明:TCP/IP协议可以为各种各样的应用提供服务(everything over ip) 同时TCP/IP协议也允许IP协议在各种各样的网络构成的互联网上运行(IP over everything)。 230 | 231 | #### 22.谈一谈 ARP 地址解析协议的工作原理。 232 | 233 | 网络层以上的协议用IP地址来标识网络接口,但以太数据帧传输时,以物理地址来标识网络接口。因此我们需要进行IP地址与物理地址之间的转化。 234 | 235 | 对于IPv4来说,我们使用ARP地址解析协议来完成IP地址与物理地址的转化(IPv6使用邻居发现协议进行IP地址与物理地址的转化,它包含在ICMPv6中)。 236 | 237 | ARP协议提供了网络层地址(IP地址)到物理地址(mac地址)之间的动态映射。ARP协议 是地址解析的通用协议。 238 | 239 | ARP地址解析实现原理 240 | 241 | 每个主机都会在自己的 ARP 缓冲区中建立一个 ARP 列表,以表示 IP 地址和 MAC 地址之间的对应关系。 242 | 主机(网络接口)新加入网络时(也可能只是mac地址发生变化,接口重启等), 会发送免费ARP报文把自己IP地址与Mac地址的映射关系广播给其他主机。 243 | 网络上的主机接收到免费ARP报文时,会更新自己的ARP缓冲区。将新的映射关系更新到自己的ARP表中。 244 | 某个主机需要发送报文时,首先检查 ARP 列表中是否有对应 IP 地址的目的主机的 MAC 地址,如果有,则直接发送数据,如果没有,就向本网段的所有主机发送 ARP 数据包,该数据包包括的内容有:源主机 IP 地址,源主机 MAC 地址,目的主机的 IP 地址等。 245 | 当本网络的所有主机收到该 ARP 数据包时: 246 | 247 | (A)首先检查数据包中的 IP 地址是否是自己的 IP 地址,如果不是,则忽略该数据包。 248 | 249 | (B)如果是,则首先从数据包中取出源主机的 IP 和 MAC 地址写入到 ARP 列表中,如果已经存在,则覆盖。 250 | 251 | (C) 然后将自己的 MAC 地址写入 ARP 响应包中,告诉源主机自己是它想要找的 MAC 地址。 252 | 253 | 6.源主机收到 ARP 响应包后。将目的主机的 IP 和 MAC 地址写入 ARP 列表,并利用此信息发送数据。如果源主机一直没有收到 ARP 响应数据包,表示 ARP 查询失败。 254 | 255 | #### 23.谈一谈 DNS 域名系统的工作原理 256 | 257 | DNS(Domain Name System,域名系统) 258 | 259 | 因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析) 260 | 261 | 每个IP地址都可以有一个主机名,主机名由一个或多个字符串组成,字符串之间用小数点隔开。有了主机名,就不要死记硬背每台IP设备的IP地址,只要记住相对直观有意义的主机名就行了。这就是DNS协议所要完成的功能。 262 | 263 | 主机名到IP地址的映射有两种方式:DNS 264 | 265 | 1)静态映射,每台设备上都配置主机到IP地址的映射,各设备独立维护自己的映射表,而且只供本设备使用; 266 | 267 | 2)动态映射,建立一套域名解析系统(DNS),只在专门的DNS服务器上配置主机到IP地址的映射,网络上需要使用主机名通信的设备,首先需要到DNS服务器查询主机所对应的IP地址。 268 | 269 | 通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。在解析域名时,可以首先采用静态域名解析的方法,如果静态域名解析不成功,再采用动态域名解析的方法。可以将一些常用的域名放入静态域名解析表中,这样可以大大提高域名解析效率。 270 | 271 | 比如我们游览一个网站的时候,打开一个网址, 这个时候 我们的电脑会首先发送一个数据包个 DNS系统 ,DNS系统回应一个数据包给我们,然后再转到我们游览的网站! 那个数据包里面就包含这个 我们访问的这个网站,然后返回来的数据包是 解析成了IP地址,然后就能通过TCP/IP协议通信了! 272 | 273 | 再比如我们发送baidu.com到DNS服务器,DNS服务器发给我们百度的服务器的IP,如果我们直接输入IP就绕开了解析这一个步骤 274 | 275 | #### 24.何为网桥?防火墙的端口防护是指什么? 276 | 277 | 网桥:网桥(Bridge)像一个聪明的中继器。中继器从一个网络电缆里接收信号, 放大它们,将其送入下一个电缆。相比较而言,网桥对从关卡上传下来的信息更敏锐一些。网桥是一种对帧进行转发的技术,根据MAC分区块,可隔离碰撞。网桥将网络的多个网段在数据链路层连接起来。 278 | 279 | 网桥也叫桥接器,是连接两个局域网的一种存储/转发设备,它能将一个大的LAN分割为多个网段,或将两个以上的LAN互联为一个逻辑LAN,使LAN上的所有用户都可访问服务器。 280 | 281 | 防火墙端口防护:指通过对防火墙的端口开关的设置,关闭一些非必需端口,达到一定安全防护目的行为。 282 | 283 | 284 | 285 | #### 参考 286 | 287 | https://blog.csdn.net/lingess/article/details/98479704 --------------------------------------------------------------------------------