第二十周--作业
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 #自动修改此行 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通