Java基础内容汇总[持续更新]

汇总什么?

用于笔者日常笔记汇总,工作一段时间了,也看了一些源码,技术广度、深度都有点半桶水味道了,重头拾起当初的知识点~。很多东西不做记录且长时间不回忆不使用就容易忘记,与其到处搜索不如汇总一处。 (2021/07/08 记)

本文不会记录较难的内容,只会记录常见基础的概念性内容,相关有深度的记录与剖析单独成篇。

备用分类

String&final的好处

String类的源码可以看出String是被final修饰的类,这样设计的好处是什么呢?

Java 语言之父 James Gosling 的回答是,他会更倾向于使用 final,因为它能够缓存结果,当你在传参时不需要考虑谁会修改它的值;如果是可变类的话,则有可能需要重新拷贝出来一个新值进行传参,这样在性能上就会有一定的损失。
James Gosling 还说迫使 String 类设计成不可变的另一个原因是安全,当你在调用其他方法时,比如调用一些系统级操作指令之前,可能会有一系列校验,如果是可变类的话,可能在你校验过后,它的内部的值又被改变了,这样有可能会引起严重的系统崩溃问题,这是迫使 String 类设计成不可变类的一个重要原因。
总结来说,使用 final 修饰的第一个好处是安全;第二个好处是高效。

JVM

JVM内存布局

  • 虚拟机栈 — 线程独占
  • 本地方法栈 — 线程独占
  • 程序计数器 — 线程独占
  • 堆 — 共享内存(线程)
  • 方法区 共享内存(线程)

类加载

  • 加载阶段(Loading)
  • 验证阶段(Verification) —— 连接
  • 准备阶段(Preparation) —— 连接 (此阶段是用来初始化并为类中定义的静态变量分配内存的,这些静态变量会被分配到方法区上。HotSpot 虚拟机在 JDK 1.7 之前都在方法区,而 JDK 1.8 之后此变量会随着类对象一起存放到 Java 堆中。)
  • 解析阶段(Resolution) —— 连接
  • 初始化阶段(Initialization)
  • 使用阶段(Using)
  • 卸载阶段(Unloading)

判断对象是否存活的方法

  • 引用计数法 – 无法解决循环引用问题
  • 可达性分析算法

可作为GC Roots的对象

  • 所有被同步锁持有的对象,比如被 synchronize 持有的对象;
  • 字符串常量池里的引用(String Table);
  • 类型为引用类型的静态变量;
  • 虚拟机栈中引用对象;
  • 本地方法栈中的引用对象。

垃圾回收算法

  • 标记-清除 -> 产生内存空间碎片化问题,有大量不连续的内存,当需要分配大对象时候,会触发垃圾回收动作
  • 标记-复制 -> 需要Double的内存,实际使用的只有一半,内存可用率降低
  • 标记-整理 -> 前两者结合,会整理内存碎片

HotSpot中的垃圾收集器

  • Serial -> 单线程,所有工作线程必须暂停
  • ParNew -> Serial的多线程版本
  • Parallel Scavenge -> 与ParNew类似,但是该收集器关注吞吐量
  • -XX:MaxGCPauseMillis 参数:它是用来控制垃圾回收的最大停顿时间
  • -XX:GCTimeRatio 参数:它是用来直接设置吞吐量的值的
  • Serial Old -> Serial的老年代版本
  • Parallel Old -> Parallel Old的老年代版本
  • CMS -> (标记-清除)与Parallel Scavenge不同,强调的是提供最短的停顿时间,所以会牺牲一定的吞吐量。 主要应用在Java Web项目中,满足系统需要的短时间停顿要求,提高用户的交互体验
  • G1 -> 先进的收集器,主要面向服务端应用。它将内存划分为多个Region分区,回收时以分区为单位,可以较少的时间优先回收包含垃圾最多的区块。JDK9后也成了官方默认收集器,官方也推荐G1替代CMS
  • ZGC -> JDK11新增的收集器。

ZGC 收集器是 JDK 11 中新增的垃圾收集器,它是由 Oracle 官方开发的,并且支持 TB 级别的堆内存管理,而且 ZGC 收集器也非常高效,可以做到 10ms 以内完成垃圾收集。
在 ZGC 收集器中没有新生代和老生代的概念,它只有一代。ZGC 收集器采用的着色指针技术,利用指针中多余的信息位来实现着色标记,并且 ZGC 使用了读屏障来解决 GC 线程和应用线程可能存在的并发(修改对象状态的)问题,从而避免了Stop The World(全局停顿),因此使得 GC 的性能大幅提升。

Java基础内容汇总[持续更新]

生产环境排忧解难

JDK自带的命令:jps,jstat,jinfo,jmap,jhat,jstack

jps(虚拟机进程状况工具)

jps(JVM Process Status tool,虚拟机进程状况工具)它的功能和 Linux 中的 ps 命令比较类似,用于列出正在运行的 JVM 的 LVMID(Local Virtual Machine IDentifier,本地虚拟机唯一 ID),以及 JVM 的执行主类、JVM 启动参数等信息。

jps [options] [hostid]

常用的options选项:

  • -l:用于输出运行主类的全名,如果是 jar 包,则输出 jar 包的路径;
  • -q:用于输出 LVMID(Local Virtual Machine Identifier,虚拟机唯一 ID);
  • -m:用于输出虚拟机启动时传递给主类 main() 方法的参数;
  • -v:用于输出启动时的 JVM 参数。
jstat(虚拟机统计信息监视工具)

jstat(JVM Statistics Monitoring Tool,虚拟机统计信息监视工具)用于监控虚拟机的运行状态信息。
例如,我们用它来查询某个 Java 进程的垃圾收集情况

➜  jstat -gc 43704

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT

10752.0 10752.0  0.0    0.0   65536.0   5243.4   175104.0     0.0     4480.0 774.0  384.0   75.8       0    0.000   0      0.000   -          -    0.000

Java基础内容汇总[持续更新]

jstat常用的查询参数有:

  • -class,查询类加载器信息;
  • -compiler,JIT 相关信息;
  • -gc,GC 堆状态;
  • -gcnew,新生代统计信息;
  • -gcutil,GC 堆统计汇总信息。
jinfo(查询虚拟机参数配置工具)

jinfo(Configuration Info for Java)用于查看和调整虚拟机各项参数。语法如下:

jinfo <option> <pid>
</pid></option>

查看JVM参数示例:

&#x279C;&#xA0; jinfo -flags 45129

VM Flags:

-XX:CICompilerCount=3 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:MaxNewSize=1431306240 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC

其中 45129 是使用 jps 查询的 LVMID。
我们可以通过 jinfo -flag [+/-]name 来修改虚拟机的参数值,比如下面的示例:

&#x279C;&#xA0; jinfo -flag PrintGC 45129 # &#x67E5;&#x8BE2;&#x662F;&#x5426;&#x5F00;&#x542F; GC &#x6253;&#x5370;

-XX:-PrintGC

&#x279C;&#xA0; jinfo -flag +PrintGC 45129 # &#x5F00;&#x542F; GC &#x6253;&#x5370;

&#x279C;&#xA0; jinfo -flag PrintGC 45129 # &#x67E5;&#x8BE2;&#x662F;&#x5426;&#x5F00;&#x542F; GC &#x6253;&#x5370;

-XX:+PrintGC

&#x279C;&#xA0; jinfo -flag -PrintGC 45129 # &#x5173;&#x95ED; GC &#x6253;&#x5370;

&#x279C;&#xA0; jinfo -flag PrintGC 45129 # &#x67E5;&#x8BE2;&#x662F;&#x5426;&#x5F00;&#x542F; GC &#x6253;&#x5370;

-XX:-PrintGC
jmap(堆快照生成工具)

jmap(Memory Map for Java)用于查询堆的快照信息
查询堆信息示例如下:

&#x279C;&#xA0; jmap -heap 45129

Attaching to process ID 45129, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 25.101-b13

using thread-local object allocation.

Parallel GC with 6 thread(s)

Heap Configuration:

&#xA0; &#xA0;MinHeapFreeRatio&#xA0; &#xA0; &#xA0; &#xA0; &#xA0;= 0

&#xA0; &#xA0;MaxHeapFreeRatio&#xA0; &#xA0; &#xA0; &#xA0; &#xA0;= 100

&#xA0; &#xA0;MaxHeapSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; = 4294967296 (4096.0MB)

&#xA0; &#xA0;NewSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; = 89128960 (85.0MB)

&#xA0; &#xA0;MaxNewSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;= 1431306240 (1365.0MB)

&#xA0; &#xA0;OldSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; = 179306496 (171.0MB)

&#xA0; &#xA0;NewRatio&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;= 2

&#xA0; &#xA0;SurvivorRatio&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; = 8

&#xA0; &#xA0;MetaspaceSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; = 21807104 (20.796875MB)

&#xA0; &#xA0;CompressedClassSpaceSize = 1073741824 (1024.0MB)

&#xA0; &#xA0;MaxMetaspaceSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0;= 17592186044415 MB

&#xA0; &#xA0;G1HeapRegionSize&#xA0; &#xA0; &#xA0; &#xA0; &#xA0;= 0 (0.0MB)

Heap Usage:

PS Young Generation

Eden Space:

&#xA0; &#xA0;capacity = 67108864 (64.0MB)

&#xA0; &#xA0;used&#xA0; &#xA0; &#xA0;= 5369232 (5.1204986572265625MB)

&#xA0; &#xA0;free&#xA0; &#xA0; &#xA0;= 61739632 (58.87950134277344MB)

&#xA0; &#xA0;8.000779151916504% used

From Space:

&#xA0; &#xA0;capacity = 11010048 (10.5MB)

&#xA0; &#xA0;used&#xA0; &#xA0; &#xA0;= 0 (0.0MB)

&#xA0; &#xA0;free&#xA0; &#xA0; &#xA0;= 11010048 (10.5MB)

&#xA0; &#xA0;0.0% used

To Space:

&#xA0; &#xA0;capacity = 11010048 (10.5MB)

&#xA0; &#xA0;used&#xA0; &#xA0; &#xA0;= 0 (0.0MB)

&#xA0; &#xA0;free&#xA0; &#xA0; &#xA0;= 11010048 (10.5MB)

&#xA0; &#xA0;0.0% used

PS Old Generation

&#xA0; &#xA0;capacity = 179306496 (171.0MB)

&#xA0; &#xA0;used&#xA0; &#xA0; &#xA0;= 0 (0.0MB)

&#xA0; &#xA0;free&#xA0; &#xA0; &#xA0;= 179306496 (171.0MB)

&#xA0; &#xA0;0.0% used

2158 interned Strings occupying 152472 bytes.

我们也可以直接生成堆快照文件,示例如下:

&#x279C;&#xA0; jmap -dump:format=b,file=/Users/admin/Documents/2020.dump 47380

Dumping heap to /Users/admin/Documents/2020.dump ...

Heap dump file created
jhat(堆快照分析功能)

jhat(JVM Heap Analysis Tool,堆快照分析工具)和 jmap 搭配使用,用于启动一个 web 站点来分析 jmap 生成的快照文件。

执行示例如下(7000端口):

jhat /Users/admin/Documents/2020.dump

Reading from /Users/admin/Documents/2020.dump...

Dump file created Tue May 26 16:12:41 CST 2020

Snapshot read, resolving...

Resolving 17797 objects...

Chasing references, expect 3 dots...

Eliminating duplicate references...

Snapshot resolved.

Started HTTP server on port 7000

Server is ready.

jastack(查询虚拟机当前的线程快照信息)

jstack(Stack Trace for Java)用于查看当前虚拟机的线程快照,用它可以排查线程的执行状况,例如排查死锁、死循环等问题

jstack [-l] pid

JVM调优

常见参数:

  • -Xmx,设置最大堆内存大小;
  • -Xms,设置初始堆内存大小;
  • -XX:MaxNewSize,设置新生代的最大内存;
  • -XX:MaxTenuringThreshold,设置新生代对象经过一定的次数晋升到老生代;
  • -XX:PretrnureSizeThreshold,设置大对象的值,超过这个值的对象会直接进入老生代;
  • -XX:NewRatio,设置分代垃圾回收器新生代和老生代内存占比;
  • -XX:SurvivorRatio,设置新生代 Eden、Form Survivor、To Survivor 占比。

并发编程

Synchronized&ReentrantLock

Synchronized 属于独占式悲观锁,是通过 JVM 隐式实现的,synchronized 只允许同一时刻只有一个线程操作资源。
在 Java 中每个对象都隐式包含一个 monitor(监视器)对象,加锁的过程其实就是竞争 monitor 的过程,当线程进入字节码 monitorenter 指令之后,线程将持有 monitor 对象,执行 monitorexit 时释放 monitor 对象,当其他线程没有拿到 monitor 对象时,则需要阻塞等待获取该对象。

ReentrantLock 是 Lock 的默认实现方式之一,它是基于 AQS(Abstract Queued Synchronizer,队列同步器)实现的,它默认是通过非公平锁实现的,在它的内部有一个 state 的状态字段用于表示锁是否被占用,如果是 0 则表示锁未被占用,此时线程就可以把 state 改为 1,并成功获得锁,而其他未获得锁的线程只能去排队等待获取锁资源。

synchronized 是 JVM 隐式实现的,而 ReentrantLock 是 Java 语言提供的 API;
ReentrantLock 可设置为公平锁,而 synchronized 却不行;
ReentrantLock 只能修饰代码块,而 synchronized 可以用于修饰方法、修饰代码块等;
ReentrantLock 需要手动加锁和释放锁,如果忘记释放锁,则会造成资源被永久占用,而 synchronized 无需手动释放锁;
ReentrantLock 可以知道是否成功获得了锁,而 synchronized 却不行。

ReentrantLock 支持中断、超时中断(毕竟是API嘛)

Synchronized锁升级

缓存

LRU&LFU

LRU:Least Recently Used,最近最少使用
LFU:Least Frequently Used,最近不常被使用

LRU 算法有一个缺点,比如说很久没有使用的一个键值,如果最近被访问了一次,那么即使它是使用次数最少的缓存,它也不会被淘汰;而 LFU 算法解决了偶尔被访问一次之后,数据就不会被淘汰的问题,它是根据总访问次数来淘汰数据的,其核心思想是”如果数据过去被访问多次,那么将来它被访问次数也会比较多”。因此 LFU 可以理解为比 LRU 更加合理的淘汰算法。

缓存常见过期策略

  • 定时删除、惰性删除、定期删除

定时删除是指在设置键值的过期时间时,创建一个定时事件,当到达过期时间后,事件处理器会执行删除过期键的操作。它的优点是可以及时的释放内存空间,缺点是需要开启多个延迟执行事件来处理清除任务,这样就会造成大量任务事件堆积,占用了很多系统资源。

惰性删除不会主动删除过期键,而是在每次请求时才会判断此值是否过期,如果过期则删除键值,否则就返回正常值。它的优点是只会占用少量的系统资源,缺点是清除不够及时,会造成一定的空间浪费。

定期删除是指每隔一段时间检查一次数据库,随机删除一些过期键值。

Redis

过期策略,Redis是如何处理过期数据的?

  • 惰性删除
  • 定期删除 (注:Redis 服务器为了保证过期删除策略不会导致线程卡死,会给过期扫描增加了最大执行时间为 25ms。)

内存淘汰策略,当内存不够用时,Redis是如何处理的?

  • noeviction:不淘汰任何数据,当内存不足时,执行缓存新增操作会报错,它是 Redis 默认内存淘汰策略。
  • allkeys-lru:淘汰整个键值中最久未使用的键值。
  • allkeys-random:随机淘汰任意键值。
  • volatile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值。
  • volatile-random:随机淘汰设置了过期时间的任意键值。
  • volatile-ttl:优先淘汰更早过期的键值。
    Redis4.0增加了两种策略
  • volatile-lfu,淘汰所有设置了过期时间的键值中最少使用的键值;
  • allkeys-lfu,淘汰整个键值中最少使用的键值。

这个内存淘汰策略我们可以通过配置文件来修改,redis.conf 对应的配置项是”maxmemory-policy noeviction”,只需要把它修改成我们需要设置的类型即可。

Redis实现分布式锁

SETNX

  • 锁误删 : 借助LUA脚本, 判断VALUE中的字符串(存线程UUID),是否是当前线程,如果是则能删除锁
  • 锁超时:
  • 把执行耗时的方法从锁中剔除,减少锁中代码的执行时间,保证锁在超时之前,代码一定可以执行完
  • 把锁超时时间设置的长一些,正常情况下我们在使用完锁之后,会调用删除的方法手动删除锁,因此可以把超时时间设置的稍微长一些
  • 使用Redission的锁续约机制

Redis高可用

  • 数据持久化
  • AOF
  • RDB
  • 主从数据同步(主从复制)
  • Redis哨兵模式(Sentinel)
  • Redis集群(Cluster)

分布式锁的常见实现方式

  • 基于 MySQL 的悲观锁来实现分布式锁,这种方式使用的最少,因为这种实现方式的性能不好,且容易造成死锁;
  • 基于 Memcached 实现分布式锁,可使用 add 方法来实现,如果添加成功了则表示分布式锁创建成功;
  • 基于 Redis 实现分布式锁,可以使用 setnx 方法来实现;
  • 基于 ZooKeeper 实现分布式锁,利用 ZooKeeper 顺序临时节点来实现。

SpringBean的作用域

  • singleton、prototype、request、session、application

singleton 作用域:表示在 Spring 容器中只有一个 Bean 实例,以单例的形式存在,是默认的 Bean 作用域。
prototype 作用域:原型作用域,每次调用 Bean 时都会创建一个新实例,也就是说每次调用 getBean() 方法时,相当于执行了 new Bean()。
request 作用域:每次 Http 请求时都会创建一个新的 Bean,该作用域仅适应于 WebApplicationContext 环境。
session 作用域:同一个 Http Session 共享一个 Bean 对象,不同的 Session 拥有不同的 Bean 对象,仅适用于 WebApplicationContext 环境。
application 作用域:全局的 Web 作用域,类似于 Servlet 中的 Application。

Memcache和Redis的技术差异

Java基础内容汇总[持续更新]

Java基础内容汇总[持续更新]

MySQL

索引合并

在 MySQL 5.0 之前的版本要尽量避免使用 or 查询,可以使用 union 或者子查询来替代,因为早期的 MySQL 版本使用 or 查询可能会导致索引失效,在 MySQL 5.0 之后的版本中引入了索引合并,简单来说就是把多条件查询,比如 or 或 and 查询的结果集进行合并交集或并集的功能,因此就不会导致索引失效的问题了。

优化

  • 避免在 where 查询条件中使用 != 或者 <> 操作符,因为这些操作符会导致查询引擎放弃索引而进行全表扫描。
  • 要尽量避免使用 select *,而是查询需要的字段,这样可以提升速度,以及减少网络传输的带宽压力。
  • 尽量使用 Join 语句来替代子查询,因为子查询是嵌套查询,而嵌套查询会新创建一张临时表,而临时表的创建与销毁会占用一定的系统资源以及花费一定的时间,但 Join 语句并不会创建临时表,因此性能会更高。
  • 不要在列上进行运算操作

不要在列字段上进行算术运算或其他表达式运算,否则可能会导致查询引擎无法正确使用索引,从而影响了查询的效率。

  • 适当增加冗余字段(空间换时间)

Explain

Explain含义:

Java基础内容汇总[持续更新]
Type字段含义:
Java基础内容汇总[持续更新]

设计模式

六大设计原则

单一职责

开闭原则

里氏替换原则

依赖倒置原则

接口隔离原则

迪米特法则

MyBatis

工厂模式:DefaultSqlSessionFactory

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {

    executorType = executorType == null ? defaultExecutorType : executorType;

    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;

    Executor executor;

    if (ExecutorType.BATCH == executorType) {

        executor = new BatchExecutor(this, transaction);

    } else if (ExecutorType.REUSE == executorType) {

        executor = new ReuseExecutor(this, transaction);

    } else {

        executor = new SimpleExecutor(this, transaction);

    }

    if (cacheEnabled) {

        executor = new CachingExecutor(executor);

    }

    executor = (Executor) interceptorChain.pluginAll(executor);

    return executor;

}

建造者模式:SqlSessionFactoryBuilder (笔者认为虽然从类名上看是建造者模式,但是它整体思路并不符合建造者模式,所以笔者不认为它是建造者模式)

单例模式:ErrorContext

ErrorContext 是线程级别的的单例,每个线程中有一个此对象的单例,用于记录该线程的执行环境的错误信息。

public class ErrorContext {

  private static final String LINE_SEPARATOR = System.lineSeparator();

  // 每个线程存储的容器

  private static final ThreadLocal LOCAL = ThreadLocal.withInitial(ErrorContext::new);

  public static ErrorContext instance() {

    return LOCAL.get();

  }

  // 忽略其他

}

适配器模式:Log

Java基础内容汇总[持续更新]

代理模式:MapperProxyFactory

public class MapperProxyFactory {

  private final Class mapperInterface;

  private final Map methodCache = new ConcurrentHashMap<>();

  public MapperProxyFactory(Class mapperInterface) {

    this.mapperInterface = mapperInterface;

  }

  public Class getMapperInterface() {

    return mapperInterface;

  }

  public Map getMethodCache() {

    return methodCache;

  }

  // 创建代理类

  @SuppressWarnings("unchecked")

  protected T newInstance(MapperProxy mapperProxy) {

    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

  }

  public T newInstance(SqlSession sqlSession) {

    final MapperProxy mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);

    return newInstance(mapperProxy);

  }

}

模板方法模式 :BaseExecutor

Java基础内容汇总[持续更新]

装饰器模式:Cache

Cache 除了有数据存储和缓存的基本功能外(由 PerpetualCache 永久缓存实现),还有其他附加的 Cache 类,比如先进先出的 FifoCache、最近最少使用的 LruCache、防止多线程并发访问的 SynchronizedCache 等众多附加功能的缓存类,Cache 所有实现子类如下图所示:

Java基础内容汇总[持续更新]
更多内容欢迎阅读开源框架是如何使用设计模式的-MyBatis缓存机制之装饰者模式

微服务

Eureka

自我保护机制

默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将注销该实例(默认为90s)。但是当网络分区发生故障时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时不应该注销这个微服务。

Eureka通过”自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

在Spring Cloud中,可以使用eureka.server.enable-self-preservation = false 禁用自我保护模式。

Hystrix

断路器

断路器可以自动诊断依赖的服务是否已经恢复正常。如果发现依赖的服务已经恢复正常,那么就会恢复请求该服务。使用这种方式,就可以实现微服务的 “自我修复”——当依赖的服务不正常时,打开断路器时快速失败,从而防止雪崩效应;当发现依赖的服务恢复正常时,又会恢复请求。

  • 正常情况下,断路器关闭,可正常请求依赖的服务
  • 当一段时间内,请求失败率达到一定阈值(例如错误率达到50%,或100次/分钟等),断路器就会打开。此时,不会再请求依赖的服务。
  • 断路器打开一段时间后,会自动进入”半开”状态。此时,断路器可允许一个请求访问依赖的服务。如果该请求能够调用成功,则关闭断路器;否则继续保持打开状态。

Linux

常用命令

排查问题了解到了zcat命令,以前都是先解压…。发现了个看着不错的网址Linux命令大全

ZCAT

zcat:zcat命令用于不真正解压缩文件,就能显示压缩包中文件的内容的场合。zcat是一个命令行实用程序,用于查看压缩文件的内容,而无需对其进行解压缩。

Original: https://www.cnblogs.com/deepSleeping/p/14987994.html
Author: DeepSleeping丶
Title: Java基础内容汇总[持续更新]

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574533/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring JDBC

    用过JDBC(Java DataBase Connectivity,Java数据库连接)的人都知道,JDBC非常臃肿,一点也不可爱。以致于我们每次使用JDBC操作数据库时,总会忍不…

    Java 2023年6月5日
    067
  • Redis入门与实践(附项目真实案例代码)

    我是3y,一年 CRUD经验用十年的 markdown程序员👨🏻‍💻常年被誉为优质八股文选手 今天继续更新austin项目,如果还没看过该系列的同学可以点开我的历史文章回顾下,在看…

    Java 2023年6月9日
    057
  • [JVM] JVM的类加载机制

    JVM的类加载 首先我们来看下 Java虚拟机的类加载过程: 如上图。 当 JVM需要用到某个类的时候,虚拟机会加载它的 .class 文件。加载了相关的字节码信息之后,会常见对应…

    Java 2023年6月5日
    059
  • lambda表达式和stream流

    lambda表达式 基本格式 (Object o1, Object o2) -> {方法体} o1、o2:方法参数 ->:特定的箭头符号 {…}:方法体内容…

    Java 2023年6月6日
    065
  • Spring Cloud Zuul 过滤器拆分serivceId和请求路径

    由于项目所需,需要在Zuul网关中解析请求URL,将URL中路由服务的部分和真实请求路径分离开。 localhost:8080/serviceA/api/xxx –&g…

    Java 2023年6月5日
    059
  • Mybatis基本流程及配置文件解析

    Mybatis基本流程 1、利用Resources工具类加载配置文件,并转换成输入输出流 2、利用解析的配置,创建SqlSessionFactory工厂 3、生产SqlSessio…

    Java 2023年6月5日
    074
  • java中的枚举

    java;gutter:true; class Weather { public static void main(String[] args) { //打印自定义枚举常量 Sys…

    Java 2023年6月6日
    087
  • 给IDEA道个歉,这不是它的BUG,而是反编译插件的BUG。

    你好呀,我是歪歪。 主要描述了在 IDEA 里面反编译后的 class 文件中有这样的代码片段: 很明显,这玩意就是一个语法错误。 但是当我用其他的编译器打开之后,显示又是正常的。…

    Java 2023年6月5日
    057
  • Java基础-续1

    方法 概念 在JS中,我们把方法称之为函数。在java我们称之为方法。 方法就是一个黑匣子。我们不需要知道内部是如何执行的,只要按照要求调用,就能完成必要的功能。 方法申明的语法:…

    Java 2023年6月7日
    057
  • SQL的一种写法,匹配就更新,否则就是插入

    语法:(using里面可以是查询语句,也可以是dao层传入来的对象,集合) 例子 (mybatis写法,dao层传入来的集合对象) 解析: Original: https://ww…

    Java 2023年6月9日
    069
  • Mybatis源码解读-插件

    注册 xml方式的注册,是在XMLConfigBuilder#pluginElement完成的。 不明觉厉的同学,请参考上一篇文章:Mybatis源码解读-配置加载和Mapper的…

    Java 2023年6月16日
    0103
  • VSCode打字特效Power Mode插件

    由于最近比较频繁使用VSCode这个软件写代码,然后里面有一个非常炫酷的打字特效插件,平时写代码的时候不会感觉太枯燥(其实就是装一下逼吧)! 安装很简单,但是容易忘,所以这里整理一…

    Java 2023年6月5日
    075
  • maven中profiles使用详解

    使用的场景 常常遇到一些项目中多环境切换的问题。比如在开发过程中用到开发环境,在测试中使用测试环境,在生产中用生产环境的情况。springboot中提供了 spring.profi…

    Java 2023年6月7日
    092
  • 单元测试、反射、注解、动态代理

    单元测试JUnit 单元测试的目的是针对方法进行测试, JUnit的两个要点:①必须是公开的,无参数,无返回值的方法 ②测试方法必须使用@Test注解标记 public class…

    Java 2023年6月9日
    060
  • mybatis-plus忽略映射字段

    mybatis-plus使用对象属性进行SQL操作,经常会出现对象属性非表字段的情况,忽略映射字段使用以下注解: @TableField(exist = false):表示该属性不…

    Java 2023年5月30日
    060
  • 使用Docker快速安装Redis

    1、使用docker命令下一个redis的镜像 docker pull redis 2、创建 redis 的 data 目录和 conf 目录 1. cd /home/fengsi…

    Java 2023年6月9日
    087
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球