1、tomcat调优
采用动静分离节约tomcat性能:nginx+tomcat实现动静分离,nginx实现静态资源的访问
调整tomcat线程池:比如maxThreads线程池中最大的线程数量 minSpareThreads线程池中允许空闲的线程数量 maxIdLeTime一个线程空闲多久算是空闲线程
调整tomcat连接器:enableLookups="false"关闭dns解析,减少性能损耗
修改tomcat的运行模式:可以将protocol改为NIO模式
禁用AJP连接器 Apache JServer Protocol
使用Nginx+tomcat的架构,所以用不着AJP协议,所以把AJP连接器禁用
2、tomcat里JVM调优
修改TOMCAT_HOME/bin/catalina.sh,添加JAVA_OPTS配置
JAVA_OPTS="-Xms2G -Xmx2G -Xss256K -server -XX:+UseG1GC -XX:NewRatio=1 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/work/test/appdata/mfs -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/home/work/test/appdata/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M -XX:ParallelGCThreads=11 -XX:ConcGCThreads=4 -Dfile.encoding=UTF-8"
-Xms 初始堆大小 空余堆内存小于40%时,jvm就会增大堆直到-Xmx的最大限制
-Xmx 最大堆大小 空余堆内存大于70%时,jvm会减少堆直到-Xms的最小限制
这两个值设置成一样大,可以减少伸缩堆大小带来的压力
PrintGCDetails 打印gc的具体日志
-XX:+UseG1GC 使用G1垃圾收集器 优点:1、并行与并发,并行指G1在回收期间会有多个GC线程同时工作,并发是指G1部分工作可以和应用程序同时执行
2、空间整合,将内存划分为一个个的region,region之间是复制算法,整理实际上可以算是标记-压缩算法,避免产生内存碎片
3、可预测的停顿时间模型,维护了一个优先列表,根据每个region的垃圾堆积的价值大小来决定回收哪块region
我们之前说过,G1在回收每个Region上的垃圾时,每个Region之间又有相互依赖引用关系,想要做到对全部Region进行扫描清理,那么不得不做一次全堆扫描。这样就降低了垃圾回收的效率。所以HotSpot引入了Remembered Set来专门存储于管理对象的引用依赖关系,这样当每次回收时,只需要根据Remembered Set上面的对应关系找到相对的区域进行清理,这样就可以避免扫描整个堆内存又不会遗漏某一个区域。
缺点:垃圾收集产生的内存占用和程序运行时的额外负载(overload)比cms要高
使用Java 8以后,关于元空间的JVM参数有两个:-XX:MetaspaceSize=N
和 -XX:MaxMetaspaceSize=N
,对于64位JVM来说,元空间的默认初始大小是20.75MB,默认的元空间的最大值是无限。MaxMetaspaceSize用于设置metaspace区域的最大值,这个值可以通过mxbean中的MemoryPoolBean获取到,如果这个参数没有设置,那么就是通过mxbean拿到的最大值是-1,表示无穷大。
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M(PS:读者可以根据自己的实际情况再调整)。
3、Kafka优化
1、broker参数配置优化
网络和磁盘io线程配置优化
num.network.threads=xxx broker处理消息的最大线程数 默认为3,内部实现是采用了selector模型,启动一个线程作为acceptor来负责建立连接,启动n个线程轮流负责从sockets中取请求,主要处理网络io,读写缓冲区的数据,建议配置为cpu核数+1
num.io.threads=xxx broker处理磁盘io的线程数,主要进行磁盘io操作,因此需要配置大一些,建议配置为cpu核数*2
log数据文件刷盘策略
og.flush.interval.ms=1000 建议配置为1s或者10000条
日志保留策略
log.retention.hours=72。Kafka默认是7天,建议保留三天或者更短
replica相关配置
default.replication.factor:1 #这个参数指新创建一个topic时,默认的Replica数量
Replica过少会影响数据的可用性,太多则会白白浪费存储资源,一般建议在2~3为宜。
2、producer优化
-
buffer.memory:33554432 (32m) 调整未发送出去消息的缓冲区大小
-
compression.type:none 默认发送不压缩,可以配置合适的压缩方式(snappy/gzip/lz4可选,推荐 少CPU,高性价比的snappy)
-
batch.size:16384一个批次的数据字节大小,太大占用缓冲区多,但是不会延迟(有其他触发机制)而 太小会频繁提交消息效率低下 ,Producer会尝试去把发往同一个Partition的多个Requests进行合并,batch.size指明了一次Batch合并后Requests总大小的上限。如果这个值设置的太小,可能会导致所有的Request都不进行Batch。
-
acks:1 这个配置可以设定发送消息后是否需要Broker端返回确认。 0: 不需要进行确认,速度最快。存在丢失数据的风险。1: 仅需要Leader进行确认,不需要ISR进行确认。是一种效率和安全折中的方式。all: 需要ISR中所有的Replica给予接收确认,速度最慢,安全性最高,但是由于ISR可能会缩小到仅包含一个Replica,所以设置参数为all并不能一定避免数据丢失。
-
分区数,num.partitions: 默认分区数配置
分区是为了提高消息处理的吞吐量,一个分区只能由一个consumer消费,但是一个consumer可以消费多个分区,因此分区数决定了同组消费者个数的上限
标准方法:创建一个只有1个分区的topic,然后测试这个topic的producer吞吐量和consumer吞吐量。假设它们的值分别是Tp和Tc,单位可以是MB/s。然后假设总的目标吞吐量是Tt,那么分区数 = Tt / max(Tp, Tc)
简单方法:设置为集群中服务器中数量的1倍或者2倍。
1、副本数推荐设置 3 副本,同步复制。主要为了保证分区的高可用,以避免机器故障导致数据丢失。
2、分区数量与Kafka的消费者的处理能力是强关联的,因此根据自己系统的量级以及场景选择合适的分区数,单topic最大分区数建议为10,以下为消息数量以及分区数的推荐设置
消息数量 | 分区数 |
100万 | 1~3 |
500~700万 | 3~ 5 |
1000+万 | 7~8 |
1+亿 | 10+ |
3、consumer优化
1.启动consumer的线程数适当的增加可以提高并发度 与分区数一致
Kafka内存:默认一个G可以适当的调高一些,一般不建议超过6个G
auto.offset.reset关乎kafka数据的读取,是一个非常重要的设置。常用的二个值是latest和earliest,默认是latest
1,earliest 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
2,latest 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
提交过offset,latest和earliest没有区别,但是在没有提交offset情况下,用latest直接会导致无法读取旧数据。