第20周-2022-05-17

1、总结tomcat优化方法

由于Tomcat的运行依赖于JVM,从虚拟机的角度把Tomcat的调整分为外部环境调优 JVM 和 Tomcat 自身调优两部分。

  • 内存空间优化
    Tomcat的JVM参数设置
JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限(不指定时,大约使用总内存的1/4)
-XX:NewSize=:新生代空间初始化大小 
-XX:MaxNewSize=:新生代空间最大值

生产案例:

[root@centos8 ~]#vim /usr/local/tomcat/bin/catalina.sh
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -
XX:CMSInitiatingOccupancyFraction=65 -XX:+AggressiveOpts -XX:+UseBiasedLocking -
XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -
XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -
XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -
XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -
XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
#一台tomcat服务器并发连接数不高,生产建议分配物理内存通常4G到8G较多,如果需要更多连接,一般会利用虚拟化技术实现多台tomcat
  • 线程池调整
    常用属性:
    connectionTimeout :连接超时时长,单位ms
    maxThreads:最大线程数,默认200
    minSpareThreads:最小空闲线程数
    maxSpareThreads:最大空闲线程数
    acceptCount:当启动线程满了之后,等待队列的最大长度,默认100
    URIEncoding:URI 地址编码格式,建议使用 UTF-8
    enableLookups:是否启用客户端主机名的DNS反向解析,缺省禁用,建议禁用,就使用客户端IP就行
    compression:是否启用传输压缩机制,建议 "on",CPU和流量的平衡
    • compressionMinSize:启用压缩传输的数据流最小值,单位是字节
    • compressableMimeType:定义启用压缩功能的MIME类型text/html, text/xml, text/css,text/javascript
      示例:
[root@centos8 ~]#vim /usr/local/tomcat/conf/server.xml
......

......

2、java程序出现oom如何解决?什么场景下会出现oom?

当JVM因为没有足够内存来为对象分配空间,并且垃圾回收器也没有空间可回收时,系统会出现如下OOM日志:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 at java.util.Arrays.copyOf(Arrays.java:3332)
 at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
 at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
 at java.lang.StringBuilder.append(StringBuilder.java:208)
 at HeapOom2.main(HeapOom2.java:6)

通常出现OOM的原因是:

  • 给应用分配的内存太少,一般是启动时的JVM参数指定太少
  • 应用使用太多,并且用完没有释放,此时就会造成内存泄漏或内存溢出
    • 可以通过JDK工具来分析原因,如jvisualvm配合Visual GC插件;或通过商业软件profiler定位出现问题的代码

解决思路:

  • 限制java进程的max heap,并且降低java程序的worker数量,从而降低内存使用
  • 给系统增加swap空间
  • 设置内核参数,不允许内存申请过量,不推荐的做法;
  • linux默认是允许内存申请过量的,系统寄希望于实际上用不到那么多内存,但如果出现内存过量时:
    linux通过OOM killer机制,挑选一个进程kill来腾出部分内存,还不够那就继续kill,也可以通过vm.panic_on_oom,当发生OOM时就自动重启系统,重启和kill都可能造成业务中断,linux 2.6之后,允许通过vm.overcommit_memory内核参数来禁止memory overcommit

3、简述redis特点及其应用场景

redis特点:

  • 速度快: 10W QPS,基于内存,C语言实现
  • 单线程
  • 持久化
  • 支持多种数据结构
  • 支持多种编程语言
  • 功能丰富: 支持Lua脚本,发布订阅,事务,pipeline等功能
  • 简单: 代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单
  • 主从复制
  • 支持高可用和分布式

redis应用场景:

  • Session 共享:常见于web集群中的Tomcat或者PHP中多web服务器session共享
  • 缓存:数据查询、电商网站商品信息、新闻内容
  • 计数器:访问排行榜、商品浏览数等和次数相关的数值统计场景
  • 微博/微信社交场合:共同好友,粉丝数,关注,点赞评论等
  • 消息队列:ELK的日志缓存、部分业务的订阅发布系统
  • 地理位置: 基于GEO(地理信息定位),实现摇一摇,附近的人,外卖等功能

4、对比redis的RDB、AOF模式的优缺点

  • RDB对内存执行快照,保存了某个时间点内存中的所有数据,当出现问题时可以恢复到不同时间点的版本;但RDB不能实时保存数据,会丢失故障时到上一个时间点之间未保存的数据;
  • RDB是通过父进程fork的子进程来执行的保存工作;但如果子进程在存在期间,发生了大量的写操作,会导致子进程执行复制操作,就会出现很多的page-fault,这样需要消耗不少性能在复制上
  • AOF的数据安全性相对较高,根据使用的fsync策略(何时同步内存数据到磁盘),默认是1s同步一次,就算发生故障,也只会丢失1s内的数据;但根据fsync的策略不同,aof可能速度慢于rdb
  • AOF会产生重复记录,比如对一个数据执行了创建和修改,则创建和修改两个操作都会被记录;
  • AOF在恢复大数据集时需要比RDB久的时间,因为RDB是直接加载到内存,而AOF则需要一条条执行操作;

5、实现redis哨兵,模拟master故障场景

环境:
初始master节点:192.168.184.101
初始slave1节点:192.168.184.102
初始slave2节点:192.168.184.103

使用脚本安装所有redis

[root@centos7-01 ~]# cat install_redis.sh 
#!/bin/bash

. /etc/init.d/functions 
VERSION=redis-6.2.4
PASSWORD=123456
INSTALL_DIR=/apps/redis

install() {
yum  -y install gcc jemalloc-devel || { action "安装软件包失败,请检查网络配置" false ; exit; }

wget http://download.redis.io/releases/${VERSION}.tar.gz || { action "Redis 源码下载失败" false ; exit; }



tar xf ${VERSION}.tar.gz
cd ${VERSION}
make -j 4 PREFIX=${INSTALL_DIR} install && action "Redis 编译安装完成" || { action "Redis 编译安装失败" false ;exit ; }


ln -s ${INSTALL_DIR}/bin/redis-*  /usr/bin/
mkdir -p ${INSTALL_DIR}/{etc,log,data,run}
cp redis.conf  ${INSTALL_DIR}/etc/

sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/'  -e "/# requirepass/a requirepass $PASSWORD"  -e "/^dir .*/c dir ${INSTALL_DIR}/data/"  -e "/logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log"  -e  "/^pidfile .*/c  pidfile ${INSTALL_DIR}/run/redis_6379.pid" ${INSTALL_DIR}/etc/redis.conf


if id redis &> /dev/null ;then 
    action "Redis 用户已存在" false  
else
    useradd -r -s /sbin/nologin redis
    action "Redis 用户创建成功"
fi

chown -R redis.redis ${INSTALL_DIR}

cat >> /etc/sysctl.conf < /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
/etc/rc.d/rc.local

cat > /usr/lib/systemd/system/redis.service < /dev/null && action "Redis 服务启动成功,Redis信息如下:" || { action "Redis 启动失败" false ;exit; } 

redis-cli -a $PASSWORD INFO Server 2> /dev/null

}

install

在所有主从节点配置

[root@centos7-01 ~]# vi /apps/redis/etc/redis.conf
bind 0.0.0.0
masterauth 123456
requirepass 123456

在所有从节点配置

[root@centos7-02 ~]# echo "replicaof 192.168.184.101 6379" >> /apps/redis/etc/redis.conf 
[root@centos7-02 ~]# systemctl restart redis

测试主从复制

#查看master状态
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.184.102,port=6379,state=online,offset=351,lag=1
slave1:ip=192.168.184.103,port=6379,state=online,offset=351,lag=1
master_failover_state:no-failover
master_replid:6a5cf39edbeb45dd6b91eaa3cedcaf55bff50674
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:351
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:351

#在master写数据
[root@centos7-01 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> set name test1
OK

#在slave查看数据
[root@centos7-02 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> get name
"test1"

配置哨兵
所有redis节点使用相同的以下示例的配置文件

[root@centos7-01 ~]# grep -vE '^#|^$' /apps/redis/etc/redis-sentinel.conf 
bind 0.0.0.0
port 26379
daemonize yes
pidfile /apps/redis/run/redis-sentinel.pid
logfile "/apps/redis/log/sentinel_26379.log"
dir /tmp
sentinel monitor mymaster 192.168.184.101 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

将配置文件复制到slave节点
[root@centos7-01 ~]# scp /apps/redis/etc/redis-sentinel.conf 192.168.184.102:/apps/redis/etc/
[root@centos7-01 ~]# scp /apps/redis/etc/redis-sentinel.conf 192.168.184.103:/apps/redis/etc/

在所有节点生成新的service文件

[root@centos7-01 ~]# cat /lib/systemd/system/redis-sentinel.service 
[Unit]
Description=Redis Sentinel
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/redis-sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
Type=notify
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

所有节点配置目录权限,启动sentinel

[root@centos7-01 ~]# chown -R redis.redis /apps/redis/
[root@centos7-01 ~]# systemctl daemon-reload
[root@centos7-01 ~]# systemctl enable --now redis-sentinel

查看sentinel状态

[root@centos7-01 ~]# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.184.101:6379,slaves=2,sentinels=3

模拟101master节点故障

[root@centos7-01 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> shutdown
not connected> 

102slave已提升为主节点

#查看slave节点日志
[root@centos7-01 ~]# tail -f /apps/redis/log/sentinel_26379.log
31252:X 18 May 2022 08:07:13.148 # +sdown master mymaster 192.168.184.101 6379
31252:X 18 May 2022 08:07:13.177 # +new-epoch 1
31252:X 18 May 2022 08:07:13.178 # +vote-for-leader d8410373cb35a36984fb25a19c236f16c3d6e74d 1
31252:X 18 May 2022 08:07:13.240 # +odown master mymaster 192.168.184.101 6379 #quorum 3/2
31252:X 18 May 2022 08:07:13.240 # Next failover delay: I will not start a failover before Wed May 18 08:13:13 2022
31252:X 18 May 2022 08:07:14.289 # +config-update-from sentinel d8410373cb35a36984fb25a19c236f16c3d6e74d 192.168.184.103 26379 @ mymaster 192.168.184.101 6379
31252:X 18 May 2022 08:07:14.289 # +switch-master mymaster 192.168.184.101 6379 192.168.184.102 6379
31252:X 18 May 2022 08:07:14.290 * +slave slave 192.168.184.103:6379 192.168.184.103 6379 @ mymaster 192.168.184.102 6379
31252:X 18 May 2022 08:07:14.290 * +slave slave 192.168.184.101:6379 192.168.184.101 6379 @ mymaster 192.168.184.102 6379
31252:X 18 May 2022 08:07:17.291 # +sdown slave 192.168.184.101:6379 192.168.184.101 6379 @ mymaster 192.168.184.102 6379

# 查看102slave节点状态
[root@centos7-02 ~]# redis-cli -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.184.103,port=6379,state=online,offset=130524,lag=1
master_failover_state:no-failover
master_replid:7103af6186691a2d95490d649ce39ac48203caf6
master_replid2:6a5cf39edbeb45dd6b91eaa3cedcaf55bff50674
master_repl_offset:130669
second_repl_offset:92695
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:130669

#查看102slave节点sentinel状态
[root@centos7-02 ~]# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.184.102:6379,slaves=2,sentinels=3

恢复101redis

[root@centos7-01 ~]# systemctl start redis
[root@centos7-01 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.184.102
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:195382
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:7103af6186691a2d95490d649ce39ac48203caf6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:195382
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:191417
repl_backlog_histlen:3966
#原master节点恢复后状态为slave

你可能感兴趣的:(第20周-2022-05-17)