linux运维20

一、总结tomcat优化方法

  1. 修改JVM虚拟机启动参数进行优化。
    因为tomcat运行实际是相当于用java程序运行了一台JVM虚拟机,所以可以通过修改Java的启动参数进行优化。如在启动脚本catalina.sh里面修改优化后的内存参数。
    java参数文档:java8参数文档
JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限
-XX:NewSize=:新生代空间初始化大小
-XX:MaxNewSize=:新生代空间最大值
  1. 修改server.xml的文件修改connector连接器参数,优化tomcat的service组件和engine组件。
常用属性:
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

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

  1. OOM是什么?
    OOM(Out Of Memory):中文意思就是内存用完了。java程序工作时都要在java环境里创建JVM虚拟机,当JVM虚拟机的内存被用完时,就会出现OOM。
  2. 出现OOM的原因:
    (1)JVM的虚拟机内存分配太小:比如:java程序需要的内存需要200M内存才能启动,但是JVM虚拟机的内存只有100M,程序想要运行运行不了。
    (2)java程序的内存的回收机制没能及时回收内存空间,程序申请新的内存空间没有足够的空间进行分配,也就是入不敷出。
  3. OOM衍生的术语:
    (1)内存溢出:java程序申请的内存时,JVM虚拟机没有足够的内存给java程序,这个就是内存溢出。
    (2)内存泄露:java程序申请了一段内存,但是java没有及时释放内存,其他程序想要使用内存时无内存可以使用。

java内存溢出演示:
Java编译安装:
Java 8的源码包需要注册账户后才能下载:Java下载

tar xf jdk-8u301-linux-x64.tar.gz -C /usr/local/ 解压下载的压缩包
cd /usr/local/
ln -s jdk1.8.0_301/ jdk
vi /etc/profile.d/java.sh
编辑环境变量
export JAVA_HOME=/usr/local/jdk
export PATH=$PATH:$JAVA_HOME/bin
export JRE_HOME=$JAVA_HOME/jre 
export CLASSPATH=$JAVA_HOME/lib/:$JRE_HOME/lib: #这个冒号必须要添加

source /etc/profile.d/java.sh
java -version

创建java的oom脚本

vi test.java
import java. util. Random;
public class test {
    
    
    public static void main(String[] args) {
    
    
        String str = "this is a test";
        while (true){
    
    
            str += str + new Random().nextInt(88888888);
        }
    }
}

javac test.java  转换为字节码(二进制文件),也就是生成class文件
java -Xms100m -Xmx100m -XX:+PrintGCDetails test  不用指定文件名,但是要指定名字,然后创建JVM虚拟机
-Xms100m       设置虚拟机初始内存大小
-Xmx100m       设置Java堆最大使用大小
-XX:+PrintGCDetails  在前台输出运行日志

因为while这个死循环,脚本不断申请内存空间,从而造成内存溢出。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

通过工具扫描java代码,从而解决OOM问题
在服务器上生成代码错误日志

java  -Xms100m -Xmx100m -XX:+HeapDumpOnOutOfMemoryError test

-XX:+HeapDumpOnOutOfMemoryError这个参数就是将日志导出到当前目录下

ls 可以看到生成了java_pid22866.hprof文件,将这个文件传送到客户端

在这里插入图片描述
在客户端下载jprofiler工具
jprofiler工具可以进行java代码扫描,协助开发人员找到有问题的代码行。
jprofiler下载地址:jprofiler
下载工具进行代码扫描
在这里插入图片描述
安装完成后,可以看到文件可以直接打开
在这里插入图片描述

在这里插入图片描述

选择线程转储,可以看到是代码的第6行出了问题,一般就是在这个行上下部分。
查看代码可以看到是因为while死循环导致的报错。

代码文件:
import java. util. Random;
public class test {
    
    
    public static void main(String[] args) {
    
    
        String str = "this is a test";
        while (true){
    
    
            str += str + new Random().nextInt(88888888);  #也就是这行
        }
    }
}

在这里插入图片描述

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

redis官网:redis
redis配置文件介绍:redis配置文件

redis特点:

  1. 基于内存实现缓存,速度快,单机可达10W并发
  2. 单线程模式,避免线程来回切换造成造成阻塞(redis6.0及以上版本不是单线程)
  3. 数据可持久化,可以将内存的数据保存到硬盘上
  4. 支持多种数据结构,比如集合,哈希,列表等方式
  5. 支持多种编程语言
  6. 源代码开源且代码量小,支持二次开发
  7. 可以实现主从复制,防止数据丢失
  8. 支持高可用和分布式,性能高

redis应用场景:

  1. web集群服务器之间的session共享
  2. 电商网站,数据查询,新闻内容等场景下的缓存实现
  3. 适合点击榜,商品浏览次数榜,访问排行榜等计数统计场景
  4. 消息队列:ELK日志缓存,业务订阅发布系统
  5. 基于GEO(地理信息定位)实现附近的人,外卖 ,摇一摇等功能
  6. 可以实现微博或微信的粉丝数,共同好友,点赞等功能

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

redis的RDB模式(默认模式,快照模式)

  1. 工作原理:

在这里插入图片描述

  1. 工作模式:
  • save: 同步,会阻塞其它命令,不推荐使用
  • bgsave: 异步后台执行,不影响其它命令的执行
  • 自动: 自动进行快照
  1. 优点:
  • 基于时间进行快照,保留时间点
  • 恢复速度快
  • 快照时,父进程不用做I/O操作,子进程处理I/O工作,性能较好
  1. 缺点:
  • 不能实时保存数据,恢复时只能基于上次时间点进行的快照

  • 快照时父进程不能进行I/O操作,如数据量太大可能会影响用户体验

  1. 配置参数:
redis.conf                           配置文件
文件参数
dbfilename dump.rdb                  数据库文件名
dir /var/lib/redis                   数据库保存路径
save 900 1                           900秒有一个key发送变化就进行快照
save 300 10                          300秒有一个key发送变化就进行快照
save 60 10000                        60秒有10000key发生变化就进行快照
stop-writes-on-bgsave-error no       空间满的时候是否禁止写入redis数据,最好设为no
rdbcompression yes                   是否压缩rdb文件
rdbchecksum yes                      是否校验rdb文件

手动后台生成RDB文件方式:
默认是根据上面的save规则进行快照

redis-cli -h 127.0.0.1 -a '123456' bgsave    创建后台备份,-a指定密码,没有设则不用指定
ll /var/lib/redis/                           查看生成的快照文件

在这里插入图片描述

redis的AOF模式(实时备份模式,默认不开启)

  1. 工作原理:

在这里插入图片描述

  1. 工作模式:
  • 手动:命令行执行
  • 自动:默认模式,根据规则自动触发生成
  1. 优点:
  • 实时保存数据,避免数据丢失
  • 有自动保护机制,不会因为断电而破坏数据
  • 数据以redis命令行方式保存,方便数据重建
  • 重写机制,减少磁盘空间使用率。从redis的2.4版本后才有
  1. 缺点:
  • 记录全部操作,部分重写也会记录,加大磁盘空间使用率
  • 恢复速度比ROF文件慢
  • 实时写入,加大磁盘I/O使用率
  1. 配置参数
redis.conf                             配置文件
文件参数
appendonly yes                        是否开启AOF模式
appendfilename "appendonly.aof"       AOF文件名字
appendfsync everysec                  是否设置自动写入数据,不是则为no
dir /var/lib/redis                    AOF文件存放路径
no-appendfsync-on-rewrite no          是否立刻将数据写入磁盘
auto-aof-rewrite-percentage 100       设置到多少条数据后自动重写AOF文件,0为不重写
auto-aof-rewrite-min-size 64mb        设置AOF文件保存最大值
aof-load-truncated yes                是否加载断电或其他中断后的异常数据

手动后台生成AOF文件:
redis-cli -h 127.0.0.1 -a ‘123456’ bgrewriteaof
在这里插入图片描述

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

sentinel(哨兵)机制:

  1. 多个哨兵交叉发现并且确认redis主节点故障
  2. 选举一个新的哨兵作为领导
  3. 选举一个新的从节点成为主节点
  4. 通知其他从节点记录新的主节点的信息
  5. 通知客户端主从变化
  6. 等待老的主节点修复后将其修改为从节点

因为是交叉确认是否故障,所以redis的主从需要3台或者3台以上的服务器。

3台初始化环境:

cd /etc/yum.repos.d/
yum install -y wget
wget http://mirrors.aliyun.com/repo/Centos-7.repo
wget http://mirrors.aliyun.com/repo/epel-7.repo
mv CentOS-Base.repo CentOS-Base.repo.bak
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
yum clean all
yum makecache
systemctl stop firewalld
systemctl disable firewalld
sed -i 's/SELINUX=enforcing$/SELINUX=disabled/g' /etc/selinux/config
setenforce 0

3台redis都按照下面编译安装:

yum install -y gcc jemalloc-devel                             安装依赖包和环境
wget https://download.redis.io/releases/redis-5.0.7.tar.gz    下载源码包
tar xf redis-5.0.7.tar.gz                                     解压压缩包
cd redis-5.0.7                                                进入目录
make PREFIX=/usr/local/redis install                          编译并安装到目录下

将redis的工具定义到本地变量
echo 'PATH=/usr/local/redis/bin:$PATH' > /etc/profile.d/redis.sh  
source /etc/profile.d/redis.sh

创建redis的配置目录及其他目录
mkdir /usr/local/redis/{
    
    etc,log,data,run} -p

将源码包的配置文件复制到安装目录下
cp redis.conf /usr/local/redis/etc/

创建redis账户
useradd -r -s /sbin/nologin redis

把redis安装的目录及子目录权限设置为redis
chown redis.redis -R /usr/local/redis

添加redis服务到systemd守护进程,设置开机启动
vi /usr/lib/systemd/system/redis.service 
#添加下面内容
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
ExecReload=/bin/kill -s QUIT $MAINPID;/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf --supervised systemd
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target

systemctl daemon-reload                重新加载systemd配置文件
systemctl start redis                  启动redis
systemctl enable redis                 开启开机自启redis

redis搭建主从:
redis1主配置:

hostnamectl set-hostname redis1  设置主机名,方便查看,需要注销后重新登录生效
vi /usr/local/redis/etc/redis.conf  直接文件底部添加这些
bind 0.0.0.0
requirepass redis123456
masterauth redis123456

systemctl restart redis   重启服务,使配置生效

redis2从配置:

hostnamectl set-hostname redis2  设置主机名,方便查看,需要注销后重新登录生效
vi /usr/local/redis/etc/redis.conf  直接文件底部添加这些
bind 0.0.0.0
requirepass redis123456
masterauth redis123456
slaveof 192.168.116.130 6379 #设置为主redis的IP

systemctl restart redis

redis3从配置:

hostnamectl set-hostname redis3  设置主机名,方便查看,需要注销后重新登录生效
vi /usr/local/redis/etc/redis.conf  直接文件底部添加这些
bind 0.0.0.0
requirepass redis123456
masterauth redis123456
slaveof 192.168.116.130 6379 #设置为主redis的IP

systemctl restart redis

在redis-1主查看主从是否成功:

redis-cli -a redis123456 info replication
通过下面可以看到redis的角色是主,从节点2个,还有从节点的IP
role:master
connected_slaves:2
slave0:ip=192.168.116.132,port=6379,state=online,offset=252,lag=0
slave1:ip=192.168.116.133,port=6379,state=online,offset=252,lag=1

在这里插入图片描述
3个redis节点配置哨兵文件:

vi /usr/local/redis/etc/sentinel.conf   3台配置都是一样的
bind 0.0.0.0    #添加监听地址
daemonize yes   #把no改为yes
logfile "/usr/local/redis/log/redis-sentinel.log" #修改日志路径
dir /usr/local/redis/data/   #修改数据目录
sentinel monitor mymaster 192.168.116.130 6379 2  #修改为主节点的IP,2为全部节点除以2,然后取整数。如3台服务器/2为1.5台,取整数为2
sentinel auth-pass mymaster redis123456  #设置哨兵密码

vi /usr/lib/systemd/system/redis-sentinel.service   创建哨兵service
[Unit]
Description=redis-sentinel
After=network.target
[Service]
ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/killall redis-sentinel
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
[Unit]
Description=Redis Sentinel
After=network.target

systemctl daemon-reload
systemctl start redis-sentinel
ss -tnl

在这里插入图片描述

redis1查看哨兵状态

redis-cli -a bigone1234 -p 26379 info sentinel

在这里插入图片描述
故障测试:
在redis1关闭redis服务

systemctl stop redis 

在这里插入图片描述

等待一会后,可以在redis2或者redis3看到新的主节点产生。
redis-cli -a redis123456 info replication   在redis3看到角色从slave变成了master,证明哨兵机制触发成功,redis3被选举成新的主节点。

在这里插入图片描述

在redis3的日志中可以看到
tail /usr/local/redis/log/redis-sentinel.log
在这句话 +switch-master mymaster 192.168.116.130 6379 192.168.116.133 6379   从这句可以看到因为主节点故障,redis3变成了主节点

6750:X 26 Dec 2021 15:09:24.203 # -odown master mymaster 192.168.116.130 6379
6750:X 26 Dec 2021 15:09:25.052 * +slave-reconf-inprog slave 192.168.116.132:6379 192.168.116.132 6379 @ mymaster 192.168.116.130 6379
6750:X 26 Dec 2021 15:09:25.052 * +slave-reconf-done slave 192.168.116.132:6379 192.168.116.132 6379 @ mymaster 192.168.116.130 6379
6750:X 26 Dec 2021 15:09:25.142 # +failover-end master mymaster 192.168.116.130 6379
6750:X 26 Dec 2021 15:09:25.142 # +switch-master mymaster 192.168.116.130 6379 192.168.116.133 6379
6750:X 26 Dec 2021 15:09:25.142 * +slave slave 192.168.116.132:6379 192.168.116.132 6379 @ mymaster 192.168.116.133 6379

在这里插入图片描述
在redis2查看日志:

tail /usr/local/redis/log/redis-sentinel.log
可以看到redis2和redis3都参加了选举,最终redis3变成了主节点

19571:X 26 Dec 2021 15:09:24.072 * +slave slave 192.168.116.132:6379 192.168.116.132 6379 @ mymaster 192.168.116.133 6379
19571:X 26 Dec 2021 15:09:24.072 * +slave slave 192.168.116.130:6379 192.168.116.130 6379 @ mymaster 192.168.116.133 6379
19571:X 26 Dec 2021 15:09:54.120 # +sdown slave 192.168.116.130:6379 192.168.116.130 6379 @ mymaster 192.168.116.133 6379

在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/DLWH_HWLD/article/details/122027707