后端接口性能优化分析-问题发现问题定义

  • 👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家
  • 📕系列专栏:Spring源码、JUC源码
  • 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
  • 🍂博主正在努力完成2023计划中:源码溯源,一探究竟
  • 📝联系方式:nhs19990716,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬👀

文章目录

  • 定位问题
    • 1.慢查询日志
    • 2.监控
      • 压测监控核心指标
        • 系统性能指标
          • 交易响应时间
          • 系统处理能力
          • 错误率
        • 资源指标
          • CPU
          • Memory
          • 磁盘吞吐量
          • 网络吞吐量
        • 中间件指标
        • 数据库指标
        • 稳定性指标
        • 可扩展性指标
    • 3.链路追踪
  • 问题排查
    • 1.个别接口响应慢
      • 链路追踪
      • 在链路上打印日志
      • 死锁问题
        • 定位死锁
          • jps
          • jconsole
    • 2.所有接口响应慢
      • CPU占用过高
      • 内存占用过高
      • 磁盘问题
      • 网络问题
      • 垃圾回收
  • 相关优秀博客

定位问题

1.慢查询日志

通常情况下,为了定位sql的性能瓶颈,我们需要开启mysql的慢查询日志。把超过指定时间的sql语句,单独记录下来,方面以后分析和定位问题。

开启慢查询日志需要重点关注三个参数:

  • slow_query_log 慢查询开关
  • slow_query_log_file 慢查询日志存放的路径
  • long_query_time 超过多少秒才会记录日志

通过mysql的set命令可以设置:

set global slow_query_log='ON'; 
set global slow_query_log_file='/usr/local/mysql/data/slow.log';
set global long_query_time=2;

设置完之后,如果某条sql的执行时间超过了2秒,会被自动记录到slow.log文件中。

当然也可以直接修改配置文件my.cnf

[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 2

但这种方式需要重启mysql服务。

2.监控

可观测性帮助企业在复杂的分布式系统中更加快速的排查、定位问题,已经是分布式系统中必不可少的运维工具。

可观测性从传统监控场景不断延伸,逐渐覆盖 Metrics、Traces、Logs 三个维度并将之相互融合。在性能压测领域中,可观测性更为重要,除了有助于定位性能问题,其中 Metrics 性能指标更直接决定了压测是否通过,系统最终是否可以上线,具体如下:

  • Metrics - 监控指标

系统性能指标,包括请求成功率、系统吞吐量、响应时长

资源性能指标,衡量系统软硬件资源使用情况,配合系统性能指标,观察系统资源水位

  • Logs - 日志

施压引擎日志,观察施压引擎是否健康,压测脚本执行是否有报错

采样日志,采样记录API的请求和响应详情,辅助排查压测过程中的一些出错请求的参数是否正常,并通过响应详情,查看完整的错误信息

  • Traces - 分布式链路追踪

用于性能问题诊断阶段,通过追踪请求在系统中的调用链路,定位报错 API 的报错系统和报错堆栈,快速定位性能问题点。

压测监控核心指标

压测过程中,对系统硬件、中间件、数据库资源的监控也很重要,包括系统性能指标、资源指标、中间件指标、数据库指标、前端指标、稳定性指标、批量处理指标、可扩展性指标、可靠性指标等。

系统性能指标
交易响应时间

定义 :响应时间指用户从客户端发起一个请求开始,到客户端接收到从服务器端返回的响应结束,整个过程所耗费的时间。在性能检测中一般以压力发起端至被压测服务器返回处理结果的时间为计量,单位一般为秒或毫秒。平均响应时间指系统稳定运行时间段内,同一交易的平均响应时间。一般而言,交易响应时间均指平均响应时间。

简称 :Response Time: RT

参考标准不同行业不同业务可接受的响应时间是不同的

  • 互联网企业:500 毫秒以下,例如淘宝业务 10 毫秒左右

  • 金融企业:1 秒以下为佳,部分复杂业务 3 秒以下

  • 保险企业:3 秒以下为佳

  • 制造业:5 秒以下为佳

  • 时间窗口:即整个压测过程的时间,不同数据量则时间不一样,例如双 11 和 99 大促,数据量级不一样则时间窗口不同。大数据量的情况下,2 小时内可完成压测

系统处理能力

定义 :系统处理能力是指系统在利用系统硬件平台和软件平台进行信息处理的能力。系统处理能力通过系统每秒钟能够处理的交易数量来评价,是技术测试活动中重要指标

简称一般情况下,用以下指标来度量:

  • HPS(Hits Per Second) :每秒点击次数,单位是次/秒

  • TPS(Transaction per Second):系统每秒处理交易数,单位是笔/秒。

  • QPS(Query per Second):系统每秒处理查询次数,单位是次/秒。对于互联网业务中,如果某些业务有且仅有一个请求连接,那么 TPS=QPS=HPS,一般情况下用 TPS 来衡量整个业务流程,用 QPS 来衡量接口查询次数,用 HPS 来表示对服务器单击请求

标准无论 TPS、QPS、HPS,此指标是衡量系统处理能力非常重要的指标,越大越好,根据经验,一般情况下:

  • 金融行业:1000 TPS~50000 TPS,不包括互联网化的活动

  • 保险行业:100 TPS~100000 TPS,不包括互联网化的活动

  • 制造行业:10 TPS~5000 TPS

  • 互联网电子商务:10000 TPS~1000000 TPS

  • 互联网中型网站:1000 TPS~50000 TPS

  • 互联网小型网站:500 TPS~10000 TPS

错误率

定义 :错误率指系统在负载情况下,失败交易的概率。错误率=(失败交易数/交易总数)×100%。稳定性较好的系统,其错误率应该由超时引起,即为超时率。

标准不同系统对错误率的要求不同,但一般不超出千分之六,即成功率不低于 99.4%

资源指标
CPU

定义 :中央处理器是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Unit)。它的功能主要是解释计算机指令以及处理计算机软件中的数据。

Memory

定义 内存是计算机中重要的部件之一,它是与 CPU 进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大

磁盘吞吐量

定义 磁盘吞吐量是指在无磁盘故障的情况下单位时间内通过磁盘的数据量

网络吞吐量

定义 网络吞吐量是指在无网络故障的情况下单位时间内通过的网络的数据数量。单位为 Byte/s。网络吞吐量指标用于衡量系统对于网络设备或链路传输能力的需求。当网络吞吐量指标接近网络设备或链路最大传输能力时,则需要考虑升级网络设备

中间件指标

在这里插入图片描述

数据库指标

在这里插入图片描述

数据库监控中的命中率通常指的是缓存命中率,它表示在数据库访问中,请求能够从缓存中获取所需数据的比例。换句话说,命中率越高,就意味着数据库查询所需的数据越多地可以从缓存中获取,而不需要去访问磁盘或进行其他昂贵的操作。这通常被认为是一个性能指标,因为高命中率通常意味着更快的响应时间和更好的系统性能。

稳定性指标

定义 :最短稳定时间:系统按照最大容量的 80% 或标准压力(系统的预期日常压力)情况下运行,能够稳定运行的最短时间。一般来说,对于正常工作日(8小时)运行的系统,至少应该能保证系统稳定运行8小时以上。对于 7×24 运行的系统,至少应该能够保证系统稳定运行 24 小时以上。如果系统不能稳定的运行,上线后,随着业务量的增长和长时间运行,将会出现性能下降甚至崩溃的风险

标准

  • TPS 曲线稳定,没有大幅度的波动
  • 各项资源指标没有泄露或异常情况
可扩展性指标

定义 :指应用软件或操作系统以集群方式部署,增加的硬件资源与增加的处理能力之间的关系。计算公式为:(增加性能/原始性能)/(增加资源/原始资源)×100%。扩展能力应通过多轮测试获得扩展指标的变化趋势。一般扩展能力非常好的应用系统,扩展指标应是线性或接近线性的,现在很多大规模的分布式系统的扩展能力非常好。

标准

  • 理想的扩展能力是资源增加几倍,性能就提升几倍。
  • 扩展能力至少在70%以上。

目前业界使用比较多的开源监控系统是:Prometheus

它提供了 监控预警 的功能。

我们可以用它监控如下信息:

  • 接口响应时间
  • 调用第三方服务耗时
  • 慢查询sql耗时
  • cpu使用情况
  • 内存使用情况
  • 磁盘使用情况
  • 数据库使用情况

它的界面大概长这样子:

在这里插入图片描述

可以看到mysql当前qps,活跃线程数,连接数,缓存池的大小等信息。

如果发现数据量连接池占用太多,对接口的性能肯定会有影响。

这时可能是代码中开启了连接忘了关,或者并发量太大了导致的,需要做进一步排查和系统优化。

3.链路追踪

有时候某个接口涉及的逻辑很多,比如:查数据库、查redis、远程调用接口,发mq消息,执行业务代码等等。

该接口一次请求的链路很长,如果逐一排查,需要花费大量的时间,这时候,我们已经没法用传统的办法定位问题了。

有没有办法解决这问题呢?

用分布式链路跟踪系统:skywalking

通过skywalking定位性能问题:

在这里插入图片描述

在skywalking中可以通过traceId(全局唯一的id),串联一个接口请求的完整链路。可以看到整个接口的耗时,调用的远程服务的耗时,访问数据库或者redis的耗时等等,功能非常强大。

之前没有这个功能的时候,为了定位线上接口性能问题,我们还需要在代码中加日志,手动打印出链路中各个环节的耗时情况,然后再逐一排查。

问题排查

1.个别接口响应慢

链路追踪

使用SkyWalking,展示出每一个与网络有关的耗时。比如:读写数据库、读写Redis、SpringCloud调用、Dubbo调用等。这样就能立马定位是哪次操作耗时了。

同时,SkyWalking可以记录每一个SQL语句,可以帮助定位。

例如:(如箭头所指处,最上边一个是总耗时,下边的线段是单个操作的耗时)

在这里插入图片描述

在链路上打印日志

在相应的链路上打印日志,然后查看日志,看是哪个地方耗时。

死锁问题

在这里重点讲一下出现死锁问题的排查经验吧

有这样的情况:一个线程需要同时获取多把锁,这时就容易发生死锁

t1 线程 获得 A对象 锁,接下来想获取 B对象 的锁 t2 线程 获得 B对象 锁,接下来想获取 A对象 的锁

Object A = new Object();
    Object B = new Object();
    Thread t1 = new Thread(() -> {
        synchronized (A) {
            log.debug("lock A");
            sleep(1);
            synchronized (B) {
                log.debug("lock B");
                log.debug("操作...");
            }
        }
    }, "t1");
    Thread t2 = new Thread(() -> {
        synchronized (B) {
            log.debug("lock B");
            sleep(0.5);
            synchronized (A) {
                log.debug("lock A");
                log.debug("操作...");
            }
        }
    }, "t2");
    t1.start();
    t2.start();

12:22:06.962 [t2] c.TestDeadLock - lock B 
12:22:06.962 [t1] c.TestDeadLock - lock A 
定位死锁

检测死锁可以使用 jconsole工具,或者使用 jps 定位进程 id,再用 jstack 定位死锁:

jps
cmd > jps
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
12320 Jps
22816 KotlinCompileDaemon
33200 TestDeadLock // JVM 进程
11508 Main
28468 Launcher
cmd > jstack 33200
        Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
        2018-12-29 05:51:40
        Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.91-b14 mixed mode):
        "DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000003525000 nid=0x2f60 waiting on condition
        [0x0000000000000000]
        java.lang.Thread.State: RUNNABLE
        "Thread-1" #12 prio=5 os_prio=0 tid=0x000000001eb69000 nid=0xd40 waiting for monitor entry
        [0x000000001f54f000]
        java.lang.Thread.State: BLOCKED (on object monitor)
        at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
        - waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)
        - locked <0x000000076b5bf1d0> (a java.lang.Object)
        at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)
        "Thread-0" #11 prio=5 os_prio=0 tid=0x000000001eb68800 nid=0x1b28 waiting for monitor entry
        [0x000000001f44f000]
        java.lang.Thread.State: BLOCKED (on object monitor)
        at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)
        - waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)
        - locked <0x000000076b5bf1c0> (a java.lang.Object)
        at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)

// 略去部分输出
        Found one Java-level deadlock:
        =============================
        "Thread-1":
        waiting to lock monitor 0x000000000361d378 (object 0x000000076b5bf1c0, a java.lang.Object),
        which is held by "Thread-0"
        "Thread-0":
        waiting to lock monitor 0x000000000361e768 (object 0x000000076b5bf1d0, a java.lang.Object),
        which is held by "Thread-1"
        Java stack information for the threads listed above:
        ===================================================
        "Thread-1":
        at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
        - waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)
        - locked <0x000000076b5bf1d0> (a java.lang.Object)
        at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)
        "Thread-0":
        at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)
        - waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)
        - locked <0x000000076b5bf1c0> (a java.lang.Object)
        at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:745)
        Found 1 deadlock

这里是两个线程 “Thread-0” 和 “Thread-1” 在互相等待对方释放锁,从而导致了死锁。

线程 “Thread-1” 试图获取对象0x000000076b5bf1c0的监视器锁(即synchronized关键字保护的那个对象),但是这个锁已经被线程 “Thread-0” 持有。因此,“Thread-1” 进入了等待状态,等待 “Thread-0” 释放这个锁。

同时,线程 “Thread-0” 试图获取对象0x000000076b5bf1d0的监视器锁,但是这个锁已经被线程 “Thread-1” 持有。因此,“Thread-0” 进入了等待状态,等待 “Thread-1” 释放这个锁。

jconsole

在这里插入图片描述

在这里插入图片描述

2.所有接口响应慢

如果线上出了问题,首先判断是业务问题还是整个系统的问题。如果是业务问题,就去看应用的日志等进行排查。如果出现了如下问题,就可能是整个系统的问题

  1. 大量接口都很慢
  2. 页面打不开

如何得知系统出问题了?

系统出问题时,我们需要进行详细排查,一般情况下,有以下场景我们可以得知线上出问题了:

  1. 用户反馈功能不能正常使用
  2. 监控系统的邮件或者短信提醒

系统问题排查步骤

以下按顺序进行

  1. 是否CPU占用过高
  2. 是否内存占用过高
  3. 是否磁盘占用过高
  4. 是否网络故障
  5. 查看后台日志
  6. 是否是数据库问题(比如:索引失效、死锁)
  7. 是否是垃圾回收导致

CPU占用过高

什么场景需要排查CPU占用?

  1. 访问接口的响应速度很慢。
  2. 系统崩溃无响应
  3. 压测时要查看CPU、内存、load、rt、qps等指标

步骤简述

  1. 定位进程 (命令:top)
  2. 定位线程 (命令:top -Hp 进程号)
  3. 定位代码位置 (命令:jstack)

排查方法详述

  1. 找到占CPU最高的进程。
    1. top命令,记下进程号(PID)。假设最高的是:1893
  2. 通过进程找到对应的线程。
    1. top -Hp 1893。假设最高的是:4519
    2. (因为Java是单进程多线程的)
  3. 通过线程定位到代码大概的位置信息。
    1. printf %x 4519。结果为:11a7
    2. jstack 1893 | grep 11a7 -A 30 –color
      结果大概是这样的:

在这里插入图片描述

可能导致CPU使用率飙升的操作

  • 无限循环的while
  • 经常使用Young GC
  • 频繁的GC

如果访问量很高,可能会导致频繁的GC甚至Full GC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。

  • 序列化和反序列化

序列化和反序列化本身不会导致CPU使用率飙升。序列化是将对象转换为字节流的过程,而反序列化则是将字节流转换回对象的过程。这两个过程通常在内存中完成,并不直接导致CPU使用率的飙升。

然而,在某些情况下,序列化和反序列化可能会导致CPU使用率增加。例如,当需要大量的数据进行序列化或反序列化时,可能会消耗较多的CPU资源。此外,如果序列化和反序列化的操作频繁且耗时较长,也可能对CPU使用率产生一定影响。

  • 正则表达式

正则表达式本身不会导致CPU飙升,但是使用不当或者复杂的正则表达式可能会导致CPU负载增加。

正则表达式在处理大量文本时,特别是复杂的表达式或者需要进行大量回溯的情况下,可能会消耗大量的 CPU 资源。这是因为正则表达式引擎需要在文本中进行搜索和匹配,并且有些复杂的规则可能需要大量的计算才能找到匹配的结果。

因此,在编写正则表达式时,需要注意避免过于复杂或低效的表达式,尤其是在处理大量文本的场景下。另外,对于一些需要频繁执行的操作,可以考虑在代码中进行优化,以减少对 CPU 的负载影响。

  • 线程上下文切换

内存占用过高

步骤简述

定位Java程序内存使用过高或者内存泄漏的问题跟CPU也类似,可分为以下步骤:

  1. 定位进程 (命令:top)
  2. 定位线程 (命令:top -Hp 进程号)
  3. 定位代码位置 (命令:jmap生成快照,MAT / jprofiler / VisualVM / jhat 查看快照数据)

1.定位进程

  1. top
  2. 按下M(按内存占用由大到小排序)
    1. // 假设定位到的进程ID为14279。

2.定位线程

top -Hp 14279;

按下M(按内存占用由大到小排序)

top - 18:33:07 up 25 days,  7:48,  1 user,  load average: 0.17, 0.27, 0.23
Threads:  54 total,   1 running,  53 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.5 us,  0.7 sy,  0.0 ni, 98.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  8168236 total,   231696 free,  3660496 used,  4276044 buff/cache
KiB Swap:   969964 total,   969964 free,        0 used.  4197860 avail Mem
  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
14293 weiping   20   0 4508772  97036  18112 S  10    12 152:35.42 java
14279 weiping   20   0 4508772  97036  18112 S  5.0  1.2   0:00.00 java
14282 weiping   20   0 4508772  97036  18112 S  0.0  1.2   0:00.37 java

注意观察两点:

  1. 线程的数量
    1. 可以看到,它线程数是54(左上角的Threads项),属于正常。
    2. 若比较大(比如大于1000),要考虑是不是代码有问题:
      1. 是不是代码里手动起了多个线程。比如:使用OkHttpClient时每次都创建了连接池(ConnectionPool);应该是只创建一个连接池的。
      2. 是不是自己创建的线程池最大个数太大了。
  2. 占内存大的线程的PID
    1. 如果线程数量正常,就要dump内存的快照信息来查看。

3.定位代码位置

如果是线上环境,注意dump之前必须先将流量切走,否则大内存dump是直接卡死服务。

dump当前快照:jmap -dump:format=b,file=dump.hprof 14279

查找实例数比较多的业务相关的实例,然后找到相应代码查看。(使用工具查看dump.hprof。比如:MAT、VisualVM、jhat)

磁盘问题

步骤简介

  1. 是否磁盘快用完了(命令:df、du)
  2. TPS是否正常(命令:iostat、vmstat、lsof)

这个命令是用来检查系统的磁盘性能是否正常。具体来说:

  • iostat 命令用于报告 CPU 使用情况和磁盘I/O统计信息。
  • vmstat 命令用于报告虚拟内存统计信息。
  • lsof 命令用于列出打开文件。

通过使用这些命令,可以获得关于磁盘 I/O 活动、CPU 使用率、内存使用等方面的统计数据。其中,磁盘 I/O 统计信息中的 TPS(每秒传输的 I/O 操作数)可以用来评估磁盘的性能是否正常。如果 TPS 过高或者过低,可能意味着磁盘存在性能问题,需要进一步分析和解决。

网络问题

垃圾回收

什么情况下,GC会对程序产生影响?

不管Minor GC还是FGC,都会造成一定程度的程序卡顿(即Stop The World:GC线程开始工作,其他工作线程被挂起),即使采用ParNew、CMS或者G1这些更先进的垃圾回收算法,也只是在减少卡顿时间,而并不能完全消除卡顿。

那到底什么情况下,GC会对程序产生影响呢?根据严重程度从高到底,包括以下4种情况:

  1. FGC过于频繁
    1. FGC通常比较慢,少则几百毫秒,多则几秒,正常情况FGC每隔几个小时甚至几天才执行一次,对系统的影响还能接受。
    2. 一旦出现FGC频繁(比如几十分钟执行一次),是存在问题的,会导致工作线程频繁被停止,让系统看起来一直有卡顿现象,也会使得程序的整体性能变差。
  2. YGC耗时过长
    1. 一般来说,YGC的总耗时在几十或者上百毫秒是比较正常的,虽然会引起系统卡顿几毫秒或者几十毫秒,这种情况几乎对用户无感知,对程序的影响可以忽略不计。
    2. 如果YGC耗时达到了1秒甚至几秒(都快赶上FGC的耗时了),那卡顿时间就会增大,加上YGC本身比较频繁,就会导致比较多的服务超时问题。
  3. FGC耗时过长
    1. FGC耗时增加,卡顿时间也会随之增加,尤其对于高并发服务,可能导致FGC期间比较多的超时问题,可用性降低,这种也需要关注。
  4. YGC过于频繁
    1. 即使YGC不会引起服务超时,但是YGC过于频繁也会降低服务的整体性能,对于高并发服务也是需要关注的。

如何排查

  1. 公司的监控系统:大部分公司都会有,可全方位监控JVM的各项指标。
  2. JDK自带工具:jmap、jstat
    1. 查看堆内存各区域的使用率以及GC情况:jstat -gcutil pid 1000 (重点关注结果中的YGC、YGCT、FGC、FGCT、GCT)
    2. 查看堆内存中的存活对象,并按空间排序:jmap -histo pid | head -n20
    3. dump堆内存文件:jmap -dump:format=b,file=heap pid

相关优秀博客

后端接口性能优化分析-多线程优化-CSDN博客

后端接口性能优化分析-程序结构优化-CSDN博客

后端接口性能优化分析-数据库优化-CSDN博客

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

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

相关文章

图解系列--密码

1.概念 _1.对称密码与公钥密码 对称密码是指在加密和解密时使用同一密钥的方式。 公钥密码则是指在加密和解密时使用不同密钥的方式。因此&#xff0c;公钥密码又称为非对称密码。 _2.混合密码系统 对称密码和公钥密码结合起来的密码方式 _3.散列值 散列值就是用单向散列函数计…

CSDN每日一题学习训练——Java版(二叉搜索树迭代器、二叉树中的最大路径和、按要求补齐数组)

版本说明 当前版本号[20231115]。 版本修改说明20231115初版 目录 文章目录 版本说明目录二叉搜索树迭代器题目解题思路代码思路参考代码 二叉树中的最大路径和题目解题思路代码思路参考代码 按要求补齐数组题目解题思路代码思路参考代码 二叉搜索树迭代器 题目 实现一个二…

UE4动作游戏实例RPG Action解析三:实现效果,三连击Combo,射线检测,显示血条,火球术

一、三连Combo 实现武器三连击,要求: 1.下一段Combo可以随机选择, 2.在一定的时机才能再次检测输入 3. 等当前片段播放完才播放下一片段 1.1、蒙太奇设置 通过右键-新建蒙太奇片段,在蒙太奇里创建三个片段,并且移除相关连接,这样默认只会播放第一个片段 不同片段播…

requests 2.13.0 版本的 https 连接慢漏提示

# 解决方案 requests 2.13.0 版本的 https 连接慢漏问题 问题背景&#xff1a;在使用requests 2.13.0版本时&#xff0c;发现存在一个缓慢的泄漏问题。这个问题只在使用https连接时出现。经过调查&#xff0c;发现这个问题与pyOpenSSL的使用有关。在使用pyOpenSSL与requests 2.…

Ps:利用 AI 技术创建人像皮肤图层蒙版

Photoshop 并没有提供专门选择人像皮肤的工具或命令&#xff08;色彩范围中的肤色选择非常不精准&#xff09;&#xff0c;但较新版的 Camera Raw 滤镜则提供了基于 AI 技术的选择人物并创建面部和身体皮肤蒙版的功能。 如果能将 Camera Raw 滤镜中创建的 AI 皮肤蒙版转换成 Ps…

Qt图形视图框架:QGraphicsItem详解

Qt图形视图框架&#xff1a;QGraphicsItem详解 Chapter1 Qt图形视图框架&#xff1a;QGraphicsItem详解Chapter2 自定义QGraphicsItem实现平移、改变尺寸和旋转1. 平移2. 改变尺寸3. 旋转完整代码如下&#xff1a;头文件源文件 Chapter1 Qt图形视图框架&#xff1a;QGraphicsIt…

初试 jmeter做压力测试

一.前言 压力测试是每一个Web应用程序上线之前都需要做的一个测试&#xff0c;他可以帮助我们发现系统中的瓶颈问题&#xff0c;减少发布到生产环境后出问题的几率&#xff1b;预估系统的承载能力&#xff0c;使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步…

nodejs+vue黄河风景线旅游网站的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

本文首先对该系统进行了详细地描述&#xff0c;然后对该系统进行了详细的描述。管理人员增加了系统首页、个人中心、用户管理、景点分类管理、景点简介管理、旅游路线管理、文章分类管理、公告文章管理、系统管理理等功能。这套黄河风景线旅游网站是根据当前的现实需要&#xf…

接口

文章目录 概述语法使用特性接口的继承抽象类和接口的区别 概述 电脑的USB口上&#xff0c;可以插&#xff1a;U盘、鼠标、键盘…所有符合USB协议的设备 电源插座插孔上&#xff0c;可以插&#xff1a;电脑、电视机、电饭煲…所有符合规范的设备 通过上述例子可以看出&#xff…

.NET 7 创建Android项目 (拥有原生的界面设计能力,比MAUI更好的性能)

vs2022默认移动开发使用的是maui项目模板&#xff0c;maui确实有很多亮点&#xff0c;就是对比android原生项目性能还需要优化&#xff0c;特别是启动app时无法达到秒开。后来发现vs2022中依然可以直接创建android项目&#xff0c;性能和原生Android基本一致。 1、搜索模板 dot…

OPPO Watch纯手机开启远程ADB调试

Wear OS手表中&#xff0c;我们可以直接在开发者设置中打开WiFi调试。但是这在OPPO等魔改Android系统中不再奏效。 需要什么&#xff1f;&#xff1f; 手表一台手机一个OTG转接头一个手表充电器一个 演示设备 手机&#xff1a; OPPO Find X手表&#xff1a; OPPO Watch 1代 …

Mysql MMM

MMM概述 MMM(Master-Master replication manager for MvSQL&#xff0c;MySQL主主复制管理器&#xff09; 是一套支持双主故障切换和双主日常管理的脚本程序。 MMM 使用 Perl 语言开发&#xff0c;主要用来监控和管理MySQL Master-Master&#xff08;双主&#xff09;复制&…

S-Clustr(影子集群) 重磅更新!黑入工业PLC设备!

公告 项目地址:https://github.com/MartinxMax/S-Clustr 更新预告内容进度SIEMENS S7-200 SMART远程控制进行中 开发人员Blog联系方式提交时间提交内容授权情况ASH_HHhttps://blog.csdn.net/m0_53711047/article/details/133691537?spm1001.2014.3001.5502匿名2023-10-16 2…

性能测试 —— Jmeter接口处理不低于200次/秒-场景

需求&#xff1a;期望某个接口系统的处理能力不低于200次/秒&#xff0c;如何设计&#xff1f; ①这个场景是看服务器对某个接口的TPS值是否能大于等于200&#xff0c;就可以了&#xff1b; ②系统处理能力&#xff1a;说的就是我们性能测试中的TPS&#xff1b; ③只要设计一…

借助Spire.Doc for Java控件,将 ODT 转换为 PDF。

在通过电子邮件发送或与其他人共享 ODT 文件之前&#xff0c;您可能需要将该文件转换为 PDF&#xff0c;以便任何人都可以跨多个操作系统访问该文件。在本文中&#xff0c;您将学习如何使用Spire.Doc for Java在 Java 中将 ODT 转换为 PDF。 Spire.Doc 是一款专门对 Word 文档…

基于单片机的公交车报站系统(论文+源码)

1系统设计 本次课题为基于单片机的公交车报站系统&#xff0c;在此主要是基于Proteus平台展开设计&#xff0c;因此结合Proteus平台的特性&#xff0c;将功能设计如下&#xff1a; &#xff08;1&#xff09;公交车具有上行和下行两种状态&#xff0c;可以通过按键进行手动播…

保姆级教程之SABO-VMD-CNN-SVM的分类诊断,特征可视化

今天出一期基于SABO-VMD-CNN-SVM的分类诊断。 依旧是采用经典的西储大学轴承数据。基本流程如下&#xff1a; 首先是以最小包络熵为适应度函数&#xff0c;采用SABO优化VMD的两个参数。其次对每种状态的数据进行特征向量的求取&#xff0c;并为每组数据打上标签。然后将数据送入…

系列二、类装载器ClassLoader

一、能干嘛 1.1、方法区 存放类的描述信息的地方。 1.2、JVM中的类装载器 1.3、获取ClassLoader的方式 /*** Author : 一叶浮萍归大海* Date: 2023/11/16 0:08* Description: 获取类的加载器的方式*/ public class ClassLoaderMainApp {public static void main(String[] arg…

【linux】centos7 yum安装nginx

查看系统中是否已安装 nginx 服务 yum list | grep nginx查看nginx运行进程 ps -ef | grep nginx添加源 rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 安装Nginx yum install -y nginx 查看nginx安装目录 find …

vagrant+virtualbox的踩坑记录

vagrant virtualbox 文章目录 vagrant virtualbox一、导入虚拟机ova文件失败二、修改虚拟机的保存位置三、无法使用xshell等软件用密码进行连接四、vagrant up失败 一、导入虚拟机ova文件失败 背景&#xff1a;手动删除了虚拟机文件导致无法重新导入相同名称虚拟机的ova文件…
最新文章