JVM调参实践总结

JVM调优–理论篇从理论层面介绍了如何对JVM调优。这里再写一篇WIKI,尝试记录下JVM参数使用的最佳实践,注意,这里重点介绍HotSpot VM的调参,其他JVM的调参可以类比,但不可照搬。

Java版本选择

基于Java开发应用时,第一个要考虑的问题,就是Java版本的选择。一般情况下,一个团队或一个组织使用相同的Java版本。由于现在Java版本的发布周期是半年一个版本,所以在实际应用中应选择发行版本,目前支持的发行版本有Java 11、Java 17、Java 21。当然,很大一部分厂商使用Java 8。尽管Java官方目前已不在直接支持Java 8的发行版本,但是Java 8因其广泛且长久的使用,已经非常稳定,且部分有能力的厂商还在维护Java 8,所以Java 8也是一个不错的选择。更多Java版本信息可以参考官网。注意,Java提供的版本均是收费版本,如果需要获取免费版本,可以获取OpenJDK。OpenJDK是Java语言的一个开源实现,OpenJDK采用GPL协议,主要组件包括Hotspot JVM、Java核心类库和javac编译器。OpenJDK具有开源免费、跨平台、高性能和多版本支持等特点,适用于Java应用程序开发、桌面应用程序等多种场景。可以从adoptium网站获取已编译的OpenJDK版本。

JVM类型选择

Java提供了Java Language and Virtual Machine Specifications,约定了JVM的实现细节,这样不同的厂商可以实现自己的JVM。目前,主流的JVM有:HotSpot VM、IBM JVM、Open JDK、GraalVM等。在选用JVM类型时,根据稳定性、高性能、安全性、可维护性、费用等方面组合考虑。如在Java 8中,通常使用Oracle的HotSpot JVM。如果期望使用免费版本,可以选择Open JDK。

JVM部署平台相关选择

JVM部署时,是选择32位JVM,还是64位JVM。HotSpot VM默认的执行位数取决于所安装的JDK版本和操作系统。在32位操作系统上,只能运行32位的JDK,因此HotSpot虚拟机也只能在32位模式下执行。而在64位操作系统上,可以选择安装32位或64位的JDK。如果安装了64位的JDK,那么HotSpot虚拟机将默认在64位模式下执行。推荐在64位操作上安装64位的JDK版本。注意,不同操作系统上,对应的版本不同,所以在选择JVM位数的同时,也要注意选择和待部署操作系统向匹配的版本。此外,针对不同的CPU架构,JVM的版本也不尽相同。在选择JVM执行位数时,还应考虑CPU架构。

JVM部署模式选择

JVM部署模式指的是将应用部署到单个JVM实例上,还是部署多个JVM实例上。目前应用的主流架构是微服务架构。对一个应用来说,常常需要拆分成多个独立的微服务。对于每个微服务来说,为了保证其高可用,通常需要多个实例。所以,对于一个大型的应用来说,是将其拆分成微服务单独部署。而对一个微服务,会对应多个服务实例,且每个每个服务部署在隔离的环境中,如Kubernetes的Pod中。JVM部署模式是架构层面需要考虑的事情,针对一个Java进程来说,无需考虑。

JVM运行模式

为Java应用选择JVM运行模式,就是指定以何种方式运行JVM,可选项有:client模式、server模式和混合模式。注意,混合模式是在Java 7及之后的版本才引入。推荐使用混合模式,这也是Java 8及之后的版本默认的运行模式。该模式可以很好地融合client模式和Server模式的主要特征。如无特殊说明,使用混合模式即可,除非有明确诉求需要使用client模式或server模式。选用server模式启动JVM的示例命令如下:

java -server -jar hello-world.jar

上述示例命令中,使用server模式启动了一个hello-world的Java应用。

垃圾收集器选择

JVM的一个重要职责是实现内存的自动化管理。而实现内存的自动化管理的关键就是垃圾收集器。垃圾收集主要关注的性能属性有:吞吐量、延迟、内存占用。其中:
(1) 吞吐量:是评价垃圾收集器能力的重要指标之一,指不考虑垃圾收集引起的停顿时间或内存消耗,垃圾收集器能支撑应用达到的最高性能指标。
(2) 延迟:也是评价垃圾收集器能力的重要指标,度量标准是缩短由于垃圾收集引起的停顿时间或完全消除因垃圾收集所引起的停顿,避免应用运行时发生抖动。
(3) 内存占用:垃圾收集器流畅运行所需要的内存数量。
这其中任何一个属性性能的提高几乎都是以另一个或两个属性性能的损失作代价的。换句话说,某一个属性上的性能提高总是牺牲另一个或两个属性。然而,对大多数应用来说,极少出现这三个属性的重要程度都同等的情况。很多时候,某一个或两个属性的性能要比另一个重要。哪个属性最重要,并将其映射到应用的系统需求,对应用而言非常重要。
同一个JVM中,可能包含多种垃圾收集器实现。在选择垃圾收集器时,要根据应用的需求,进行一个初步的选择。在HotSpot VM中,如果应用对停顿时间要求较为严格(即不希望因为垃圾收集而导致过多的暂停),那么可能需要选择那些停顿时间较短的垃圾收集器,如CMS收集器或G1收集器。相反,如果应用对停顿时间要求不那么严格,可以考虑使用串行收集器或并行收集器,它们在垃圾收集时可能会暂停所有工作线程。如果对较小的堆或较低配置的硬件,可能更适合使用简单的串行收集器或者并行收集器。对于大内存堆和多核CPU的环境,可以考虑使用G1等垃圾收集器,它们更适合大规模的堆和高配置的硬件。垃圾收集器的选择,要根据业务的特征,进行充分的测试。初步选择后,如果经过测试后,并不能达到预期,则要考虑换用垃圾收集器,并重新进行测试。
在进行垃圾收集验证时,一般从默认垃圾收集器开始。Java 8默认的垃圾收集器是Parallel Scavenge和Parallel Old。这是Oracle JDK 8中的默认设置,适用于大多数应用程序场景。但在某些特定场景下,可能需要选择其他更适合的垃圾收集器,如CMS收集器或G1收集器。指定CMS收集器或G1收集器的示例命令如下:

# 指定使用CMS垃圾收集器
java -XX:+UseConcMarkSweepGC hello-world.jar
# 指定使用G1垃圾收集器
java -XX:+UseG1GC -jar hello-world.jar

CMS收集器在Java 9之后已被标记为废弃(deprecated),并在后续的Java版本中被移除。因此,如果正在使用Java 9或更高版本,并且希望使用类似的低延迟垃圾收集器,应该考虑使用G1(Garbage-First)收集器,它是Java 9之后的默认收集器,并且也旨在提供可预测的停顿时间。G1收集器在Java 9及更高版本中通常是一个更好的选择,因为它提供了更好的性能和更灵活的垃圾收集配置选项。不过,具体的选择应该基于你的应用程序的需求和性能目标。

垃圾收集器的进一步优化

不同的垃圾收集器还提供了一系列参数,帮助进一步对垃圾收集器进行调优。这里以G1收集器为例,介绍下常用的调优命令。

java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar hello-world.jar

-XX:MaxGCPauseMillis参数用来设置垃圾收集的最大暂停时间,这样垃圾收集对延迟或响应的影响就变得可控。

垃圾收集报告

监控JVM的垃圾收集非常重要,因为垃圾收集对应用的吞吐量和延迟都有着深刻的影响。HotSpot VM报告垃圾收集数据几乎没有什么额外开销,推荐在测试环境启用该配置,但不建议在生产环境中使用。生成垃圾收集统计数据的命令行如下:

# Java 8及更早版本启用记录详细的GC日志
java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log -jar hello-world.jar
# Java 9及更高版本启用记录详细的GC日志
java -Xlog:gc*:file=gc.log -jar hello-world.jar

上述命令中,-XX:PrintGCDetails参数用来打印比-verbose:gc参数更多有价值的垃圾收集信息。注意,在生产环境中启用-verbose:gc或-XX:PrintGCDetails参数,或其他详细的GC日志可能会产生大量的输出,这可能会对应用程序的性能产生轻微的影响。因此,通常建议仅在开发和测试阶段使用这些参数,以便在必要时进行调优和分析。此外,-XX:PrintGCDetails参数打印的日志包含时间戳前缀,这个时间是自JVM启动以来的秒数。为了生成标准时间戳,形如YYYY-MM-DD-T-HH-MM-SS.mmm-TZ,可以补充-XX:PrintGCDateStamps参数。为了更好的分析垃圾收集器的统计数据,还可以使用-Xloggc:<filename>将垃圾收集的统计数据直接输出到文件(filename是保存的文件名)。离线分析可以处理时间范围更广的垃圾收集数据,查找问题时也不会直接影响线上应用。
在Java 9及更高的版本,使用新的日志系统,称为统一日志记录(Unified Logging),它使用-Xlog参数来配置各种日志,包括垃圾收集(GC)日志。-Xlog:gc是启用与垃圾收集相关的所有日志条目的快捷方式。其中,gc:file=<filename>是指将GC日志输出到指定的文件中。

应用GC停止时间和应用GC并发时间

使用-XX:+PrintGCApplicationConcurrentTime和-XX:PrintGCApplicationStoppedTime,HotSpot VM可以报告应用在安全点操作之间的运行时间,以及阻塞Java线程的时间。利用这两个命令行选项观察安全点操作有助于理解和量化延迟对JVM的影响,也可以用来辨别是JVM安全点操作还是应用程序引入的延迟。命令使用示例如下:

java -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -jar hello-world.jar

Java堆调优

HotSpot VM根据对象存活周期的不同,将内存划分三部分:老年代(Tenured Generation)和新生代(Young Generation)、永久代(Permanet Generation)。其中,老年代和新生代组合了堆空间,而永久代则在堆空间之外。在新生代中,存放新分配的对象,在老年代中,存放旧的或长期存活或大的对象,在永久代中,存放JVM加载的类元数据(如类的结构信息、常量池等)、类静态变量,等。在Java 8中,永久代被元空间所取代,元空间使用本地内存,可以动态扩展。HotSpot VM堆布局如下所示:
请添加图片描述

堆大小

-Xmx和-Xms设置堆的初始值和最大值。其中-Xmx设定了初始值及最小值,-Xmx设定了最大值。当-Xms指定的值小于-Xmx的值时,新生代及老年代空间大大小会根据应用的需求动态的扩展或缩减。对于吞吐量和延迟关注的Java应用应将-Xms和-Xmx设定为同一值。这样,就不会因为新生代和老年代空间的动态的扩展或缩减触发Full GC,从而降低应用的吞吐量和更长的延迟。如果-Xms指定的值比-Xmx的值大,那么会导致JVM在启动时就会因为无法满足内存分配要求而失败,并可能抛出一个错误。所以业务环境上,不可能存在-Xms值大于-Xmx值的情况。此外,如果堆的初始值设置过小,可能会导致应用在启动的时候进行扩容,从而延长启动时间。在需要优化启动时间的时候,可以观察启动期间是否有堆扩容动作。
HotSpot VM不指定Java堆的大小时,会根据物理机或虚拟机的物理内存或分配的物理内存的大小来计算默认的堆大小。具体的计算方式可能因JVM版本和操作系统而略有不同,但大致遵循如下规则:
(2) 对于64位JVM,默认的堆大小会根据物理内存的大小来计算。在物理内存小于192MB时,JVM的初始和最大堆大小通常为物理内存的一半。当物理内存大于192MB但小于1GB时,JVM的最大堆大小通常为物理内存的1/4。而当物理内存大于或等于1GB时,JVM的最大堆大小可能会根据JVM版本和操作系统的不同而有所变化,但通常会限制在一个合理的范围内,以避免过度消耗系统资源。
一般情况下,默认的堆大小不能够充分的利用物理内存,所以均需要手动设置JVM的堆大小。通常建议将JVM的最大堆大小设置为物理内存的1/4至1/2之间,但这只是一个大致的指导原则,具体设置需要根据实际情况进行调整。JVM除了堆空间会占用内存,栈空间、系统其他资源也会消耗内存,所以不建议把JVM的堆设置过大。应该在保证系统正常运行、满足业务需要、充分测试等前提下,合理设置JVM的堆大小。不建议JVM的堆最大值大于物理内存的80%。举例来说,对于物理内存为2GB的环境来说,如果当前环境,主要的业务进程就是Java应用,那么预留400MB的空间已经足够其他对象或进程使用,在经过充分测试后,可以设置Java堆的最大值为1600MB。
设置堆大小的示例命令如下:

java -Xmx1g -Xms512m -jar hello-world.jar

上述命令中,设置堆的最小值为512MB,堆的最大值为1GB。

新生代

在调优延迟或响应时间时,Minor GC的持续时间会影响应用的平均停滞时间,Minor GC的执行频率会影响平均停滞的发生频率。根据垃圾收集的统计数据、Minor GC的持续时间和频率可以确定新生代空间的大小。Minor GC需要的时间与新生代中可访问的对象数直接相关。通常情况下,新生代空间越小,Minor GC持续的时间越短。不考虑这对于Minor GC持续时间的影响,减少新生代空间又会增大Minor GC的频率。这是因为以同样的对象分配频率,较小的新生代空间在很短时间内就会被填满,增大新生代空间可以减少Minor GC的频率。
分析GC数据时,如果发现Minor GC的间隔时间较长,修正的方法是减少新生代空间。如果Minor GC频率太高,修正的方法是增加新生代空间。
计算平均持续时间和频率时,Minor GC的次数越多,平均持续时间及频率的统计也就越准确。另外,使用应用运行于稳定阶段时的Minor GC的值也是非常重要的。
调整新生代的示例命令如下:

# 新生代固定为256MB
java -Xms512m -Xmx1024m -Xmn256m -jar hello-world.jar
# 新生代动态调整,且最小值为128MB,最大值为256MB
java -Xms512m -Xmx1024m -XX:NewSize=128m -XX:MaxNewSize=256m -jar hello-world.jar
# 新生代固定比例,NewRatio=3,表示新生代和老年代的大小比例就是1:3,也即新生代占1/4
java -Xms512m -Xmx1024m -XX:NewRatio=3 -jar hello-world.jar

HotSpot VM中,支持同时设置-Xmn以及-XX:NewSize或-XX:MaxNewSize以及-XX:NewRatio。-Xmn的优先级最高,其次是-XX:NewSize、-XX:MaxNewSize,最后是-XX:NewRatio。注意,不建议同时使用功能有重叠的命令,这会给后面的维护带来不必要的误导。推荐使用-Xmn给新生代设置一个固定的大小。

老年代

在调优延迟或响应时间时,Full GC的持续时间会影响应用的最大停顿时间,Full GC的执行频率会影响应用的最大停滞发生的频率。发生于稳定态的Full GC的持续时间是应用的最差Full GC停顿时间。如果多个Full GC在稳定态发生,就按平均最差停顿时间计算。取样的数据越多,预测的结果越准确。
从老年代中减去活跃数据的大小可以得到可用老年代空间大小。需要多长时间才能填满老年代的空闲空间取决于新生代到老年代的提升率。提升率可以依据老年代空间占用的增长量以及每次Minor GC后新生代的空间占用计算得出。老年代的空间占用情况可以通过Minor GC之后Java堆的占用情况减去同一次Minor GC后新生代的空间占用得到。
如果预期或观测到Full GC的频率已经远不能达到应用的最差Full GC频率要求,就应该增大老年代空间的大小。这个方法可以帮助降低Full GC的评率。增大老年代空间时,注意保持新生代空间大小恒定。
如果修改老年代空间大小后,只观察到Full GC,很可能是老年代与新生代空间大小失去了平衡,导致应用只进行Full GC。这一情况通常源于即使老年代经过Full GC,仍不足以容纳所有从新生代提升的对象。标识老年代空间不够大的一个线索是每次Full GC之后,老年代几乎没有任何空间被回收,而新生代总有大量的对象占用空间。当老年代没有足够的空间接纳从新生代提升的对象时,这些对象机会被"退还"到新生代空间中。
JVM不支持直接调整老年代的大小,而是通过Java堆大小减去新生代的大小,间接的计算出老年代的大小。这里不在补充命令示例。

永久代或元空间

永久代用来存放JVM加载的类元数据(如类的结构信息、常量池等)、类静态变量,等。在Java 8及更高的版本中,永久代被元空间所取代,元空间使用本地内存,可以动态扩展。永久代空间大小设置示例命令如下:

java -XX:PermSize=64m -XX:MaxPermSize=256m -jar hello-world.jar

为了解决永久代的大小是有限的问题,Java 8引入了元空间。元空间使用本地内存(native memory)来存储类的元数据,其大小可以根据需要进行动态调整。这大大减少了类加载过程中的内存限制,并提高了应用程序的灵活性。元空间大小设置示例命令如下:

java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -jar hello-world.jar

默认情况下,元空间的大小是没有上限的,即它的大小受限于机器的物理内存。然而,为了避免因元空间无限增长而导致的内存溢出问题,需要设置一个合理的最大值。

调整Survivor空间的容量

调整Survivor空间容量一个应该谨记于心的重要原则:调整Survivor空间容量时,如果新生代空间不变,增大Survivor空间会减少Eden空间;而减少Eden空间会增加Minor GC的频率。因此,为了同时满足应用Minor GC频率的要求,就需要增大当前新生代的空间;即增大Survivor空间大小时,Eden空间的大小应保持不变。如果可以增大Minor GC的频率,则可以选择用一部分Eden空间来增大Survivor空间。如果内存足够,相对于减少Eden空间,增大新生代大小通常是更好的选择。保持Eden空间不变,Minor GC的频率就不会因为Survivor空间增大而发生变化。再次提醒,减少Eden空间会导致更频繁的Minor GC。因为调整Survivor空间是通过增加新生代实现,所以可以参考新生代的调整命令。此外,如果需要调整新生代中Eden和Survivor的比例,可以使用如下的示例命令:

java -Xms1024m -Xmx1024m -Xmn256m -XX:SurvivorRatio=8 -jar hello-world.jar

上述示例中,SurvivorRatio参数决定了Eden区与单个Survivor区之间的大小比例。这里设置SurvivorRatio为8,所以Eden区的大小将是单个Survivor区大小的8倍。
调整SurvivorRatio的值时,重点关注Survivor值缩小的场景。尽管调大Survivor空间会带来不必要的资源浪费,但是执行调大操作时,基本上都是发现Survivor不足时才去调大。所以应重点关注Survivor空间过小的场景。如果Survivor区太小,可能会导致对象在Survivor区之间频繁地复制(即Survivor溢出到老年代),这可能会增加Minor GC的频率和持续时间,并可能导致不必要的对象晋升到老年代。

调整晋升阈值

HotSpot VM在每次Minor GC时,都会计算晋升阈值以决定何时对一个对象进行提升。或者说,晋升阈值就是对象的年龄。一个对象的年龄就是它所经历的Minor GC次数。对象首次分配时,其年龄是0。下一次Minor GC之后,如果该对象还在新生代,其年龄加一,以此类推。新生代中年龄大于HotSpot VM计算出的晋升阈值的对象被提升到老年代。晋升阈值计算的依据是Minor GC之后新生代要容纳的可达对象需要的空间大小及目标Survivor空间占用的空间大小(如果Survivor空间过小,一次Minor GC可能会导致Survivor溢出,溢出的对象将直接提升到老年代)。可以使用-XX:MaxTenuringThreshold=<n>指定在对象年龄超过阈值后,将其提升到老年代。在Open JDK的版本中,MaxTenuringThreshold的默认值是15。但是,这个默认值可能会在不同的JVM实现或版本中有所不同。可以使用-XX:+PrintTenuringDistribution选项来启动JVM。这个选项会在每次Minor GC之后打印出Survivor区中对象的年龄分布信息,同时也会显示当前的MaxTenuringThreshold设置值。晋升阈值示例命令如下:

java -Xms1024m -Xmx1024m -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution -jar hello-world.jar

不建议将晋升阈值设置过小,这会导致最近分配的对象很快提升到老年代,同时造成老年代空间的迅速增大,引起频繁的Full GC。同时,也不建议将晋升阈值设置为远大于实际可能的最大值。这会造成对象长期存在于Survivor空间,直到最后溢出。一旦溢出,对象将会被全部提升到老年代,从而造成短期存在对象在长期存在对象之前被提升到老年代,严重影响对象老化机制的有效性。

禁用显式的垃圾收集

Java提供System.gc()接口,这样开发人员就可显式地出发垃圾收集。注意,这个方法并不会直接执行垃圾回收,而是向JVM发出一个建议,让JVM尝试回收不再使用的对象以释放内存。所以,调用System.gc()并不保证垃圾回收会立即执行,因为JVM有自己的垃圾回收策略和调度机制。JVM会根据其内部的算法和当前的系统状态来决定何时执行垃圾回收。
可以使用-XX:+DisableExplicitGC命令行选项通知HotSpot VM忽略显式的System.gc()调用。示例命令如下:

java -XX:+DisableExplicitGC -jar hello-world.jar

禁用显式的垃圾收集时应该慎重,它可能会对应用的性能造成较大的影响。还有可能出现这样场景,开发人员需要及时的对对象引用做处理,但与之对应的是垃圾收集却跟不上其节奏。建议除非有非常明确的理由,否则不要轻易地禁用显式的垃圾收集。与此同时,也建议只有在明确理由下才能在应用中使用System.gc()。
注意,禁用了System.gc(),JVM仍然会根据其内部算法和需要自动进行垃圾回收。这个参数只是禁用了对垃圾回收的显式请求,而不是禁用垃圾回收机制。

Java线程调优

Java是多线程语言,天然支持多线程处理。在进行多线程处理时,会遇到线程的堆栈大小不符合业务需求、线程竞争等问题。

Java线程的栈大小

对于运行在线程栈上的线程来说,会遇到栈溢出(StackOverflowError)的问题。除了死循环导致的栈溢出外,还有一种情况是线程栈过小,不符合业务的需求(递归深度或大量局部变量)。调整线程栈大小的示例命令如下:

java -Xss512k -jar hello-world.jar

Xss参数用来指定每个线程的虚拟机栈大小,直接影响线程虚拟机栈的栈帧数量,即方法调用的层级深度。Xss参数指定的大小理论上会影响JVM能够生成的最大线程数量,但实际上这个数量更多地受到操作系统的最大线程数配置、物理内存大小等因素的限制。不同Java版本中,Xss的默认值不同。

Java线程间锁竞争

Java支持多线程编程,对于多线程来说,无法保证线程之间不存在锁竞争或死锁等问题。在进行Java应用调优时,如果是多线程应用,且测试的场景使用到了多线程和锁,则有必要监控线程信息。可以使用JDK的jstack工具或主流的Java应用分析工具(如Arthas)抓取线程转储信息。
Java线程间锁竞争虽然不属于JVM调优范畴,但是和JVM架构息息相关,这里作为拓展内容做简单地讨论。

参考

《Java性能优化权威指南》 Charlie Hunt, Binu John 著, 柳飞, 陆明刚 译
https://segmentfault.com/a/1190000044547802 JVM 8 调优指南:如何进行JVM调优,JVM调优参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/597816.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面向新手在无人机竞速场景下的飞行辅助系统——浙大 FAST-Lab 高飞团队 ICRA 论文三项 Best Paper 入围

恭喜浙江大学 FAST-Lab 钟宇航同学的论文 A Trajectory-based Flight Assistive System for Novice Pilots in Drone Racing Scenario 顺利发表 ICRA 2024&#xff0c;并同时入选三项 Finalist&#xff1a; the IEEE ICRA Best Conference Paper Awardthe IEEE ICRA Best Pape…

干货!Kali Linux命令大全(建议收藏)

系统信息 arch 显示机器的处理器架构 name -m 显示机器的处理器架构 name -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 -(SMBIOS/DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT /dev/sda 在磁盘上执行测试读取操作 cat /proc/cpuinfo …

[综合应用]dns nfs httpd php mysql

第一步&#xff1a;搭建三台主机 主机名称 Ip地址 角色 503A 192.168.68.10 Mysql从 503B 192.168.68.11 Mysql从&#xff0c;nfs服务端&#xff0c;dns服务端 503Cmysql 192.168.68.12 MySQL主&#xff0c;web客户端 第二步&#xff1a;在503B上配置DNS 2.1 下载…

【3dmax笔记】027:配置修改器集、工具栏自定义与加载

文章目录 一、配置修改器集二、自定义工具栏三、加载工具栏 一、配置修改器集 可以把自己常用的修改命令放到右边框中的部分&#xff0c;便于自己的操作&#xff0c;省去了每次都要花半天时间找命令的尴尬。新建一个二维或者三维物体&#xff0c;点击修改面板&#xff0c;点击…

三分钟了解计算机网络核心概念-数据链路层和物理层

计算机网络数据链路层和物理层 节点&#xff1a;一般指链路层协议中的设备。 链路&#xff1a;一般把沿着通信路径连接相邻节点的通信信道称为链路。 MAC 协议&#xff1a;媒体访问控制协议&#xff0c;它规定了帧在链路上传输的规则。 奇偶校验位&#xff1a;一种差错检测方…

【含win+Mac整合包】本地部署Stable Diffusion,超详细(AI 绘画保姆级教程,100%成功部署)

什么是stable diffusion? stable diffusion是在2022年发布的基于扩散模型的文本到图像生成模型&#xff0c;起初它只有一堆api供开发者使用&#xff0c;可以说非常难上手&#xff0c;随着2023年5月由AUTOMATIC1111大佬基于SD API开发的SD WebUI的发布&#xff0c;SD第一次有了…

C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【运维自动化-配置平台】如何对主机进行纳管

主机是配置平台管控最常见的资源&#xff0c;也是运维日常主要的管控对象&#xff1b;如何对主机进行全生命周期管理呢导入主机 直接导入 直接导入仅适用于直连区域&#xff08;default area&#xff09;的主机&#xff0c;也就是网络跟蓝鲸平台能内网互通的。 资源–>主…

西奥机电食品质构分析仪:揭秘水果蔬菜硬度等指标的测试原理

西奥机电食品质构分析仪&#xff1a;揭秘水果蔬菜硬度等指标的测试原理 在食品科学领域&#xff0c;对水果蔬菜硬度的精准测量是评估其品质与口感的重要步骤。西奥机电食品质构分析仪凭借其先进的技术和独特的测试原理&#xff0c;为这一领域带来了革命性的变革。下面&#xf…

非标类型导致Dubbo接口出入参异常的本质 | 得物技术

一、概述 笔者支持过程中多次发现诡异的Dubbo接口异常问题&#xff0c;抓耳挠腮最后定位到代码上和代码外的原因&#xff0c;事后只感觉脑瓜子嗡嗡的。考虑到这不是第一次&#xff0c;也绝不会是最后一次出现类似问题&#xff0c;下面笔者将尽可能详细的梳理、总结一下该问题的…

6个月小猫成长必备!福派斯无麸质幼猫粮评测

你知道吗&#xff1f;给小猫选择适合的猫粮是一件非常不容易但很重要的事情。那么&#xff0c;对于6个月大的小猫来说&#xff0c;什么样的猫粮是最适合它们的呢&#xff1f;&#x1f431; 我们首先要考虑的是猫粮的营养成分。6个月大的小猫正处于快速生长期&#xff0c;所以需…

vue3 + ts实现canvas绘制的waterfall

实际运行效果(仅包含waterfall图表部分) component.vue <template><div ref="heatmap" :style="{ height: props.containerHeight + px }" /> </template><script setup> import ColorMap from "colormap"; import…

Labels and Databases for Mac:强大的标签与数据库管理工具

Labels and Databases for Mac是一款集标签制作与数据库管理于一体的强大工具&#xff0c;专为Mac用户打造&#xff0c;旨在提供高效、便捷的标签制作与数据管理体验。 这款软件拥有丰富的内置标签格式&#xff0c;用户可轻松创建各种标签、信封和卡片&#xff0c;满足个性化需…

掌控网络流量,优化网络性能 - AnaTraf网络流量分析仪登场

在当今日新月异的网络环境中,网络流量监控和性能诊断已成为企业IT部门不可或缺的重要工作。只有充分了解网络流量状况,才能有效优化网络性能,提高业务运营效率。针对这一需求,全新推出的AnaTraf网络流量分析仪应运而生,为企业提供全面的网络监控和性能诊断解决方案。 快速定位…

Java双亲委派机制

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 概述 Java程序在运…

pygame实现鼠标绘制并调节画笔大小

pygame实现鼠标绘制并调节画笔大小 pygame介绍调节画笔大小鼠标绘制效果 pygame介绍 Pygame是一个开源的Python库&#xff0c;专为电子游戏开发而设计。它建立在SDL&#xff08;Simple DirectMedia Layer&#xff09;的基础上&#xff0c;允许开发者使用Python这种高级语言来实…

C语言趣味代码(五)

我想以此篇结束关于C语言的博客&#xff0c;因为在C语言拖得越久越不能给大家带来新的创作&#xff0c;在此我也相信大家对C语言已经有了一个新的认知。进入正题&#xff0c;在这一篇中我主要编一个“英语单词练习小程序”来给大家展开介绍&#xff0c;从测试版逐步改良&#x…

数据结构——图的基础知识与其表示

一&#xff1a;定义 由顶点的集合和边的集合组成&#xff1b;常以 G(V,E) 表示&#xff0c;G 代表图&#xff0c;V代表 顶点的集合&#xff0c;E代表边的集合&#xff1b; 如图&#xff1a; 在G1图中&#xff0c;有 0~4 五个顶点&#xff0c;有 0-1&#xff0c;0-2&…

专题五_位运算(2)

目录 面试题 01.01. 判定字符是否唯一 解析 题解 268. 丢失的数字 解析 题解 371. 两整数之和 解析 题解 面试题 01.01. 判定字符是否唯一 面试题 01.01. 判定字符是否唯一 - 力扣&#xff08;LeetCode&#xff09; 解析 题解 class Solution { public:bool isUnique…

Ubuntu上使用audit2allow解决Android Selinux问题

1.安装工具 sudo apt install policycoreutils 2.运行命令 提前用dmesg或者串口抓取kernel log 遇到错误&#xff0c;提示需要用-p指定policy file&#xff0c;然偶尝试创建一个policy空文件&#xff0c;用-p选项&#xff0c;遇到如下错误 3.规避问题 首先跟进错误log的堆栈…