第二十周--作业

1、总结tomcat优化方法

#内存优化
Windows 下的 catalina.bat
Linux 下的 catalina.sh
在该文件中配置jvm的内存空间,如: JAVA_OPTS='-Xms256m -Xmx512m'
-Xms JVM初始化堆的大小
-Xmx JVM堆的最大值,实际参数大小根据服务器配置或者项目具体设置;
 
#线程优化
例如:
<Connector port="80" protocol="HTTP/1.1" maxThreads="600" minSpareThreads="100" maxSpareThreads="500" acceptCount="700"
connectionTimeout="20000"  />
 
maxSpareThreads="X" 表示如果最多可以有X个线程,一旦超过X个,则会关闭不在需要的线程
acceptCount="X" 当同时连接的人数达到maxThreads时,还可以排队,队列大小为X.超过X就不处理
 
#IO优化
同步阻塞IO(JAVA BIO) 同步并阻塞,服务器实现模式为一个连接一个线程(one connection one thread 想想都觉得恐怖,线程可是非常宝贵的资源),当然可以通过线程池机制改善.
 
JAVA NIO 又分为同步非阻塞IO,异步阻塞IO与BIO最大的区别one request one thread.可以复用同一个线程处理多个connection(多路复用).
 
异步非阻塞IO(Java NIO2又叫AIO) 主要与NIO的区别主要是操作系统的底层区别,可以做个比喻:比作快递,NIO就是网购后要自己到官网查下快递是否已经到了(可能是多次),然后自己去取快递;AIO就是快递员送货上门了(不用关注快递进度)。

  

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

#以下场景
堆内存溢出
堆内存溢出太常见,⼤部分⼈都应该能想得到这⼀点,堆内存⽤来存储对象实例,我们只要不停的创建对象,并且保证GC Roots和对象之间有可达路径避免垃圾回收,那么在对象数量超过最⼤堆的⼤⼩限制后很快就能出现这个异常。
 
⽅法区(运⾏时常量池)和元空间溢出
⽅法区和堆⼀样,是线程共享的区域,包含Class⽂件信息、运⾏时常量池、常量池,运⾏时常量池和常量池的主要区别是具备动态性,也 就是不⼀定⾮要是在Class⽂件中的常量池中的内容才能进⼊运⾏时常量池,运⾏期间也可以可以将新的常量放⼊池中,⽐如String的intern()⽅法。
 
直接内存溢出
直接内存并不是虚拟机运⾏时数据区域的⼀部分,并且不受堆内存的限制,但是受到机器内存⼤⼩的限制。常见的⽐如在NIO中可以使⽤native函数直接分配堆外内存就容易导致OOM的问题。
直接内存⼤⼩可以通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java 堆最⼤值-Xmx⼀样。
由直接内存导致的内存溢出,⼀个明显的特征是在Dump⽂件中不会看见明显的异常,如果发现OOM之后Dump⽂件很⼩,⽽程序中⼜直 接或间接使⽤了NIO,那就可以考虑检查⼀下是不是这⽅⾯的原因。
 
栈内存溢出
栈是线程私有,它的⽣命周期和线程相同。每个⽅法在执⾏的同时都会创建⼀个栈帧⽤于存储局部变量表、操作数栈、动态链接、⽅法出⼝ 等信息,⽅法调⽤的过程就是栈帧⼊栈和出栈的过程。
在java虚拟机规范中,对虚拟机栈定义了两种异常:
如果线程请求的栈深度⼤于虚拟机所允许的深度,将抛出StackOverflowError异常

  

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

#redis特点
速度快:redis是基于C语言实现的,所有数据是放在内存中,因而查询速度非常快,每秒的查询次数可以达到10W;
 
单线程:单线程主要是在redis6.0之前的版本中,由于redis的数据是纯内存的,单线程可以起到非阻塞、避免线程切换和竞态消耗的效果;
 
持久化:redis虽然是基于内存的,其数据也具有磁盘存储功能,即使是出现断电等情况也不会导致数据丢失的现象,可做到数据的持久化;
 
支持多种数据结构:redis支持hash、集合、有序集合等多种数据结构;
 
支持多种编程语言:基本上主流的编程语言都可访问redis数据;
 
功能丰富:支持lua脚本、发布订阅、事务、pipeline等功能;
 
简单:redis的代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单;
 
主从复制:redis也可做到类似于MySQL数据库的主从复制;
 
支持高可用和分布式。
 
#redis典型应用场景
session共享:常见于web集群中的Tomcat或者php中多web服务器session共享;
 
缓存:数据查询、电商网站商品信息和新闻内容等;
 
计数器:访问排行榜、商品浏览数这些与次数相关的数值统计场景;
 
微博/微信社交场合:共同好友、粉丝数、点赞、关注和评论等;
 
消息队列:ELK的日志缓存、部分业务的订阅发布系统;
 
地理位置:基于GEO(地理信息定位),实现摇一摇、附近的人和外卖等功能。

  

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

RDB文件是紧凑的二进制文件,比较适合做冷备,全量复制的场景。
 
RDB做会生成多个文件,每个文件都代表了某一个时刻的Redis完整的数据快照;
RDB这种多个数据文件的方式,非常适合做冷备,因为大量的一个个的文件,可以每隔一定的时间,复制出来;
可以将这种完整的数据文件发送到一些远程的云服务、分布式存储上进行安全的存储,以预定好的备份策略来定期备份Redis中的数据;
AOF也可以做冷备,只有一个文件,但是你可以写个脚本,每隔一定时间,去copy一份这个文件出来,相对比较麻烦,不推荐;
 
由Redis去控制固定时长生成快照文件的事情,比较方便;
 
AOF,还需要自己写一些脚本去做这个事情,各种定时;
RDB数据做冷备,在最坏的情况下,提供数据恢复的时候,速度比AOF快;
 
相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复Redis进程,更加快速;
 
AOF,存放的指令日志,做数据恢复的时候,其实是要回放和执行所有的指令日志,来恢复出来内存中的所有数据的;
RDB,就是一份数据文件,恢复的时候,直接加载到内存中即可;
RDB的时候,Redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可;
 
RDB对Redis对外提供的读写服务,影响非常小,可以让Redis保持高性能,因为Redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可;
 
RDB每次写,都是直接写Redis内存,只是在一定的时候,才会将数据写入磁盘中;
AOF,每次都是要写文件的,虽然可以快速写入os cache中,但是还是有一定的时间开销的,速度肯定比RDB略慢一些;
 
RDB使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能 ;

  

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

#哨兵的前提是已经实现了一个redis的主从复制的运行环境,从而实现一个一主两从基于哨兵的高可用redis架构
注意:master 的配置文件中masterauth 和slave 都必须相同
 
#在所有主从节点执行
vim /apps/redis/etc/redis.conf
bind 0.0.0.0
masterauth 123456
requirepass 123456
 
#在所有从节点执行
vim /apps/redis/etc/redis.conf
replicaof 10.0.0.7 6379
 
#在所有主从节点执行
systemctl restart redis.service
 
 
#编辑哨兵的配置文件
Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持。默认监听在26379/tcp端口
哨兵可以不和Redis服务器部署在一起,但一般部署在一起以节约成本
所有redis节点使用相同的以下示例的配置文件
 
#如果是编译安装,在源码目录有sentinel.conf,复制到安装目录即可,如:/apps/redis/etc/sentinel.conf
cp sentinel.conf /apps/redis/etc/
vim /apps/redis/etc/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 10.0.0.7 6379 2
#mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口
#2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有
sentinel节点(一般总数是>=3的奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,
取整为2,是master的ODOWN客观下线的依据
 
sentinel auth-pass mymaster 123456
#mymaster集群中master的密码,注意此行要在上面行的下面
 
sentinel down-after-milliseconds mymaster 3000
#(SDOWN)判断mymaster集群中所有节点的主观下线的时间,单位:毫秒,建议3000
 
sentinel parallel-syncs mymaster 1
#发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力
 
sentinel failover-timeout mymaster 180000
#所有slaves指向新的master所需的超时时间,单位:毫秒
 
sentinel deny-scripts-reconfig yes  #禁止修改脚本
 
scp /apps/redis/etc/sentinel.conf 10.0.0.17:/apps/redis/etc/
scp /apps/redis/etc/sentinel.conf 10.0.0.27:/apps/redis/etc/
 
#如果是编译安装在所有节点生成新的service文件
vim /lib/systemd/system/redis-sentinel.service
[Unit]
Description=Redis Sentinel
After=network.target
 
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
 
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
 
[Install]
WantedBy=multi-user.target
 
scp /lib/systemd/system/redis-sentinel.service 10.0.0.17:/lib/systemd/system/redis-sentinel.service
scp /lib/systemd/system/redis-sentinel.service 10.0.0.27:/lib/systemd/system/redis-sentinel.service
 
#注意所有节点的目录权限,否则无法启动服务
chown -R redis.redis /apps/redis/
#重新加载配置文件
systemctl daemon-reload
 
#如果是编译安装,在所有哨兵服务器执行下面操作启动哨兵
/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf
 
#停止Redis Master 节点测试故障转移
systemctl stop redis.service
 
#查看各节点哨兵信息
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=10.0.0.27:6379,slaves=2,sentinels=3
 
#10.0.0.27 slave2自动切换为master
 
故障转移后redis.conf中的replicaof行的master IP会被修改
grep ^replicaof /apps/redis/etc/redis.conf
replicaof 10.0.0.27 6379
 
哨兵配置文件的sentinel monitor IP 同样也会被修改
grep "monitor mymaster" /apps/redis/etc/sentinel.conf
sentinel monitor mymaster 10.0.0.27 6379 2  #自动修改此行

  

posted @   এ蓝桉、  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示