第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
......
<Connector port="8080" protocol="HTTP/1.1"  connectionTimeout="20000" redirectPort="8443" />
......

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 <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
sysctl -p 

echo 'echo never > /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 <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
#Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

EOF
systemctl daemon-reload 
systemctl enable --now  redis &> /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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容