Tomcat调优总结

news2024/12/23 4:38:47

Tomcat自身的调优是针对conf/server.xml中的几个参数的调优设置。首先是对这几个参数的含义要有深刻而清楚的理解。以tomcat8.5为例,讲解参数。

同时也得认识到一点,tomcat调优也受制于linux内核。linux内核对tcp连接也有几个参数可以调优。

因此可以将tomcat调优分为:

  • linux内核优化
  • java虚拟机调优
  • tomcat自身优化

1 tomcat自身优化

1.1 maxThreads 

tomcat创建的最大线程数,也就是同时处理的请求最大并发数。默认值是200。

官网说明:The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool. Note that if an executor is configured any value set for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1 to make clear that it is not used.

1.1.1 maxThreads如何配置

一般的服务器操作都包括量方面:

  • 计算(主要消耗cpu)
  • 等待(io、数据库等)

第一种极端情况,如果业务逻辑是纯粹的计算,那么系统响应时间的主要限制就是cpu的运算能力,此时maxThreads应该尽量设的小,降低同一时间内争抢cpu的线程个数,可以提高计算效率,提高系统的整体处理能力。

第二种极端情况,如果我业务逻辑纯粹是IO或者数据库,那么响应时间的主要限制就变为等待外部资源,此时maxThreads应该尽量设的大,这样才能提高同时处理请求的个数,从而提高系统整体的处理能力。此情况下因为tomcat同时处理的请求量会比较大,所以需要关注一下tomcat的虚拟机内存设置和linux的open file限制。

在测试时遇到一个问题,maxThreads设置的比较大。比如3000,当服务的线程数大到一定程度时,一般是2000出头,单次请求的响应时间就会急剧的增加。这是为什么呢?原因可能是cpu在线程切换时消耗的时间随着线程数量的增加越来越大,cpu把大多数时间都用来在这2000多个线程直接切换上了,当然cpu就没有时间来处理程序逻辑了。

其实多线程本身并不能提高cpu效率,线程过多反而会降低cpu效率。

当cpu核心数<线程数时,cpu就需要在多个线程直接来回切换,以保证每个线程都会获得cpu时间,即并发执行。所以maxThreads的配置绝对不是越大越好。

现实应用中,业务逻辑一般都会包含以上两种类型(计算、等待),所以maxThreads的配置并没有一个最优值,一定要根据具体情况来配置。

最好的做法是:在不断测试的基础上,不断调整、优化,才能得到最合理的配置。

1.2 acceptCount

当tomcat的线程数达到了最大时,接收排队的最大请求个数。默认值为100。

官网:the maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.

maxThreads与acceptCount这两个值是如何起作用的呢?

情况1:接受一个请求,此时tomcat启动的线程数没有到达maxThreads,tomcat会起动一个线程来处理此请求。

情况2:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,tomcat会把此请求放入等待队列,等待空闲线程。

情况3:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,等待队列中的请求个数也达到了acceptCount,此时tomcat会直接拒绝此次请求,返回connection refused。

对于第3种情况,在看过一篇分析connection timeout问题产生的原因后,等待队列的请求个数这个值可能是由acceptCount参数决定,也有可能由linux内核参数net.core.somaxconn决定。

关联:

网上有分析linux上TCP connection timeout的原因,这篇文章中提到一个内核参数 net.core.somaxconn。那么tomcat的acceptCount与net.core.somaxconn到底是什么关系呢。 

参考实验现象分析:

1. 将tomcat的acceptCount设置为3000 ,net.core.somaxconn设置为8192

那么用ss -lt 指令查看在tomcat起的端口上的send_q值是3000  可见这是acceptCount的值。

2.将tomcat的acceptCount设置为10000,net.core.somaxconn设置为8192

同样用ss -lt指令查看在tomcat起的端口上的send_q值是8192,可见这是somaxconn的值。

所以acceptCount设置的值要一般小于net.core.somaxconn这个参数,这样acceptCount的值才会起作用。net.core.somaxconn 这个参数默认值是128 ,所以需要改这个参数值。后面再介绍改这个值的方法。

1.2.1 acceptCount如何配置

一般是设置的跟maxThreads一样大,这个值应该是主要根据应用的访问峰值与平均值来权衡配置的。

  • 如果设的较小,可以保证接受的请求较快相应,但是超出的请求可能就直接被拒绝
  • 如果设的较大,可能就会出现大量的请求超时的情况,因为我们系统的处理能力是一定的。

1.3 maxConnections

官网:The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will accept, but not process, one further connection. This additional connection be blocked until the number of connections being processed falls below maxConnections at which point the server will start accepting and processing new connections again. Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount setting. The default value varies by connector type. For NIO and NIO2 the default is 10000. For APR/native, the default is 8192.

Note that for APR/native on Windows, the configured value will be reduced to the highest multiple of 1024 that is less than or equal to maxConnections. This is done for performance reasons.
If set to a value of -1, the maxConnections feature is disabled and connections are not counted.

maxConnections是指Tomcat允许的同时存在的最大连接数。

acceptCount、maxConnections是tcp层相关的参数。

1.4 connectionTimeOut

connectionTimeOut=10000是说建立一个socket连接后,如果一直没有收到客户端的FIN,也没有数据过来,那么此连接也必须等到10s后,才能被超时释放,tomcat就直接释放这个连接。以毫秒为单位,server.xml默认设置是20秒。

官网:The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false, this timeout will also be used when reading the request body (if any).


修改方法:
  vi server.xml 打开server.xml文件
将 
<!--
 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
 maxThreads="150" minSpareThreads="4"/>
 -->
修改为:
  <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="1500" minSpareThreads="50" prestartminSpareThreads="true"/>

将

<Connector 
 port="8080" 
 protocol="HTTP/1.1" 
 connectionTimeout="20000" 
 redirectPort="8443" 
 />
修改为

 <Connector executor ="tomcatThreadPool" port="8009" protocol="org.apache.coyote.http11.Http11Nio2Protocol"  connectionTimeout="20000" maxConnections="10000"  redirectPort="8443" acceptCount="1500"/>

下面的图为TCP三次握手与accept交互:

SYN队列称为半连接队列,由内核参数 net.ipv4.tcp_max_syn_backlog 设置.

Accept队列称为完全连接队列,三次握手已经完成,但还未被应用层接收(accept),但也处于ESTABLISHED状态。队列长度由listen的backlog参数和内核的 net.core.somaxconn 参数共同决定。由listen()函数的第二个参数 backlog 指定,内核硬限制由 net.core.somaxconn 限制,即队列长度实际的值由min(backlog,somaxconn) 来决定

客户端使用connect向服务器发送TCP连接,三次握手就发生了。

当1.1步骤 客户端首先发送SYN到达服务端后,内核会把连接信息放到SYN队列中,同时回一个SYN+ACK包给客户端。一段时间后,客户端再次发来ACK包后,内核会把连接从SYN队列中取出,再把这个连接放到ACCEPT队列中。应用服务器调用accept时,其实就是直接从ACCEPT队列中取出已经建立成功的连接套接字。

还有一张图是TCP握手建立连接的流程和队列

1.5 Tomcat原理概要 

Tomcat大致分为两个部分,Connector组件及Container组件。Connector组件负责控制入口连接,并关联着一个Executor。Container负责Servlet容器的实现,Executor负责具体的业务逻辑,如Servlet的执行。一个请求到达服务器后,经过以下关键几步,参见下图:

  1. OS与客户端握手并建立连接,并将建立的连接放入完成队列,不妨叫Acceptor Queque。这个队列的长度就是Connector的acceptCount值。

  2. Tomcat中的acceptor线程,不断从Acceptor Queque中获取连接。

  3. Acceptor Queque队列中没有连接,Acceptor线程继续监视

  4. Acceptor Queque队列中有新连接,Acceptor线程将检查当前的连接数是否超过了maxConnections

  5. 如果超过maxConnections,则阻塞。直到连接数小于maxConnections,acceptor线程将请求交由Executor负责执行。

  6. Executor将分配worker线程来处理请求数据的读取,处理(servlet的执行)以及响应。

acceptCount

acceptCount 实际上是Bind Socket时候传递的backlog值,在linux平台下含义是已经建立连接还没有被应用获取的连接队列最大长度。此时,如果请求个数达到了acceptCount,新进的请求将抛出refuse connection.

2 Linux内核参数优化

2.1 linux系统对当前用户的单一进程同时可打开的文件数量的限制

 查看系统允许当前用户进程打开的文件数量的限制:ulimit -u ,默认值为1024 。即是Linux操作系统对一个进程打开的文件句柄数量的限制。

对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。

修改方法:

sudo vi /etc/security/limits.conf 

增加如下:

prouser  soft   nofile 65536
prouser  hard nofile 65536

prouser  soft  nproc 65536

prouser hard nproc 65536

修改完后保存此文件。

nproc是操作系统级别对每个用户创建的进程数的限制。

2.2 Linux网络内核对TCP连接的有关限制 

修改方法:

sudo vi /etc/sysctl.conf
增加如下:
net.ipv4.tcp_tw_reuse = 1 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_fin_timeout = 30 
net.ipv4.ip_local_port_range = 10000 65000 
net.ipv4.tcp_max_syn_backlog = 8192 
net.ipv4.tcp_max_tw_buckets = 10000
net.core.somaxconn=8192      accept队列的长度跟这个参数有关
 
sudo /sbin/sysctl -p
实时生效

JVM调优

JAVA_OPTS="$JAVA_OPTS -server -Xmn2000m -Xms4000m -Xmx4000m -XX:PermSize=128m -XX:+UseConcMarkSweepGC -XX:MaxPermSize=512m -Djuli-logback.configurationFile=file:$CATALINA_HOME/conf/logback.xml"

默认值:

<!--
 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
 maxThreads="150" minSpareThreads="4"/>
 -->

修改为:

<Executor
 name="tomcatThreadPool"
 namePrefix="catalina-exec-"
 maxThreads="500"
 minSpareThreads="30"
 maxIdleTime="60000"
 prestartminSpareThreads = "true"
 maxQueueSize = "100"
/>

参数解释:

  • maxThreads:最大并发数,默认设置 200,一般建议在 500 ~ 800,根据硬件设施和业务来判断
  • minSpareThreads:Tomcat 初始化时创建的线程数,默认设置 25
  • maxIdleTime:如果当前线程大于初始化线程,那空闲线程存活的时间,单位毫秒,默认60000=60秒=1分钟。
  • prestartminSpareThreads:在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值,如果不等于 true,minSpareThreads 的值就没啥效果了
  • maxQueueSize:最大的等待队列数,超过则拒绝请求

4 生产环境调优实战

4.1 tomcat 启动慢

在线上环境中,我们经常会遇到类似的问题,就是tomcat 启动比较慢,查看内存和cpu,io都是正常的,但是启动很慢,有的时候长达几分钟,这到底是什么原因导致的?

4.1.1 tomcat 获取随机值阻塞

tomcat的启动需要产生session id,这个产生需要通过java.security.SecureRandom生成随机数来实现,随机数算法使用的是”SHA1PRNG”,但这个算法依赖于操作系统的提供的随机数据,在linux系统中,这个值又依赖于/dev/random 和/dev/urandom

/dev/random :阻塞型,读取它就会产生随机数据,但该数据取决于熵池噪声,当熵池空了,对/dev/random 的读操作也将会被阻塞。
/dev/urandom: 非阻塞的随机数产生器,它会重复使用熵池中的数据以产生伪随机数据。这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。

我们通过查看java.security 文件,(我的java版本是1.8.0_131) 发现依赖的是/dev/random

图片

tomcat 启动产生session id 最终依赖的是/dev/random ,/dev/random 又依赖于熵池,

对于熵池,百度百科这样写到:

Linux内核采用熵来描述数据的随机性。熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。在信息学中,熵被用来表征一个符号或系统的不确定性,熵越大,表明系统所含有用信息量越少,不确定度越大。计算机本身是可预测的系统,因此,用计算机算法不可能产生真正的随机数。但是机器的环境中充满了各种各样的噪声,如硬件设备发生中断的时间,用户点击鼠标的时间间隔等是完全随机的,事先无法预测。Linux内核实现的随机数产生器正是利用系统中的这些随机噪声来产生高质量随机数序列。内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。理论上,熵池中的数据是完全随机的,可以实现产生真随机数序列。为跟踪熵池中数据的随机性,内核在将数据加入池的时候将估算数据的随机性,这个过程称作熵估算。熵估算值描述池中包含的随机数位数,其值越大表示池中数据的随机性越好。

那么如何查看熵池 的大小,文件 /proc/sys/kernel/random/entropy_avail 保存着 熵池的大小。/proc/sys/kernel/random/poolsize 保存着熵池的最大容量,单位都是bit。

[root@haha cwd]# cat  /proc/sys/kernel/random/entropy_avail
146

总结

tomcat 启动慢的原因是随机数产生遭到阻塞,遭到阻塞的原因是 熵池大小 。

解决方法:

1. 更换产生随机数的源,(也是tomcat的官方文档的启动比较慢的解决办法)
2. 增大熵池 的值

1)更换产生随机数的源

因为/dev/urandom 是非阻塞的随机数产生器,所以我们可以从这边获取,但是生产的随机数的随机性比较低。我们可以在 我们的tomcat启动脚本(catalina.sh)里面添加

JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"

或者是更改java的java.security 文件,将securerandom.source=file:/dev/random

securerandom.source=file:/dev/./urandom

注意:为什么我们这里使用的路径是"/dev/./urandom",而不是 "/dev/urandom",是因为在java 8之前的版本设置了/dev/urandom ,但是实际还是使用/dev/random,设置为"/dev/./urandom"才能正常使用 "/dev/urandom" , 这个bug在java8版本已经修复了,如果你是java7版本的话,需要按照上面设置,java8的话可以不用加 "./"。

2)增大熵池 的值

要增大熵池 的值首先得你的cpu支持DRNG 特性, 如何查看我们的服务器的是否支持DRNG特性?

cat /proc/cpuinfo | grep rdrand

如果不支持的话,那么就只能通过上面的第一种方法来解决了

安装rngd服务(关于rngd服务的介绍)

yum -y install rng-tools
systemctl enable   rngd
systemctl start  rngd

然后我们进行查看我们的熵池 的值,会发现变大了

 cat  /proc/sys/kernel/random/entropy_avail

然后我们启动tomcat 会发现启动速度快很多。

4.1.2 tomcat 需要部署的web应用程序太多

有时候tomcat启动比较慢是因为它需要部署的web应用程序太多,但是其中有些应用程序是不需要的,比如在webapps下的 doc 、example、ROOT 等等,可以将不需要的webapps删除,然后再进行发布,这些不需要的web,不仅会占用资源,还有可能是入侵者的入侵对象。如果想并行启动多个web应用程序,我们可以Host 的属性 startStopThreads 值设置大于1 ,但这也取决于我们的服务器是不是多核的。如果是多核的建议调大 startStopThreads 的值,但不超过内核数。

4.1.3 tomcat启动内存不足

如果是项目比较大的话,使用默认的参数去启动的tomcat是很有可能内存不足的,需要设置JVM,将内存调整,JVM 的最大值和最小值建议是不要相差太大(最好一致.)

在启动脚本catalina.sh加上:

JAVA_OPTS='-server -Xms1024m -Xmx1024m'

具体的内存大小,根据业务调整。

以上就是解决tomcat 启动慢的问题和解决方案,可根据自己的项目情况进行使用。

4.2 Connector 调优

4.2.1 使用arp 连接器

tomcat 可以使用Apache Portable Runtime来提供更高的性能服务。Apache Portable Runtime是一个高度可移植的库,是Apache HTTP Server 2.x的核心。APR有许多用途,包含高级的io功能(sendfile,epoll,Openssl),系统级别功能(产生随机数,系统状态)和进程处理(共享内存,NT管道,unix套接字),它可以让tomcat成为通用的web服务器,让java应用作为一个完整的web服务器更加可行,而不是仅仅作为后端的技术。

总结:从系统级别来解决异步io的问题,提升性能。

apr 连接器需要自己手动安装,需要以下组件

  • APR library (需要手动下载安装) tomcat 8.5 需要 APR 1.2+

  • OpenSSL libraries (需要安装)

  • JNI wrappers for APR used by Tomcat (libtcnative) (tomcat 安装包已经提供)

4.2.1.1 yum安装(建议)

注意apr安装的版本

yum -y install openssl
yum -y install apr
yum -y install apr-util
yum -y install tomcat-native
4.2.1.2 源码安装

4.2.1.2.1 apr源码编译

安装流程:https://www.cnblogs.com/zscc/p/9349908.html

1)安装依赖并下载apr 包

下载地址 : http://archive.apache.org/dist/apr/

yum  -y install make gcc gcc-c++  openssl-devel libtool
cd  /tmp  &&  wget  http://archive.apache.org/dist/apr/apr-1.6.5.tar.gz

2)解压apr 包

tar -xzf  apr-1.6.5.tar.gz &&  cd apr-1.6.5

3)预编译,编译,安装

./configure   --prefix=/usr/local/apr  
make  
make  install   
4.2.1.2.2 native 安装

1)解压native 包 (native 包在tomcat 安装包里面 bin下)

cd  tomcat/bin && tar -xzf tomcat-native.tar.gz

2)预编译,编译,安装

cd tomcat-native*/native &&  ./configure  --with-apr=/usr/local/apr 
make 
make install 

3)添加环境变量

vim  + /etc/profile
# 添加环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib

# 加载变量
source  /etc/profile 
4.2.1.3 配置apr 连接器 
vim  ./conf/server.xml

# 将 Connector 属性protocol 配置成 apr(org.apache.coyote.http11.Http11AprProtocol)
   <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
               connectionTimeout="20000"
               redirectPort="8443" />

默认连接器为nio,共有三大连接器:

  • org.apache.coyote.http11.Http11NioProtocol 非阻塞nio连接器

  • org.apache.coyote.http11.Http11Nio2Protocol 非阻塞nio2连接器

  • org.apache.coyote.http11.Http11AprProtocol APR连接器

重启tomcat

图片

4.2.1.4 APR 测试

tomcat,jvm使用默认配置进行测试,使用nio 连接器 共1000次请求100并发

图片

在nio连接器时,我多次尝试使用150并发共1000请求去测试,发现一直成功不了,但是当我使用apr连接时,

1)100并发

图片

2)150 并发

图片

我们可以对比发现,在使用APR连接器在处理高并发请求的时候是有一定的优势的,能够提升web应用的处理请求能力。

4.2.2 Connector 其它属性调优

属性描述建议设置的值
maxThreadstomcat能创建来处理请求的最大线程数,默认值为200500
minProcessors启动时创建的线程数(最小线程数)
acceptCount指定当所有可以使用的处理请求的线程数都被使用时,可以放到队列中的请求数,,超过这个数的请求将拒绝连接 默认值为100500
compressibleMimeType该值用来指定哪些文件类型的文件可以进行压缩,默认值为:text/html,text/xml,text/plain,text/css,text/javascript,application/javascript
compression开启gzip 压缩,可以接受的值是 "off"(禁用压缩),"on"(开启压缩),"force(强制压缩)","1-9"(等效于开启压缩,并且设定压缩等级),开启了压缩,也就意味着要占用更多的cpu资源on
keepAliveTimeout指connector两个HTTP请求直接的等待时间,超过该时间没有接收到第二个HTTP请求就关闭连接,默认是使用connectionTimeout 的值,单位为毫秒30000
processorCache进程缓冲器,默认值是maxThreads的值,使用好该值可以提升并发请求。500

以上设置只是参考,建议根据自己的业务进行设置,并测试。
有很多参数tomcat 默认就给我设置好了,比如URIEncoding,connectionTimeout,这些值都有默认值的。

4.2.3 Host 属性调优

属性描述建议配置
startStopThreads指Host用于启动Context的线程数,默认值为1,如果多核建议配置为核心数-12
unpackWARs默认为true,如果设置为true 表示将web应用程序war包解压,false表示直接从war文件运行。设置为false对性能有一定的影响true

如果想并行启动多个web应用程序,我们可以Host 的属性 startStopThreads 值设置大于1 ,但这也取决于我们的服务器是不是多核的。如果是多核的建议调大 startStopThreads 的值,但不超过内核数。

4.2.4 tomcat线程关闭不掉调优(代码层)

如果我们使用的是自动发布的形式,也就是替换war包的形式,在tomcat安装文章中介绍了与jenkins 集成实现的,那么容易出现的一个问题就是 上一次的线程没有关闭掉,就启动了新的版本,那么上一个版本的线程还存在,也还在占用着资源,这个问题的原因有可能是代码的问题,我们可以尝试直接使用 catalina.sh 脚本stop ,你会发现stop 掉后,该tomcat 的线程还是存在的,那么出现这种情况很大一部分原因就是 在java代码中有非守护线程,也就是java代码未将线程设置为守护线程,导致了tomcat 进行stop 不掉该线程的原因。那么这种情况有可能会导致两个web应用(新老版本)都在使用,那这这个应用的定时任务可能就会执行两次,就容易导致生产事故。

这种问题,一方面会占用服务器资源。另外一方面还会容易导致生产事故,我们可以用jstack 分析下未停止的线程,并和开发区解决这个线程关闭不掉的问题。

4.2.5 AJP 连接器禁用

AJP协议在tomcat中的作用就是将该服务与其它HTTP服务器集成,一般项目中,没有用到该连接器,所以可以禁用该连接器。

4.3 JVM 设置

在前面启动内存不足就谈到了

JAVA_OPTS='-server -Xms1024m -Xmx1024m'

其他的调优选项,如果有多个connector 的话,那么还可以通过 Executor 的属性进行调优。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无锡国家集成电路设计中心某公司的单锂小电机直流电机H桥驱动电路

H桥驱动 L9110S是一款直流电机驱动电路&#xff0c;适合单节锂电池应用。输出电流0.4A。价格约3毛。 推荐原因&#xff1a; 某些人应该知道这个地方&#xff0c;大多数人应该不知道这个地方&#xff0c;所以推荐一下。 这个地方去过几次&#xff0c;某公司与某方走的“近”&…

用Wireshark解码H.264

H264&#xff0c;你不知道的小技巧-腾讯云开发者社区-腾讯云 这篇文章写的非常好 这里仅做几点补充 init.lua内容&#xff1a; -- Set enable_lua to false to disable Lua support. enable_lua trueif not enable_lua thenreturn end-- If false and Wireshark was start…

31.2k star, 免费开源的白板绘图工具 tldraw

31.2k star, 免费开源的白板绘图工具 tldraw 分类 开源分享 项目名: tldraw -- 无限画布白板 Github 开源地址&#xff1a; https://github.com/tldraw/tldraw 在线测试地址&#xff1a; tldraw 文档地址&#xff1a; tldraw SDK tldraw 是一款开源免费的无限画布白板&…

【NC14326】Rails

题目 Rails 栈 翻译 由于原题是英文的&#xff0c;所以这里先翻译一下&#xff1a; PopPush市有一个著名的火车站。那里的山地多得令人难以置信。这个车站建于上个世纪。不幸的是&#xff0c;当时资金极为有限。只能建立一条地面轨道。此外&#xff0c;事实证明&#xff0c;火…

PurpleKeep:提供Azure管道以创建基础设施并执行Atomic测试

关于PurpleKeep PurpleKeep是一款功能强大的安全测试自动化工具&#xff0c;该工具能够通过提供Azure管道以创建基础设施&#xff0c;并帮助广大研究人员执行Atomic测试。 随着攻击技术种类的迅速增加&#xff0c;以及EDR&#xff08;端点检测和响应&#xff09;和自定义检测规…

[leetcode] 637. 二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[3.00000,14.50000,11.00000] 解释&#xff1a;第 0 层的平均值…

FMEA引领智能家居安全革新,打造无忧智能生活新纪元!

在智能家居日益普及的今天&#xff0c;如何确保家居安全成为消费者关注的焦点。本文将探讨如何通过FMEA&#xff08;故障模式与影响分析&#xff09;这一强大的质量管理工具&#xff0c;为智能家居赋能&#xff0c;打造安全无忧的智能生活新体验。 一、FMEA在智能家居领域的应用…

Electron的学习

目录 项目初始化可以看官网非常详细根路径创建.vscode文件夹主进程和渲染进程之前的通信ipcRenderer.send和ipcMain.on的使用ipcRenderer.invoke和ipcMain.handle的使用 切换主题模式文件拖放保存消息通知进度展示图标闪烁自定义菜单自定义右键菜单 项目初始化可以看官网非常详…

基于ArgoCD和Testkube打造GitOps驱动的Kubernetes测试环境

本文介绍了一项新工具&#xff0c;可以基于Gitops手动或者自动实现Kubernetes集群应用测试&#xff0c;确保集群的健康状态与Git仓库定义的一致。原文: GitOps-Powered Kubernetes Testing Machine: ArgoCD Testkube 简介&#xff1a;GitOps 云原生测试面临的挑战 现代云原生应…

Qt中出现中文乱码的原因以及解决方法

Qt专栏&#xff1a;http://t.csdnimg.cn/C2SDN 目录 1.引言 2.原因分析 3.源文件的编码格式修改方法 4.程序内部使用的默认编码格式修改方法 5.QString转std::string的方法 6.总结 1.引言 在编写Qt程序的时候&#xff0c;或多或少都可能遇到用QString时候&#xff0c;明明…

游戏APP如何提高广告变现收益的同时,保证用户留存率?

APP广告变现对接第三方聚合广告平台主要通过SDK文档对接&#xff0c;一些媒体APP不具备专业运营广告变现的对接能力和资源沉淀&#xff0c;导致APP被封控&#xff0c;设置列入黑名单&#xff0c;借助第三方聚合广告平台进行商业化变现是最佳选择。#APP广告变现# 接入第三方平台…

51单片机入门:认识开发板

认识开发板 板载资源&#xff1a; 数码管模块 说明&#xff1a; 2个四位一体共阴数码管 详细&#xff1a; 2个四位一体&#xff1a;两个独立的四位数码管&#xff0c;每个四位数码管都是“一体”的设计&#xff0c;也就是说&#xff0c;每个数码管内部集成了四个独立的七段LE…

Stable Diffusion WebUI 附加功能/图片放大(Extras):单张图片/批量处理/从目录进行批量处理

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 大家好&#xff0c;我是水滴~~ 篇文章主要讲解 Stable Diffusion WebUI 的附加功能/图片放大&#xff08;Extras&#xff09;的使用&#xff0c;主要…

JAV八股--redis

如何保证Redis和数据库数据一致性 关于异步通知中消息队列和Canal的内容。 redisson实现的分布式锁的主从一致性 明天继续深入看这个系列问题 介绍IO复用模型

WebSocket用户验证

在WebSocket中&#xff0c;如何携带用户的验证信息 一、在OnMessage中进行验证 客户端在连接到服务器后&#xff0c;客户端通过发送消息&#xff0c;服务器端在OnMessage方法中&#xff0c;进行信息验证&#xff0c;这种方式需要将用户身份验证及接收用户消息进行混合处理&am…

什么是原生IP?原生IP的作用是什么?

原生IP&#xff08;Native IP&#xff09;是指直接从互联网服务提供商&#xff08;ISP&#xff09;获得的IP地址&#xff0c;而非通过代理服务器、VPN或其他中间层方式获取。这种IP地址直接与用户的设备或网络关联&#xff0c;无需经过任何中间服务器或代理的转发或隐藏&#x…

体验OceanBase 的binlog service

OceanBase对MySQL具备很好的兼容性。目前&#xff0c;已经发布了开源版的binlog service工具&#xff0c;该工具能够将OceanBase特有的clog模式转换成binlog模式&#xff0c;以便下游工具如canal、flink cdc等使用。今天&#xff0c;我们就来简单体验一下这个binlog service的功…

Educational Codeforces Round 163 (Rated for Div. 2) E. Clique Partition

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e9, maxm 4e4 5; co…

MacBook 访达使用技巧【mac 入门】

快捷键 打开访达搜索窗口默认快捷键【⌥ ⌘ 空格键】可以在键盘【系统偏好设置 -> 键盘->快捷键->聚焦】修改 但是我不会去修改它&#xff0c;因为我不常用访达的搜索窗口&#xff0c;更多的是想快速打开访达文件夹窗口&#xff0c;可以通过第三方软件定义访达的快…

测开——Java、python、SQL、数据结构面试题整理

一、Java 1.Java中finally、final、finalize的区别 1.性质不同 &#xff08;1&#xff09;final为关键字; &#xff08;2&#xff09;finalize()为方法; &#xff08;3&#xff09;finally为为区块标志,用于try语句中; 2. 作用 &#xff08;1&#xff09;final为用于标识…