赞
踩
案例说明
为解决memcached单点故障,需要实现memcached缓存的高可用。
首先,需要实现 Memcached的主主复制
指任意一台memcached服务器修改数据都会被同步到另外一台,但是memcached API无法判断连接哪一台服务器,因此需要VIP。
其次,通过 Keepalived 产生的VIP连接memcached服务器,提供高可用架构。
实验环境
- 一台centos7虚拟机作为memcache主服务器,IP地址:20.0.0.41
- 一台centos7虚拟机作为memcache从服务器,IP地址:20.0.0.42
- 一台centos7虚拟机作为memcache客户端,IP地址:20.0.0.43:
#关闭防火墙规则跟防护功能 [root@localhost ~]# iptables -F [root@localhost ~]# setenforce 0 #解压事件通知库到opt #Memcache 用到了 libevent 这个库用于 Socket 的处理,所以还需要安装 libevent [root@master ~]# tar zxvf libevent-2.1.8-stable.tar.gz -C /opt [root@master ~]# tar zxvf memcached-1.5.6.tar.gz -C /opt [root@master ~]# mkdir /opt/magent #从服务器不需要创建 [root@master ~]# tar zxvf magent-0.5.tar.gz -C /opt/magent/ #安装编译环境 [root@master ~]# yum install gcc gcc-c++ make -y [root@master ~]# cd /opt/libevent-2.1.8-stable/ [root@master libevent-2.1.8-stable]# ./configure --prefix=/usr #指定安装路径 #编译及安装 [root@master libevent-2.1.8-stable]# make && make install [root@master libevent-2.1.8-stable]# cd .. [root@master opt]# cd memcached-1.5.6/ ./configure \ --prefix=/usr/local/memcached \ --with-libevent=/usr/local/libevent #编译及安装 [root@slave memcache:d-1.5.6]# make && make install
[root@master memcached-1.5.6]# cd /opt/magent/ [root@master magent]# ls ketama.c ketama.h magent.c Makefile #修改magent配置文件 [root@master magent]# vim ketama.h '//修改前两个如下' #ifndef SSIZE_MAX #define SSIZE_MAX 32767 .......... #endif #修改Makefile配置文件 [root@master magent]# vim Makefile '//首行添加-lm' LIBS = -levent -lm #make编译 [root@master magent]# make gcc -Wall -O2 -g -c -o magent.o magent.c gcc -Wall -O2 -g -c -o ketama.o ketama.c gcc -Wall -O2 -g -o magent magent.o ketama.o -levent -lm #编译后会产生magent可执行程序 [root@master magent]# ls ketama.c ketama.h ketama.o magent magent.c magent.o Makefile #下载远程传输 这样从服务器就不需要修改了 [root@master magent]# yum install openssh-clients -y #将magent可执行程序复制到/usr/bin中 [root@master magent]# cp magent /usr/bin/ '//将magent可执行程序复制到从服务器的/usr/bin中' '//此命令需要输入yes,输入从服务器的密码才能将文件拷贝过去,根据提示操作即可' [root@master magent]# scp magent root@20.0.0.42:/usr/bin/
#主从服务器都需要安装
[root@master magent]# yum install keepalived -y
[root@slave keepalived]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived '//添加此段:定义了一个函数脚本' vrrp_script magent { '//脚本名字自定义' script "/opt/shell/magent.sh" '//脚本指定位置' interval 2 '//时间间隔' } global_defs { '//区域指定全局参数' notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id MAGENT_HA '//执行名称备用服务器不能一样' } vrrp_instance VI_1 { '//实例名称' state MASTER interface ens33 '//承载网络为VIP地址的物理接口' virtual_router_id 51 priority 100 '//优先级 备用服务器小于主服务器' advert_int 1 '//通告间隔秒数' authentication { auth_type PASS '//认证类型' auth_pass 1111 '//密码验证' } track_script { '//调用刚刚的函数在实例里面调用,调用名字' magent } virtual_ipaddress { 20.0.0.100 '//漂移地址' } } #下面全部删除
[root@slave bin]# cd /etc/keepalived/ [root@slave keepalived]# ls keepalived.conf '//备份配置文件【改名】,就不会被识别' [root@slave keepalived]# mv keepalived.conf keepalived.conf.bk #拷贝主服务器的kaeepalived配置文件到从服务器 [root@master magent]# scp /etc/keepalived/keepalived.conf root@20.0.0.42:/etc/keepalived root@20.0.0.42's password: #输入密码 keepalived.conf 100% 652 479.2KB/s 00:00 #下面这几项跟主服务器不一样 router_id MAGENT_HB '//id名和第一台要不一样,从服务器改为MAGENT_HB' state BACKUP '//从服务器为BACKUP' virtual_router_id 52 '//id号和第一台不一样即可' priority 90 '//优先级低与主服务器 '
上面keepalived.conf定义了函数定义脚本我们来创建
[root@master magent]# mkdir /opt/shell [root@master magent]# cd /opt/shell/ [root@master shell]# vim magent.sh #!/bin/bash K=`ps -ef | grep keepalived | grep -v grep | wc -l` if [ $K -gt 0 ]; then magent -u root -n 51200 -l 20.0.0.100 -p 12000 -s 20.0.0.41:11211 -b 20.0.0.42:11211 else pkill -9 magent fi '//如下解释' -n 51200 '//定义用户最大连接数' -l 20.0.0.100 '//指定虚拟IP' -p 12000 '//指定端口号' -s '//指定主缓存服务器20.0.0.41' -b '//指定从缓存服务器20.0.0.42' 11211 '//memcache端口号'
-d选项是作为守护进程在后台运行
-m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB,
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话
-p是设置Memcache监听的端口,我这里设置了12000,最好是1024以上的端口,
-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件
-vv是以very vrebose模式启动,将调试信息和错误输出到控制台
[root@master shell]# chmod +x magent.sh '//增加执行权限'
[root@master shell]# systemctl stop firewalld.service
[root@master shell]# systemctl start keepalived.service '//启动服务 稍微有点慢'
[root@master shell]# netstat -ntap | grep 12000
tcp 0 0 20.0.0.100:12000 0.0.0.0:* LISTEN 100623/magent
-m:指定缓存 -d:指定守护进程 -p:端口号
[root@master shell]# ln -s /usr/local/memcached/bin/* /usr/local/bin/
[root@master shell]# memcached -m 512k -u root -d -l 20.0.0.41 -p 11211
[root@master shell]# netstat -ntap |grep 11211
tcp 0 0 20.0.0.41:11211 0.0.0.0:* LISTEN 100207/memcached
'//设置从服务器'
[root@slave shell]# ln -s /usr/local/memcached/bin/* /usr/local/bin/
[root@slave shell]# memcached -m 512k -u root -d -l 20.0.0.42 -p 11211
[root@slave shell]# netstat -ntap |grep 11211
tcp 0 0 20.0.0.42:11211 0.0.0.0:* LISTEN 22510/memcached
'//主服务器测试' [root@master shell]# yum install telnet -y #安装Telnet远程程序 [root@master shell]# telnet 20.0.0.41 11211 Trying 20.0.0.41... #连接成功 Connected to 20.0.0.41. Escape character is '^]'. quit #quit Connection closed by foreign host. '//从服务器测试' [root@slave shell]# yum install telnet -y #安装Telnet [root@slave shell]# telnet 20.0.0.42 11211 Trying 20.0.0.42... Connected to 20.0.0.42. Escape character is '^]'. quit Connection closed by foreign host.
[root@tom03 ~]# yum install telnet -y #进行连接 [root@tom03 ~]# telnet 20.0.0.100 12000 Trying 20.0.0.100... Connected to 20.0.0.100. Escape character is '^]'. add shuai 0 0 4 '//客户端插入并新建一个数据' 1234 STORED #返回主服务器查看是否同步数据 [root@master shell]# telnet 20.0.0.41 11211 Trying 20.0.0.41... Connected to 20.0.0.41. Escape character is '^]'. get shuai '//查看数据' VALUE shuai 0 4 1234 END #从服务器进行验证 [root@slave shell]# telnet 20.0.0.42 11211 Trying 20.0.0.42... Connected to 20.0.0.42. Escape character is '^]'. get shuai '//查看数据' VALUE shuai 0 4 1234 END '//测试成功,主从都成功生成数据'
客户端直接访问多个 memcache 实例
优点:简单,未引入新的节点;
缺点:维护不方便,未实现集中管理;性能不满足,实例宕机后不能自动踢出(hash 到该实例的请求都要等到超时才能转到其他正常实例)。
'//宕机主服务器,看从服务器是否正常使用' [root@master shell]# systemctl stop keepalived.service '//关闭主服务器keepalived服务' #客户端登录 [root@tom03 ~]# telnet 20.0.0.100 12000 '//客户端登陆成功' Trying 20.0.0.100... Connected to 20.0.0.100. Escape character is '^]'. set niu 0 0 3 123 STORED '//从服务器验证' [root@slave shell]# telnet 20.0.0.42 11211 Trying 20.0.0.42... Connected to 20.0.0.42. Escape character is '^]'. get niu VALUE niu 0 3 123 END
Redis是一种流行的缓存数据库,它是开源的、高性能的、基于内存的数据存储系统,广泛应用于Web应用程序的缓存、消息队列、实时计算和持久化存储等方面。在使用Redis作为缓存数据库时,我们需要采取一些加固措施来保护数据的安全性和稳定性,以避免因为未经授权的访问、数据丢失或其他安全问题而导致的损失。以下是一些Redis缓存数据库加固措施:
描述:
Redis提供的访问控制、代码安全问题、选择恶意输入可从外部触发的攻击等功能,需要我们运维人员进行相应的配置提高安全性。
描述: Redis 不需要 root 权限即可运行,建议以仅用于此目的的非特权redis用户身份运行它,此种方式能最大程度防止CONFIG SET/GET 目录和其他类似运行时配置指令的可能性。
#设置一个单独的redis账户很有必要,redis crackit就利用到了root用户的特性来重置authorized_keys。首先创建一个redis账户,然后通过该账户启动。
$ useradd redis
$ setsid sudo -u redis redis-server /etc/redis.conf
$ ps -elf|grep redis #可以看到是redis用户启动
# 4 S root 9048 1 0 80 0 - 59753 poll_s 19:43 ? 00:00:00 sudo -u redis redis-server /etc redis.conf
# 4 S redis 9049 9048 0 80 0 - 38471 ep_pol 19:43 ? 00:00:00 redis-server
描述: 因为redis密码明文存储在配置文件中,所以我们需要限制redis文件目录访问权限,如设置redis的主目录权限为700(rwx------),如果redis.conf配置文件独立于redis主目录权限修过为600(rw-------)
# 文件权限
chmod 700 /opt/redis/redis-5.0.4/
chmod 600 /etc/redis.conf
# 所属者、组
chown redis:redis /etc/redis.conf
chown redis:redis /opt/redis/redis-5.0.4/
描述: 除了网络中受信任的客户端之外,每个人都应该拒绝访问 Redis 端口,因此运行 Redis 的服务器应该只能由使用 Redis 实现应用程序的计算机直接访问。
假如服务器有两个网络接口(一个A区域、一个B区域),如果只需要A区域的机器访问则只绑定到A区域网络接口中,如服务器自身访问则只绑定到本地回环接口上。
# 通过在redis.conf文件中添加如下一行,可以将 Redis 绑定到单个接口:
bind 127.0.0.1 192.168.1.200
Tips:注意除了您可以绑定IPV4以为你还可绑定IPV6
描述: 除了我们可以指定绑定的接口外,我们还可以更改默认的redis服务端口,可以防止黑客针对于Redis服务扫描探测。
# 将默认的服务断开从6379变成63791
port 63791
描述: 为Redis服务端设置一个认证密码是非常必须,下面讲解 Redis 配置密码认证的几种方式总结:
操作流程:
# 1.通过redis.conf文件中进行配置,此种方式修改后需要重启Redis。
vim /etc/redis.conf
requirepass WeiyiGeek # WeiyiGeek 即认证密码
masterauth WeiyiGeek # 配置主节点认证密码, 注意若master配置了密码则slave也要配置相应的密码参数否则无法进行正常复制的
# 2.通过命令行进行配置,此种方式的优点无需重启Redis。
redis 127.0.0.1:6379[1]> config set requirepass my_redis
OK
redis 127.0.0.1:6379[1]> config get requirepass
1) "requirepass"
2) "my_redis"
使用密码验证登陆Redis服务器:
# 方式1:密码明文会被记录到系统命令执行历史中(极其不推荐/不安全)
redis-cli -h 127.0.0.1 -p 6379 -a WeiyiGeek
# 方式2:交互式进行配置
redis-cli -h 127.0.0.1 -p 6379
redis 127.0.0.1:6379> auth WeiyiGeek # OK
非常注意: AUTH 命令与其他所有 Redis 命令一样,以未加密的方式发送,因此它无法防范对网络有足够访问权限以执行窃听的攻击者, 所以对应高敏感的数据建议配置TLS 支持(Redis 在所有通信通道上都可选地支持 TLS)以加密数据与命令传输。
描述: 我们可以禁用 Redis 中的命令或将它们重命名为不可猜测的名称,以便普通客户端仅限于指定的一组命令,比如漏洞就利用config/save两个命令完成攻击 。
由于redis无用户权限限制,建议将危险的命令使用rename配置项进行禁用或重命名,这样外部不了解重命名规则攻击者,就不能执行这类命令FLUSHDB, FLUSHALL, KEYS, PEXPIRE, DEL, CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, SREM, RENAME, DEBUG, EVAL
例如: 普通用户可能无法调用Redis CONFIG 命令来更改实例的配置,但提供和删除实例的系统应该能够这样做。
# redis.conf 配置文件
# 方式1.CONFIG / FLUSHALL命令被重命名为一个不可猜测的名称
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
rename-command FLUSHALL b840fc02d524045429941cc15f59e41cb7be6c53
# 方式2.通过将其重命名为空字符串来完全禁用它(或任何其他命令)
rename-command CONFIG ""
rename-command FLUSHALL ""
Tips: 注意配置后需要重新redis-server服务。
描述: 为Redis创建访问(或Debug)日志(根据需求设置),在建立Redis蜜罐时,如果有攻击尝试时,就开业及时发现监控redis安全状态, 以及可以监控cmdstat_*指标信息报警;
# 执行info commandstats 看出命令执行的次数、命令耗费的 CPU 时间(单位毫秒)、执行每个命令耗费的平均 CPU 时间(单位毫秒)
cmdstat_get:calls=2,usec=15,usec_per_call=7.50
cmdstat_select:calls=1,usec=9,usec_per_call=9.00
cmdstat_keys:calls=4,usec=1948,usec_per_call=487.00
cmdstat_auth:calls=3123,usec=8291,usec_per_call=2.65
日志记录配置:
logfile "/usr/local/redis/redis.log" #日志文件存放目录
loglevel verbose #记录访问信息
描述: Redis 协议没有字符串转义的概念,所以一般情况下使用普通客户端库是不可能注入的, 但有可能会通过EVAL和EVALSHA命令执行的 Lua 脚本来构造恶意脚本。
> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
解决办法: 应用程序应该避免使用从不受信任的来源获得的字符串来组成 Lua 脚本的主体。
Tips : EVALSHA 通过其 SHA1 摘要评估缓存在服务器端的脚本。脚本使用SCRIPT LOAD命令缓存在服务器端。该命令在其他方面与EVAL相同。
描述: 有可能攻击者构造恶意的数据结构插入到 Redis 数据库中, 这可能会触发Redis 内部实现的数据结构的病态(最坏情况)算法复杂性。
例如,攻击者可以通过 Web 表单将一组已知散列到同一桶的字符串提供到散列表中,以便将 O(1)预期时间(平均时间)变为O(N )最坏的情况,消耗比预期更多的 CPU,并最终导致拒绝服务。
解决办法: 为了防止这种特定的攻击,Redis 对哈希函数使用了每次执行的伪随机种子。
描述: 前面针对Redis-server服务层面进行安全配置,此处针对网络层面进行限制,只允许指定的IP地址进行访问,在主机上配置防火墙的优点是防止同一网段的东西流量。
在Linux上系统防火墙设置命令:
iptables -A INPUT -s x.x.x.x -p tcp --dport 6379 -j ACCEPT #如果需要其他机器访问或者设置了slave模式,那就记得加上相应的防火墙设置(Centos6)
firewall-cmd --add-rich-rule="rule family="ipv4" source address="x.x.x.x" port protocol="tcp" port="6379" accept" --permanent #(Centos7)
在Windows上系统防火墙设置命令:
New-NetFirewallRule -Name "redis-server-access" -DisplayName "redis-server" -Description "redis-server 客户端访问防火墙规则" -Direction Inbound -LocalPort 6379 -RemoteAddress x.x.x.x -Protocol TCP -Action Allow -Enabled True
Get-NetFirewallRule -Name "redis-server-access" | Format-Table
描述: Redis设计旨在提供高性能的KV服务,至少目前在权限访问控制和数据持久化方面比较弱化,所以从应用层面上,不建议使用Redis来存储敏感信息,例如鉴权的密码。
安全配置示例:
# 配置文件 vim /etc/redis/redis.conf # 1.信任的内网运行,尽量避免有公网访问(如果存在内网中其他固定IP则需要设置防火墙) bind 127.0.0.1 # 2.绑定redis监听的网络接口(通过redis配置项bind,可同时绑定多个IP), 把6379改为其他得端口(或者采用unix管道进行数据管理) port 63791 # 3.开启redis密码认证,并设置高复杂度密码设置,因查询效率高,auth这种命令每秒能处理10w次以上(所以需要增加强度) # echo -e "weiyigeek"|sha256sum requirepass 097575a79efcd7ea7b1efa2bcda78a4fc7cbd0820736b2f2708e72c3d21f8b61 # 4.日志文件存放目录以及记录redis访问信息。 # debug (a lot of information, useful for development/testing) # verbose (many rarely useful info, but not a mess like the debug level) # notice (moderately verbose, what you want in production probably) 默认 # warning (only very important / critical messages are logged) logfile "/usr/local/redis/redis.log" loglevel verbose # 5.默认情况下,启用保护模式。只有在以下情况下才应禁用(no)它 # - 您确定希望其他主机的客户端连接到Redis # - 即使没有配置身份验证,也没有特定的接口集 # - 使用“bind”指令显式列出。 protected-mode yes # 6.重命名特殊命令(根据需求) # `FLUSHDB, FLUSHALL, KEYS, PEXPIRE, DEL, CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, SREM, RENAME, DEBUG, EVAL` rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 rename-command FLUSHDB b840fc02d524045429941cc15f59e41cb7be6c53 rename-command FLUSHALL b840fc02d524045429941cc15f59e41cb7be6c54 rename-command EVAL b840fc02d524045429941cc15f59e41cb7be6c55 rename-command DEBUG b840fc02d524045429941cc15f59e41cb7be6c56 rename-command SHUTDOWN b840fc02d524045429941cc15f59e41cb7be6c7
#配置文件 [root@centos7 ~]#vim /apps/redis/etc/redis.conf save "" dbfilename dump_6379.rdb dir "/data/redis" appendonly no #脚本 [root@centos8 ~]#cat redis_backup_rdb.sh #!/bin/bash # #******************************************************************** #Author: wangxiaochun #QQ: 29308620 #Date: 2020-10-21 #FileName: redis_rdb.sh #URL: http://www.wangxiaochun.com #Description: The test script #Copyright (C): 2020 All rights reserved #******************************************************************** BACKUP=/backup/redis-rdb DIR=/data/redis FILE=dump_6379.rdb PASS=123456 color () { RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL}G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$1" && $MOVE_TO_COL echo -n "[" if [ $2 = "success" -o $2 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $2 = "failure" -o $2 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo } redis-cli -h 127.0.0.1 -a $PASS --no-auth-warning bgsave result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'` until [ $result -eq 0 ] ;do sleep 1 result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'` done DATE=`date +%F_%H-%M-%S` [ -e $BACKUP ] || { mkdir -p $BACKUP ; chown -R redis.redis $BACKUP; } cp $DIR/$FILE $BACKUP/dump_6379-${DATE}.rdb color "Backup redis RDB" 0 #执行 [root@centos8 ~]#bash redis_backup_rdb.sh Background saving started Backup redis RDB [ OK ] [root@centos8 ~]#ll /backup/redis-rdb/ -h total 143M -rw-r--r-- 1 redis redis 143M Oct 21 11:08 dump_6379-2020-10-21_11-08-47.rdb
范例: 观察save 和 bgsave的执行过程
#阻塞
#生成临时文件
[root@centos7 ~]#(redis-cli -a 123456 save &) ; echo save is finished; redis
cli -a 123456 get class
范例: 自动保存
[root@centos7 ~]#vim /apps/redis/etc/redis.conf
save 60 3
#测试60s内修改3个key,验证是否生成RDB文件
前言
AOF 即 AppendOnlyFile,AOF 和 RDB 都采有COW(copy on write–数据变了才去复制)机制,AOF可以指定不同的保存策略,默认为每秒钟
执行一次 fsync,按照操作的顺序地将变更命令追加至指定的AOF日志文件尾部
在第一次启用AOF功能时,会做一次完全备份,后续将执行增量性备份,相当于完全数据备份+增量变化
如果同时启用RDB和AOF,进行恢复时,默认AOF文件优先级高于RDB文件,即会使用AOF文件进行恢复
在第一次开启AOF功能时,会自动备份所有数据到AOF文件中,后续只会记录数据的更新指令
注意: AOF 模式默认是关闭的,第一次开启AOF后,并重启服务生效后,会因为AOF的优先级高于RDB,而AOF默认没有数据文件存在,从而导致所有数据丢失
范例: 错误开启AOF功能,会导致数据丢失
[root@ubuntu1804 ~]#redis-cli
127.0.0.1:6379> dbsize
(integer) 10010011
[root@ubuntu1804 ~]#vim /apps/redis/etc/redis.conf
appendonly yes #修改此行
[root@ubuntu1804 data]#systemctl restart redis
[root@ubuntu1804 ~]#redis-cli
127.0.0.1:6379> dbsize
(integer) 0
范例: 正确启用AOF功能,访止数据丢失
[root@centos8 ~]#ll /var/lib/redis/ total 314392 -rw-r--r-- 1 redis redis 187779391 Oct 17 14:23 dump.rdb [root@centos8 ~]#redis-cli 127.0.0.1:6379> config get appendonly 1) "appendonly" 2) "no" 127.0.0.1:6379> config set appendonly yes #自动触发AOF重写,会自动备份所有数据到AOF文 件 OK [root@centos8 ~]#ll /var/lib/redis/ total 314392 -rw-r--r-- 1 redis redis 187779391 Oct 17 14:23 dump.rdb -rw-r--r-- 1 redis redis 85196805 Oct 17 14:45 temp-rewriteaof-2146.aof [root@centos8 ~]#ll /var/lib/redis/ total 366760 -rw-r--r-- 1 redis redis 187779391 Oct 17 14:45 appendonly.aof -rw-r--r-- 1 redis redis 187779391 Oct 17 14:23 dump.rdb [root@centos8 ~]#vim /etc/redis.conf appendonly yes #改为yes #config set appendonly yes 后可以同时看到下面显示
mysql的binlog同步两种规则一是立即写磁盘,二是不会立即写到磁盘会写到操作系统的缓冲区,由操作系统决定什么时候写到磁盘
appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能
appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中
appendfsync everysec #aof持久化策略的配置
#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值(1秒钟刷新一次磁盘)
dir /path
#rewrite相关
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
将一些重复的,可以合并的,过期的数据重新写入一个新的AOF文件,从而节约AOF备份占用的硬盘空间,也能加速恢复过程
可以手动执行bgrewriteaof 触发AOF,第一次开启AOF功能,或定义自动rewrite 策略
AOF rewrite 过程
AOF rewrite 重写相关配置(直接写磁盘,缓冲区–效率、写多少百分比、写大小、是否加载由于某些原因导致的末尾异常)
同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制
no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步
策略,主要考虑磁盘IO开支和请求阻塞时间。
#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要
忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不
会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux
的默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐
#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间
auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表
示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据
清理后不满足64Mb重写大小会增长一倍100%--128Mb继续清理变成100M,下次变成200Mb再清理
auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小
aof-load-truncated yes #是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),
建议yes
BGREWRITEAOF
时间复杂度: O(N), N 为要追加到 AOF 文件中的数据数量。
执行一个 AOF文件 重写操作。重写会创建一个当前 AOF 文件的体积优化版本。
即使 BGREWRITEAOF 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 BGREWRITEAOF 成功之
前不会被修改。
重写操作只会在没有其他持久化工作在后台执行时被触发,也就是说:
如果 Redis 的子进程正在执行快照的保存工作,那么 AOF 重写的操作会被预定(scheduled),等到保存
工作完成之后再执行 AOF 重写。在这种情况下, BGREWRITEAOF 的返回值仍然是 OK ,但还会加上一条
额外的信息,说明 BGREWRITEAOF 要等到保存操作完成之后才能执行。在 Redis 2.6 或以上的版本,可
以使用 INFO [section] 命令查看 BGREWRITEAOF 是否被预定。
如果已经有别的 AOF 文件重写在执行,那么 BGREWRITEAOF 返回一个错误,并且这个新的
BGREWRITEAOF 请求也不会被预定到下次执行。
从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。
范例: 手动 bgrewriteaof
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
#同时可以观察到下面显示`
如果主要充当缓存功能,或者可以承受较长时间,比如数分钟数据的丢失, 通常生产环境一般只需启用RDB即可,此也是默认值
如果一点数据都不能丢失,可以选择同时开启RDB和AOF(金融业务)
一般不建议只开启AOF
参考资料:http://www.redis.cn/topics/data-types.html
相关命令参考: http://redisdoc.com/
字符串是一种最基本的Redis值类型。Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任意类型的数据,例如: 一张JPEG格式的图片或者一个序列化的Ruby对象。一个字符串类型的值最多能存储512M字节的内容。Redis 中所有 key 都是字符串类型的。此数据类型最为常用
Set 是一个无序的字符串合集,同一个集合中的每个元素是唯一无重复的,支持在两个不同的集合中对数据进行逻辑处理,常用于取交集,并集,统计等场景,例如: 实现共同的朋友
集合特点
Redis有序集合和Redis集合类似,是不包含相同字符串的合集。它们的差别是,每个有序集合的成员都关联着一个双精度浮点型的评分,这个评分用于把有序集合中的成员按最低分到最高分排序。有序集合的成员不能重复,但评分可以重复,一个有序集合中最多的成员数为 2^32 - 1=4294967295个,经常用于排行榜的场景
hash 即字典, 用于保存字符串字段field和字符串值value之间的映射,即key/value做为数据部分,hash特别适合用于存储对象场景.
一个hash最多可以包含2^32-1 个key/value键值对
哈希特点
消息队列: 把要传输的数据放在队列中,从而实现应用之间的数据交换
常用功能: 可以实现多个应用系统之间的解耦,异步,削峰/限流等
常用的消息队列应用: Kafka,RabbitMQ,Redis
消息队列分为两种
生产者消费者模式下,多个消费者同时监听一个频道(redis用队列实现),但是生产者产生的一个消息只能被最先抢到消息的一个消费者消费一次,队列中的消息由可以多个生产者写入,也可以有不同的消费者取出进行消费处理.此模式应用广泛
[root@redis ~]# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> LPUSH channel1 message1 #从管道的左侧写入
(integer) 1
127.0.0.1:6379> LPUSH channel1 message2
(integer) 2
127.0.0.1:6379> LPUSH channel1 message3
(integer) 3
127.0.0.1:6379> LPUSH channel1 message4
(integer) 4
127.0.0.1:6379> LPUSH channel1 message5
(integer) 5
127.0.0.1:6379> LRANGE channel1 0 -1
1) "message5"
2) "message4"
3) "message3"
4) "message2"
5) "message1"
127.0.0.1:6379> RPOP channel1 #基于实现消息队列的先进先出原则,从管道的右侧消费
"message1"
127.0.0.1:6379> RPOP channel1
"message2"
127.0.0.1:6379> RPOP channel1
"message3"
127.0.0.1:6379> RPOP channel1
"message4"
127.0.0.1:6379> RPOP channel1
"message5"
127.0.0.1:6379> RPOP channel1
(nil)
127.0.0.1:6379> LRANGE channel1 0 -1
(empty list or set) #验证队列中的消息全部消费完成
在发布者订阅者Publisher/Subscriber模式下,发布者Publisher将消息发布到指定的频道channel,事先监听此channel的一个或多个订阅者Subscriber都会收到相同的消息。即一个消息可以由多个订阅者获取到. 对于社交应用中的群聊、群发、群公告等场景适用于此模式
[root@redis ~]# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> SUBSCRIBE channel01 #订阅者事先订阅指定的频道,之后发布的消
息才能收到
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel01"
3) (integer) 1
127.0.0.1:6379> PUBLISH channel01 message1 #发布者发布信息到指定频道
(integer) 2 #订阅者个数
127.0.0.1:6379> PUBLISH channel01 message2
(integer) 2
[root@redis ~]#redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> SUBSCRIBE channel01
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel01"
3) (integer) 1
1) "message"
2) "channel01"
3) "message1"
1) "message"
2) "channel01"
3) "message2"
#订阅指定的多个频道
127.0.0.1:6379> SUBSCRIBE channel01 channel02
127.0.0.1:6379> PSUBSCRIBE * #支持通配符*
127.0.0.1:6379> PSUBSCRIBE chann* #匹配订阅多个频道
127.0.0.1:6379> unsubscribe channel01
1) "unsubscribe"
2) "channel01"
3) (integer) 0
Redis 常见应用场景
Zabbix 有两种工作模式: 主动和被动模式
无论是模式还是被动模式,都是站在zabbix agent 角度来说的工作模式
Zabbix 监控流程中 Agent 收集数据分为主动和被动两种模式
主动模式和被动模式都是相对 zabbix agent而言的
Zabbix默认是被动模式,如果有100个监控项,被动模式需要 Zabbix Server找 Zabbix Agent要100次(老师挨个收学生作业)
主动模式是Zabbix Server给 Zabbix Agent发送一个包括100个监控项的任务清单,Zabbix Agent根据任务清单,采集好100个监控项的值,主动汇报给 Zabbix Server这100个监控项,Zabbix Agent主动模式只需要发送一次数据,大大提高了传输效率。(老师给学生布置一些作业,学生根据作业清单主动交作业给老师)
注意: 两种模式可以在Zabbix Server上同时存在,可以将一部分监控项设为主动,其它设为被动模式(这样做原因是主动布置的作业难度比较大,老师虽然下发了但是学生可能没有全部完成)
被动监测通信过程如下:
Server打开一个TCP连接
Server发送请求agent.ping
Agent接收到请求并且响应
Server处理接收到的数据
关闭TCP连接
被动模式每获取一个监控项都需要打开一个tcp连接,这样当监控项越来越多时,Zabbix Server会打开很多端口,就会出现server端性能瓶颈问题。
主动模式监测通信过程如下:
zabbix agent 首先向ServerActive配置的IP请求获取active items,获取并提交active items数据值给server或者proxy。
zabbix多久获取一次active items?
它会根据agent的配置文件中的RefreshActiveChecks的频率进行,如果获取失败,那么将会在60秒之后重试。
被动模式是指 zabbix agent 被动的接受zabbix server(或者Zabbix Proxy)周期性发送过来的数据收集指令
此为默认的工作方式。
在被动模式之下,zabbix server会根据主机关联的模板中的监控项和数据采集间隔时间,周期性的打开随机端口并向zabbix agent服务器的10050端口发起tcp连接,然后发送获取监控项数据的指令,即zabbix server发送什么指令那么zabbix agent就收集什么数据,zabbix server什么时候发送指令,zabbix agent就什么时候采集,zabbix server不发送指令,zabbix agent就一直不响应,所以zabbix agent也不用关心其监控项和数据采集周期间隔时间。
被动模式的优点就是配置简单,安装后即可使用,因此也成为zabbix的默认工作模式,但是被动模式的最大问题就是会加大zabbix server的 负载,在数百甚至数千台服务器的环境下会导致zabbix server需要轮训向每个zabbix agent发送数据采集指令,如果zabbix server负载过高还会导致不能及时获取到最新数据
被动模式因为性能的原因,一台 **Zabbix Server 一般只能监控500台以下的主机,**更多的主机建议使用主动模式
Zabbix Server 通过Poller进程实现被动模式
[root@zabbix-server ~]#grep StartPollers /etc/zabbix/zabbix_server.conf #此数量可以适当进行调整 # StartPollers=5 [root@zabbix-server ~]#ps ax|grep poller 48 ? I< 0:00 [edac-poller] 1115 ? S 0:03 /usr/sbin/zabbix_server: http poller #1 [got 0 values in 0.000622 sec, idle 5 sec] 1246 ? S 0:01 /usr/sbin/zabbix_server: proxy poller #1 [exchanged data with 0 proxies in 0.000036 sec, idle 5 sec] 1249 ? S 0:19 /usr/sbin/zabbix_server: poller #1 [got 0 values in 0.000020 sec, idle 1 sec] 1250 ? S 0:19 /usr/sbin/zabbix_server: poller #2 [got 1 values in 0.003333 sec, idle 1 sec] 1251 ? S 0:19 /usr/sbin/zabbix_server: poller #3 [got 1 values in 0.001767 sec, idle 1 sec] 1252 ? S 0:19 /usr/sbin/zabbix_server: poller #4 [got 3 values in 0.002736 sec, idle 1 sec] ...
范例: 查看被动模式下 Zabbix agent 进程和端口打开情况
[root@centos8 ~]#grep StartAgents /etc/zabbix/zabbix_agentd.conf # StartAgents=3 #被动模式的进程数量,默认为3个,可以适当修改 [root@centos8 ~]#ps ax|grep zabbix 1793 ? S 0:00 /usr/sbin/zabbix_agentd -c /etc/zabbix/zabbix_agentd.conf 1794 ? S 2:44 /usr/sbin/zabbix_agentd: collector [idle 1 sec] 1795 ? S 0:12 /usr/sbin/zabbix_agentd: listener #1 [waiting for connection] 1796 ? S 0:12 /usr/sbin/zabbix_agentd: listener #2 [waiting for connection] 1797 ? S 0:12 /usr/sbin/zabbix_agentd: listener #3 [waiting for connection] 1798 ? S 0:10 /usr/sbin/zabbix_agentd: active checks #1 [idle 1 sec] 21213 pts/1 S+ 0:00 vim /etc/zabbix/zabbix_agentd.conf 24150 pts/0 S+ 0:00 grep --color=auto zabbix [root@centos8 ~]#ss -nta|grep 10050 LISTEN 0 128 0.0.0.0:10050 0.0.0.0:* TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48786 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48790 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48866 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48884 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48860 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48848 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48846 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48826 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48774 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48808 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48836 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48824 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48772 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48840 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48820 TIME-WAIT 0 0 10.0.0.103:10050 10.0.0.100:48886 ........ #被动模式下agent主机的日志中会提示以下错误 [root@centos8 ~]#tail /var/log/zabbix/zabbix_agentd.log 1414:20200830:180435.723 TLS support: YES 1414:20200830:180435.723 ************************** 1414:20200830:180435.723 using configuration file: /etc/zabbix/zabbix_agentd.conf 1414:20200830:180435.724 agent #0 started [main process] 1415:20200830:180435.724 agent #1 started [collector] 1416:20200830:180435.725 agent #2 started [listener #1] 1419:20200830:180435.725 agent #4 started [listener #3]
主动模式是由每个zabbix agent 打开本机的随机端口, 主动向 Zabbix Server (或者Zabbix Proxy)的10051端口发起tcp连接请求
主动模式下必须在zabbix agent配置文件中指定zabbix server的IP或者主机名(必须可以被解析为IP地址),在连接到zabbix server之前zabbix agent是不知道自己要采集那些数据以及间隔多久采集一次数据的,然后在连接到zabbix server以后获取到自己的监控项和数据采集间隔周期时间,然后再根据监控项采集数据并返回给zabbix server,在主动模式下不再需要zabbix server向zabbix agent发起连接请求,因此主动模式在一定程度上可减轻zabbix server打开的本地随机端口和进程数,在一定程度就减轻了zabbix server的压力。经过优化后可以轻松监控2000台,甚5000以上的主机
以下场景下生产推荐使用主动模式
Zabbix 不支持直接监控JAVA应用
如果要监控JAVA程序比如Tomcat等,需要使用 Java gateway 做为代理,才能从JAVA应用中获取数据
Zabbix Java gateway 能过监听10052/tcp 端口实现监控JAVA应用
Zabbix 监控JVM流程
Zabbix Java Gateway 架构
范例: 安装tomcat脚本
[root@tomcat ~]#cat install_tomcat.sh #!/bin/bash # #******************************************************************** #Author: wangxiaochun #QQ: 29308620 #Date: 2021-03-15 #FileName: install_tomcat.sh #URL: http://www.wangxiaochun.com #Description: The test script #Copyright (C): 2021 All rights reserved #******************************************************************** DIR=`pwd` JDK_FILE="jdk-8u291-linux-x64.tar.gz" TOMCAT_FILE="apache-tomcat-9.0.48.tar.gz" JDK_DIR="/usr/local" TOMCAT_DIR="/usr/local" color () { RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL}G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$2" && $MOVE_TO_COL echo -n "[" if [ $1 = "success" -o $1 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $1 = "failure" -o $1 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo } install_jdk(){ if ! [ -f "$DIR/$JDK_FILE" ];then color 1 "$JDK_FILE 文件不存在" exit; elif [ -d $JDK_DIR/jdk ];then color 1 "JDK 已经安装" exit else [ -d "$JDK_DIR" ] || mkdir -pv $JDK_DIR fi tar xvf $DIR/$JDK_FILE -C $JDK_DIR cd $JDK_DIR && ln -s jdk1.8.* jdk cat > /etc/profile.d/jdk.sh <<EOF export JAVA_HOME=$JDK_DIR/jdk export JRE_HOME=\$JAVA_HOME/jre export CLASSPATH=\$JAVA_HOME/lib/:\$JRE_HOME/lib/ export PATH=\$PATH:\$JAVA_HOME/bin EOF . /etc/profile.d/jdk.sh java -version && color 0 "JDK 安装完成" || { color 1 "JDK 安装失败" ; exit; } } install_tomcat(){ if ! [ -f "$DIR/$TOMCAT_FILE" ];then color 1 "$TOMCAT_FILE 文件不存在" exit; elif [ -d $TOMCAT_DIR/tomcat ];then color 1 "TOMCAT 已经安装" exit else [ -d "$TOMCAT_DIR" ] || mkdir -pv $TOMCAT_DIR fi tar xf $DIR/$TOMCAT_FILE -C $TOMCAT_DIR cd $TOMCAT_DIR && ln -s apache-tomcat-*/ tomcat echo "PATH=$TOMCAT_DIR/tomcat/bin:"'$PATH' > /etc/profile.d/tomcat.sh id tomcat &> /dev/null || useradd -r -s /sbin/nologin tomcat cat > $TOMCAT_DIR/tomcat/conf/tomcat.conf <<EOF JAVA_HOME=$JDK_DIR/jdk EOF chown -R tomcat.tomcat $TOMCAT_DIR/tomcat/ cat > /lib/systemd/system/tomcat.service <<EOF [Unit] Description=Tomcat #After=syslog.target network.target remote-fs.target nss-lookup.target After=syslog.target network.target [Service] Type=forking EnvironmentFile=$TOMCAT_DIR/tomcat/conf/tomcat.conf ExecStart=$TOMCAT_DIR/tomcat/bin/startup.sh ExecStop=$TOMCAT_DIR/tomcat/bin/shutdown.sh RestartSec=3 PrivateTmp=true User=tomcat Group=tomcat [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now tomcat.service &> /dev/null systemctl is-active tomcat.service &> /dev/null && color 0 "TOMCAT 安装完成" || { color 1 "TOMCAT 安装失败" ; exit; } } install_jdk install_tomcat [root@tomcat ~]#bash install_tomcat.sh
JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
JMX在Java编程语言中定义了应用程序以及网络管理和监控的体系结构、设计模式、应用程序接口以及服务。通常使用JMX来监控系统的运行状态或管理系统的某些方面,比如清空缓存、重新加载配置文件等
tomcat 开启远程 JMX 环境配置
vim /usr/local/tomcat/bin/catalina.sh
CATALINA_OPTS="$CATALINA__OPTS
-Dcom.sun.management.jmxremote #启用远程监控JMX
-Djava.rmi.server.hostname=<JAVA主机IP> #是tomcat主机自己的IP地址,不是
zabbix服务器的地址
-Dcom.sun.management.jmxremote.port=XXXXX #默认启动的JMX端口号,要和
zabbix添加主机时候的端口一致即可
-Dcom.sun.management.jmxremote.authenticate=false #不使用用户名密码
-Dcom.sun.management.jmxremote.ssl=false" #不使用ssl认证
范例: Tomcat 开启 JMX 功能
[root@tomcat ~]#vim /usr/local/tomcat/bin/catalina.sh ....... # ----------------------------------------------------------------------------- #添加下一行 CATALINA_OPTS="$CATALINA__OPTS -Dcom.sun.management.jmxremote - Dcom.sun.management.jmxremote.port=12345 - Dcom.sun.management.jmxremote.authenticate=false - Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.0.0.106" # OS specific support. $var _must_ be set to either true or false. ....... #查看端口12345是否打开 [root@tomcat ~]#systemctl restart tomcat [root@tomcat ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 100 127.0.0.1:25 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 50 *:12345 *:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 50 *:38563 *:* LISTEN 0 1 [::ffff:127.0.0.1]:8005 *:* LISTEN 0 50 *:40613 *:* LISTEN 0 100 *:8080 *:*
cmdline-jmxclient-0.10.3.jar 是一个开源jar包,在zabbix 中常用于测试的一个工具,可以用来测试
jmx 是否配置正确。在监控方面后还可以对Tomcat各种属性进行监控。下面使用java客户端cmdlinejmxclient进行测试
下载链接
https://github.com/qiueer/zabbix/blob/master/Tomcat/cmdline-jmxclient-0.10.3.jar
范例: 测试能否获取到java当前线程数和最大线程数
#先下载cmdline-jmxclient-0.10.3.jar文件
[root@zabbix-server ~]#ll cmdline-jmxclient-0.10.3.jar
-rw-r--r-- 1 root root 20124 Aug 23 22:41 cmdline-jmxclient-0.10.3.jar
#测试能否获取到java当前线程数和最大线程数:
[root@zabbix-server ~]#yum -y install java
#Ubuntu安装下面包
[root@zabbix-server ~]#apt install openjdk-8-jdk -y
[root@zabbix-server ~]#java -jar cmdline-jmxclient-0.10.3.jar - 10.0.0.106:12345
'Catalina:name="http-nio-8080",type=ThreadPool' currentThreadCount
08/30/2020 13:27:07 +0800 org.archive.jmx.Client currentThreadCount: 10
#测试能否获取到java最大线程数:
[root@zabbix-server ~]#java -jar cmdline-jmxclient-0.10.3.jar - 10.0.0.106:12345
'Catalina:name="http-nio-8080",type=ThreadPool' maxThreads
08/30/2020 13:27:33 +0800 org.archive.jmx.Client maxThreads: 200
Java gateway 是一个独立于zabbix server和 zabbix agent的组件,默认使用端口10052/tcp, 所以java gateway可以是单独的一台服务器,但是也可以和zabbix server或者zabbix agent 共用一台服务器
Java gatway 可以用两种方法安装
范例: Ubuntu 安装
[root@ubuntu1804 ~]#wget https://repo.zabbix.com/zabbix/5.0/ubuntu/pool/main/z/zabbix-release/zabbixrelease_5.0-1+bionic_all.deb [root@ubuntu1804 ~]#dpkg -i zabbix-release_5.0-1+bionic_all.deb [root@ubuntu1804 ~]#sed -i 's#http://repo.zabbix.com#https://mirrors.aliyun.com/zabbix#' /etc/apt/sources.list.d/zabbix.list [root@ubuntu1804 ~]#apt update #安装依赖JDK会自动安装 [root@ubuntu1804 ~]#apt -y install zabbix-java-gateway #可以开启自身的JMX功能实现自身的监控(可选) [root@ubuntu1804 ~]#vim /etc/zabbix/zabbix_java_gateway.conf # uncomment to enable remote monitoring of the standard JMX objects on the Zabbix Java Gateway itself JAVA_OPTIONS="$JAVA_OPTIONS -Dcom.sun.management.jmxremote - Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false - Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.registry.ssl=false" #Ubuntu安装后会自动启动服务并打开监听10052/tcp端口 [root@ubuntu1804 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 127.0.0.1:6010 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 50 *:12345 *:* LISTEN 0 128 [::1]:6010 [::]:* LISTEN 0 50 *:10052 *:* [root@ubuntu1804 ~]#ps aux|grep java zabbix 791 1.8 4.4 3131380 89620 ? Sl 18:59 0:03 java -server - Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 - Dcom.sun.management.jmxremote.authenticate=false - Dcom.sun.management.jmxremote.ssl=false - Dcom.sun.management.jmxremote.registry.ssl=false - Dlogback.configurationFile=/etc/zabbix/zabbix_java_gateway_logback.xml - classpath lib:lib/android-json-4.3_r3.1.jar:lib/logback-classic- 1.2.3.jar:lib/logback-core-1.2.3.jar:lib/slf4j-api-1.7.30.jar:bin/zabbix-javagateway-5.0.14.jar -Dzabbix.pidFile=/var/run/zabbix/zabbix_java_gateway.pid - Dsun.rmi.transport.tcp.responseTimeout=3000 com.zabbix.gateway.JavaGateway root 1235 0.0 0.0 14436 1120 pts/0 S+ 19:02 0:00 grep -- color=auto java
范例: CentOS安装
[root@centos8 ~]#rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/8/x86_64/zabbix-release-5.0- 1.el8.noarch.rpm [root@centos8 ~]#rpm -Uvh https://repo.zabbix.com/zabbix/4.0/rhel/8/x86_64/zabbix-release-4.0- 2.el8.noarch.rpm #修改为阿里云源 [root@centos8 ~]#vim /etc/yum.repos.d/zabbix.repo [zabbix] name=Zabbix Official Repository - $basearch baseurl=https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/8/x86_64/ enabled=1 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ZABBIX-A14FE591 #或者sed修改 [root@centos8 ~]#sed -i.bak 's/repo.zabbix.com/mirrors.aliyun.com\/zabbix/' /etc/yum.repos.d/zabbix.repo #安装 [root@centos8 ~]#yum -y install zabbix-java-gateway #查看包文件列表 [root@centos8 ~]#rpm -ql zabbix-java-gateway /etc/zabbix/zabbix_java_gateway.conf /etc/zabbix/zabbix_java_gateway_logback.xml /usr/lib/systemd/system/zabbix-java-gateway.service /usr/lib/tmpfiles.d/zabbix-java-gateway.conf /usr/sbin/zabbix_java_gateway /usr/share/doc/zabbix-java-gateway /usr/share/doc/zabbix-java-gateway/AUTHORS /usr/share/doc/zabbix-java-gateway/COPYING /usr/share/doc/zabbix-java-gateway/ChangeLog /usr/share/doc/zabbix-java-gateway/NEWS /usr/share/doc/zabbix-java-gateway/README /usr/share/zabbix-java-gateway /usr/share/zabbix-java-gateway/bin /usr/share/zabbix-java-gateway/bin/zabbix-java-gateway-4.0.24.jar #默认的配置文件可不做修改 [root@centos8 ~]#grep '^[^#]' /etc/zabbix/zabbix_java_gateway.conf PID_FILE="/var/run/zabbix/zabbix_java.pid" [root@centos8 ~]#cat /etc/zabbix/zabbix_java_gateway.conf # This is a configuration file for Zabbix Java Gateway. # It is sourced by startup.sh and shutdown.sh scripts ... #启动 [root@centos8 ~]#systemctl enable --now zabbix-java-gateway.service [root@centos8 ~]#ps -ef|grep java zabbix 25041 1 0 10:27 ? 00:00:00 java -server - Dlogback.configurationFile=/etc/zabbix/zabbix_java_gateway_logback.xml - classpath lib:lib/android-json-4.3_r3.1.jar:lib/logback-classic- 0.9.27.jar:lib/logback-core-0.9.27.jar:lib/slf4j-api-1.6.1.jar:bin/zabbix-javagateway-4.0.24.jar -Dzabbix.pidFile=/var/run/zabbix/zabbix_java.pid - Dzabbix.startPollers=20 -Dsun.rmi.transport.tcp.responseTimeout=3000 com.zabbix.gateway.JavaGateway root 25061 1593 0 10:29 pts/1 00:00:00 grep --color=auto java #查看是否打开端口10052/tcp [root@centos8 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 100 127.0.0.1:25 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 50 *:10052 *:*
编译安装使用的是zabbix agent,zabbix server 是同一个源码包,只需指定相关的编译选项即可
范例: 编译安装 zabbix java gateway 5.0
[root@centos8 ~]#tar xf zabbix-5.0.13.tar.gz [root@centos8 ~]#wget https://cdn.zabbix.com/zabbix/sources/stable/5.0/zabbix- 5.0.13.tar.gz [root@centos8 ~]#cd zabbix-5.0.13/ [root@centos8 zabbix-5.0.13]#./configure --prefix=/apps/zabbix_java_gateway -- enable-java --with-net-snmp --with-mysql -with-ssh2 [root@centos8 zabbix-5.0.13]#make && make install [root@centos8 zabbix- 5.0.13]#/apps/zabbix_java_gateway/sbin/zabbix_java/startup.sh [root@centos8 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 100 127.0.0.1:25 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 50 *:10052 *:* LISTEN 0 128 [::]:22 [::]:* [root@centos8 ~]#ps aux|grep java
范例: 编译安装 zabbix java gateway 4.0
[root@centos8 ~]#yum -y install gcc java-1.8.0-openjdk-devel [root@centos8 ~]#wget https://cdn.zabbix.com/zabbix/sources/stable/4.0/zabbix- 4.0.24.tar.gz cd /usr/local/src [root@centos8 ~]#tar xf zabbix-4.0.24.tar.gz [root@centos8 ~]#cd zabbix-4.0.24/ [root@centos8 zabbix-4.0.24]# ./configure --prefix=/usr/local/zabbix --enablejava --with-net-snmp --with-mysql -with-ssh2 [root@centos8 zabbix-4.0.24]#make && make install [root@centos8 ~]#tree /usr/local/zabbix/ /usr/local/zabbix/ └── sbin └── zabbix_java ├── bin │ └── zabbix-java-gateway-4.0.24.jar ├── lib │ ├── android-json-4.3_r3.1.jar │ ├── logback-classic-0.9.27.jar │ ├── logback-console.xml │ ├── logback-core-0.9.27.jar │ ├── logback.xml │ └── slf4j-api-1.6.1.jar ├── settings.sh ├── shutdown.sh └── startup.sh 4 directories, 10 files [root@centos8 ~]#/usr/local/zabbix/sbin/zabbix_java/startup.sh
默认有关java的监控项是不支持的,如下图
配置下面后,上面相关监控项会支持
#包安装zabbix server [root@zabbix-server ~]#vim /etc/zabbix/zabbix_server.conf #编译安装zabbix server [root@zabbix-server ~]#vim /apps/zabbix_server/etc/zabbix_server.conf JavaGateway=10.0.0.105 #指向JAVA gateway主机 StartJavaPollers=10 #指定开启的进程数,默认为0,即不开启,所以必须修改此行 JavaGatewayPort=10052 #指定端口,此为默认值,可不修改 [root@zabbix-server ~]#systemctl restart zabbix-server.service #查看进程 [root@zabbix-server ~]#ps -ef|grep java zabbix 2529 2518 0 12:21 ? 00:00:00 /apps/zabbix_server/sbin/zabbix_server: java poller #1 [got 0 values in 0.000011 sec, idle 5 sec] zabbix 2530 2518 0 12:21 ? 00:00:00 /apps/zabbix_server/sbin/zabbix_server: java poller #2 [got 0 values in 0.000011 sec, idle 5 sec] zabbix 2531 2518 0 12:21 ? 00:00:00 /apps/zabbix_server/sbin/zabbix_server: java poller #3 [got 0 values in 0.000025 sec, idle 5 sec] zabbix 2532 2518 0 12:21 ? 00:00:00 /apps/zabbix_server/sbin/zabbix_server: java poller #4 [got 0 values in 0.000026 sec, idle 5 sec]
如果 Java gateway 开启JMX功能,也可以直接监控 java gateway 自身
添加需要监控的java服务器,指定通过JMX接口实现
选中系统内置的模板:Template App Generic Java JMX
注意: Template App Apache Tomcat 只支持老版本的tomcat,所以此处不选择它
查看到 JMX 数据
通过自定义的 JMX 模板,可以定制生产所需的监控项和阈值
取消之前关联的模板
注意: 主机的 JMX 标识正常情况下会变绿
ch[root@centos8 ~]#key1="used_memory";redis-cli info |awk -F: -v key2=$key '$1==key2{print $2}' [root@centos8 ~]#key1="total_system_memory";redis-cli info |awk -F: -v key2=$key '$1==key2{print $2}' [root@centos8 ~]#key1="connected_clients";redis-cli info |awk -F: -v key2=$key '$1==key2{print $2}' [root@centos8 ~]#cat /etc/zabbix/zabbix_agent2.d/redis.conf UserParameter=redis.status[*],/etc/zabbix/zabbix_agent2.d/redis_status.sh "$1" UserParameter=redis.config.maxclients,redis-cli -p 6379 config get maxclients | awk "NR==2" [root@centos8 ~]#cat /etc/zabbix/zabbix_agent2.d/redis_status.sh #!/bin/bash KEY=$1 redis-cli -p 6379 info | grep "\<${KEY}\>" | awk -F ':' '{print $NF}' [root@centos8 ~]#systemctl restart zabbix-agent2 #服务器测试 [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -k redis.status[used_memory] [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -k redis.status[total_system_memory] [root@zabbix-server ~]##zabbix_get -s 10.0.0.8 -k redis.status[connected_clients]
#当Redis连接数达到最大连接数的70%: 活跃连接数/最大连接数*100 >70 #宏定义: {$REDIS.CLIENTS.MAX}=70 #名称:Redis活跃连接数达到{$REDIS.CLIENTS.MAX} #问题形式: { Template Redis status :redis.status[connected_clients].avg(1m)}/{Template Redis status:redis.config.maxclients.last()}*100 >={$REDIS.CLIENTS.MAX} #当Redis内存使用率达到50%:(used_memory/total_system_memory*100> 50 ) #宏定义: {$REDIS.MEM.MAX}=50 #名称:Redis 已用内存达到{$REDIS.MEM.MAX} #问题形式: { Template Redis status:redis.status[used_memory].last()}/{Template Redis status:redis.status[total_system _memory].last()}*100>={$REDIS.MEM.MAX} #测试 [root@rocky8 ~]#redis-cli 127.0.0.1:6379> debug populate 5000000
[root@rocky8 ~]#vim /etc/nginx/conf.d/default.conf
# 加入
location /nginx_status {
stub_status;
access_log off;
allow 127.0.0.1;
deny all;
}
# 重启服务
[root@rocky8 ~]#systemctl restart nginx
[root@rocky8 ~]#vim /etc/zabbix/zabbix_agentd.d/nginx_status.sh #!/bin/bash # Description:zabbix监控nginx性能以及进程状态 HOST="127.0.0.1" PORT="80" URL=nginx_status # 检测nginx进程是否存在 case $1 in ping) pidof nginx | wc -l ;; # 检测nginx性能 active) curl -s "http://$HOST:$PORT/$URL/" | awk 'NR==1{print $NF}' ;; reading) curl -s "http://$HOST:$PORT/$URL/" | awk 'NR==4{print $2}' ;; writing) curl -s "http://$HOST:$PORT/$URL/" | awk 'NR==4{print $4}' ;; waiting) curl -s "http://$HOST:$PORT/$URL/" | awk 'NR==4{print $6}' ;; accepts) curl -s "http://$HOST:$PORT/$URL/" |awk 'NR==3{print $1}' ;; handled) curl -s "http://$HOST:$PORT/$URL/" | awk 'NR==3{print $2}' ;; requests) curl -s "http://$HOST:$PORT/nginx_status/" | awk 'NR==3{print $3}' ;; *) echo "Usage `basename $0` {ping | active | reading | writing | waiting | accepts | handled | requests }" esac [root@rocky8 ~]#chmod +x /etc/zabbix/zabbix_agent2.d/nginx_status.sh [root@rocky8 ~]#/etc/zabbix/zabbix_agent2.d/nginx_status.sh active # 成功 1 #添加监控配置 [root@rocky8 ~]#vim /etc/zabbix/zabbix_agent2.d/nginx.conf UserParameter=nginx.status[*],/etc/zabbix/zabbix_agent2.d/nginx_status.sh $1 #agent测试 [root@rocky8 ~]#zabbix_agent2 -t nginx.status[ping] nginx.status[ping] [s|1] [root@rocky8 ~]#zabbix_agent2 -t nginx.status[active] nginx.status[active] [s|1] [root@rocky8 ~]#systemctl restart zabbix-agent2.service #服务器测试 [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -k nginx.status[ping] 1 [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -k nginx.status[active] 1
在前面的部署架构中,Zabbix Server 和MySQL都有只有一台主机,存在单点问题
可以使用Keepalived 实现 Zabbix Server的高可用
基础架构为LAMP或LNMP环境,采用keepalived实现zabbix服务器高可用,保证主服务器或者Httpd宕掉后能切换到从服务器
MySQL数据库做主主同步,保证两边服务器数据的一致性,实现数据库的高可用。
注意: 从 Zabbix 6.0 官方提供了高可用解决方案
官方链接
https://www.zabbix.com/documentation/6.0/zh/manual/concepts/server/ha#implementation-details
#在两个Zabbix Server 使用下面相同的配置 [root@ka1 ~]#grep -i SourceIP= /etc/zabbix/zabbix_server.conf SourceIP=10.0.0.10 [root@ka1 ~]#grep -i '^server=' /etc/zabbix/zabbix_agentd.conf Server=127.0.0.1,10.0.0.10 [root@ka1 ~]#systemctl enable zabbix-server.service [root@ka2 ~]#systemctl disable zabbix-server.service #keepalived相关配置 #ka1节点配置 [root@ka1 ~]#cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { root@wangxiaochun.com } notification_email_from 29308620@qq.com smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id ka1.magedu.org vrrp_skip_check_adv_addr #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 vrrp_mcast_group4 230.6.6.6 } #指定检测脚本 vrrp_script check_zabbix_server{ script "/usr/bin/killall -0 zabbix_server" interval 1 weight -30 fall 2 rise 2 timeout 2 } include /etc/keepalived/conf.d/*.conf [root@ka1 ~]#cat /etc/keepalived/conf.d/vip_zabbix.conf vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 66 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 10.0.0.10/24 dev eth0 label eth0:1 } #notify_master "systemctl start zabbix-server" #notify_backup "systemctl stop zabbix-server" track_script { check_zabbix_server } } #ka2节点框配置 [root@ka2 ~]#cat /etc/keepalived/conf.d/vip_zabbix.conf vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 66 priority 80 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 10.0.0.10/24 dev eth0 label eth0:1 } notify_master "systemctl start zabbix-server" notify_backup "systemctl stop zabbix-server" track_script { # check_zabbix_server #在ka2节点不能启用脚本,否则会导致ka2节点也降低优先级,从而 切换失败 } }
本质上就是添加自动添加port监控的模板动作
之前都是手动一台一台主机的添加到 Zabbix 中进行监控,很是繁琐,可以利用自动发现功能,自动添加被监控的主机
当众多的服务器都已经安装了agent或者snmp后,利用自动发现功能,Zabbix server 可以自动扫描预先配置好的ip段,自动添加主机,自动关联模板,自动加到主机组里等等。
网络发现功能更快速的部署zabbix、简化zabbix管理、并且在经常变动的环境里面也不需要花太多的精力,毕竟网络发现也能随时发现变化。
当然网络发现也不是万能的,虽然网络发现能干很多事情,但是它无法发现网络拓扑的变化。
由于自动发现效率比较低,严重消耗Zabbix Server资源和网络带宽,大规模环境中较少使用
自动发现虽然能自动完成发现并添加主机,但仍然存在一些问题
自动发现由两个步骤组成:
发现有Zabbix agent运行的主机
每10分钟执行一次
如果主机正常运行时间超过2分钟,添加主机
将Linux主机添加到“Linux servers”组
链接模板Template OS Linux 到Linux主机
如果主机停机时间超过24小时,删除主机
配置-- 自动发现-- 创建发现规则
指定名称,IP范围和逢动发现检查等信息
可见名称为IP地址
创建新的动作
系统默认内置动作,也可以修改已有的被禁用自动发现动作
启用此动作
操作增加三个操作: 添加主机,添加群组,添加模板
也可以添加发送消息给Admin等操作
一段时间后,可以观察到下面结果,自动添加两台主机并关联相应的模板
将客户端关机后,过一天后,再观察是否自动删除此主机
监测 – 自动发现, 可以看到下面的删除的主机
当客户端众多时,将每台主机手动添加到Zabbix,还手动添加关联模板,无疑是低效的.
但是利用网络发现实现,Zabbix Server 资源消耗又比较严重
利用Zabbix的自动注册功能,实现添加主机的自动化,可以大幅减少运维的工作量,减少Zabbix Server 的资源消耗
此方式和自动发现不同,是由Active agent主动发起请求zabbix server将这些agent加到主机里。
注意: Agent 必须使用主动模式才支持自动注册
自动注册由于比自动发现效率更好,Zabbix Server资源消耗更少,更适合大规模及云环境IP地址不固定的场景使用
官方帮助
https://www.zabbix.com/documentation/5.0/zh/manual/discovery/auto_registration
在Zabbix agent 端的配置文件修改以下项目
Server=<Zabbix Server IP>
ServerActive=<Zabbix Server IP> #客户端主动模式是实现自动注册的前提条件
Hostname=<agent IP>
#HostnameItem=system.hostname
HostMetadata==<key> #非必须项,可以做为添加主机的验证标识和分类,或者实现加入主机
的验证功能
HostMetadataItem=<监控项Item> #非必须项,监控项的值可以做为添加主机的验证标识和分类
在邮箱上开启SMTP功能,利用此邮箱实现发送报警邮件
QQ邮箱开启邮件通知功能
获取授权码
报警媒介类型是一种给运维工程师发送消息通知的渠道,即当zabbix的触发器触发一个事件后,怎么才能把这个事件通过某些方式通知给运维工程师呢? 媒介类型就起到此作用,如果想要实现邮件告警功能,那么对应的媒介类型就是配置用来发送告警邮件的发件人邮箱。
管理–>报警媒介类型–>创建报警媒介类型
结合上一小节邮箱的配置输入以下内容
QQ 邮箱配置
添加消息模板用于发送信息
#可以修改两个消息模板
# 问题
主题: 告警: {EVENT.NAME}
告警主机:{HOST.NAME1}
告警服务: {ITEM.NAME1}
告警Key1: {ITEM.KEY1}:{ITEM.VALUE1}
告警Key2: {ITEM.KEY2}:{ITEM.VALUE2}
严重级别: {TRIGGER.SEVERITY}
# 恢复 Problem Recovery
主题: 恢复: {EVENT.DURATION}: {EVENT.NAME}
恢复主机:{HOST.NAME1}
恢复服务: {ITEM.NAME1}
恢复Key1:{ITEM.KEY1}:{ITEM.VALUE1}
恢复Key2: {ITEM.KEY2}:{ITEM.VALUE2}
创建完成,可以看到下面信息
测试是否邮件正常,有时QQ邮箱不成功,可以尝试其它邮箱,如163邮箱
成功可以收下邮件和提示
媒介类型创建好之后,还需要在每个zabbix账户里面添加相应的收件配置,比如邮件类型的媒介类型要给zabbix账户添加邮箱,如果是微信类型的媒介类型那么就要在zabbix账户设置微信号,短信类型的媒介类型那就得给zabbix账户设置手机号用于接收报警消息内容。
在zabbix用户中添加报警媒介时,需要指定告警信息的收件人的邮件地址
动作可以实现当触发器被触发后可以执行哪些操作,一般可以是发送告警或执行命令关于宏,即一些在Zabbix 中可以调用的变量
宏分为三种
指定动作即条件为事件的严重度为信息时就触发动作
官方宏参考:
https://www.zabbix.com/documentation/5.0/zh/manual/appendix/macros/supported_by_location
https://www.zabbix.com/documentation/4.0/zh/manual/appendix/macros/supported_by_location
范例: 操作和恢复操作的定制消息主题和和内容
#操作主题 故障:{TRIGGER.STATUS} 服务器:{HOSTNAME1} 事件:{TRIGGER.NAME}故障! #消息内容 告警主机:{HOSTNAME1} 告警时间:{EVENT.DATE} {EVENT.TIME} 告警等级:{TRIGGER.SEVERITY} 告警信息:{TRIGGER.NAME} 告警项目:{TRIGGER.KEY1} 问题详情:{ITEM.NAME}:{ITEM.VALUE} 当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1} 事件ID:{EVENT.ID} #恢复操作主题 恢复:{TRIGGER.STATUS} 服务器:{HOSTNAME1} 事件:{TRIGGER.NAME}已恢复! #恢复消息内容 告警主机:{HOSTNAME1} 告警时间:{EVENT.DATE} {EVENT.TIME} 故障持续时间:{EVENT.AGE} 恢复时间:{EVENT.RECOVERY.TIME} 告警等级:{TRIGGER.SEVERITY} 告警信息:{TRIGGER.NAME} 告警项目:{TRIGGER.KEY1} 问题详情:{ITEM.NAME}:{ITEM.VALUE} 当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1} 事件ID:{EVENT.ID}
范例: 配置操作
操作内容
默认标题:业务报警 {EVENT.NAME}
消息内容:业务报警服务器:{HOST.NAME},IP:{HOST.IP},详情:{ITEM.NAME}:{ITEM.VALUE}
步骤设为0时,表示会不停的持续发送警报,一般建议1到3表示执行三次。
步骤持续时间表示如果有后续步骤执行时的间隔时长,默认为0表示使用默认时间1h后才会执行后续步骤,此值最低不能低于60s,最大不能超过604800s,可以设为1到5m(分钟)比较合适
配置故障恢复信息
恢复操作内容
默认标题:业务恢复
信息内容:业务恢复服务器:{HOST.NAME},IP:{HOSTNAME1},详情:{ITEM.NAME}:{ITEM.VALUE}
利用之前创建的触发器实现邮件通知
停止nginx服务,触发邮件报警
[root@centos8 ~]#systemctl stop nginx
分级告警
当出现报警后,一般会根据组织的重要级别,按时间逐级分层向上报警,如下面常见分层报警
初级运维/指定运维组--高级运维工程师/业务运维-—->架构师--->总监/CTO
使用mysql自定义模板,监控mysql性能,可以监控如下内容:OPS(增删改查)、mysql请求流量带宽,mysql响应流量带宽
[root@centos8 ~]#yum -y install mysql-server [root@centos8 ~]#systemctl enable --now mysqld [root@centos8 ~]#mysql -e 'create user zabbix@"localhost" identified by "123456"' [root@centos8 ~]#grep "^Include" /etc/zabbix/zabbix_agentd.conf Include=/etc/zabbix/zabbix_agentd.d/*.conf [root@centos8 ~]#cat /etc/zabbix/zabbix_agentd.d/mysql.conf UserParameter=mysql.version,mysql -V UserParameter=mysql.status[*],/etc/zabbix/zabbix_agentd.d/check_mysql.sh $1 2> /dev/null UserParameter=mysql.ping,mysqladmin -uzabbix -p123456 -P3306 -h127.0.0.1 ping 2>/dev/null | grep -c alive [root@centos8 ~]#cat /etc/zabbix/zabbix_agentd.d/check_mysql.sh #!/bin/bash # MYSQL_USER='zabbix' MYSQL_PWD='123456' MYSQL_HOST='127.0.0.1' MYSQL_PORT='3306' MYSQL_CONN="/usr/bin/mysqladmin -u${MYSQL_USER} -p${MYSQL_PWD} -h${MYSQL_HOST} - P${MYSQL_PORT}" #MYSQL_CONN=mysql -e "show global status" | awk -v s=$1 '$1 ~ "^"s"$"{print $2}' if [ $# -ne "1" ];then echo "arg error!" fi case $1 in Threads) result=`${MYSQL_CONN} status |awk '{print $4}'` ;; Uptime) result=`${MYSQL_CONN} status|cut -f2 -d":"|cut -f1 -d"T"` ;; Com_update) result=`${MYSQL_CONN} extended-status |grep -w "Com_update"|cut -d"|" - f3` ;; Slow_queries) result=`${MYSQL_CONN} status |cut -f5 -d":"|cut -f1 -d"O"` ;; Com_select) result=`${MYSQL_CONN} extended-status |grep -w "Com_select"|cut -d"|" - f3` ;; Com_rollback) result=`${MYSQL_CONN} extended-status |grep -w "Com_rollback"|cut -d"|" -f3` ;; Questions) result=`${MYSQL_CONN} status|cut -f4 -d":"|cut -f1 -d"S"` ;; Com_insert) result=`${MYSQL_CONN} extended-status |grep -w "Com_insert"|cut -d"|" - f3` ;; Com_delete) result=`${MYSQL_CONN} extended-status |grep -w "Com_delete"|cut -d"|" - f3` ;; Com_commit) result=`${MYSQL_CONN} extended-status |grep -w "Com_commit"|cut -d"|" - f3` ;; Bytes_sent) result=`${MYSQL_CONN} extended-status |grep -w "Bytes_sent" |cut -d"|" - f3` ;; Bytes_received) result=`${MYSQL_CONN} extended-status |grep -w "Bytes_received" |cut - d"|" -f3` ;; Com_begin) result=`${MYSQL_CONN} extended-status |grep -w "Com_begin"|cut -d"|" - f3` ;; *) echo "Usage:$0(Threads|Uptime|Com_update|Slow_queries|Com_select|Com_rollback|Questio ns|Com_insert|Com_delete|Com_commit|Bytes_sent|Bytes_received|Com_begin)" ;; esac echo $result [root@centos8 ~]#chmod +x /etc/zabbix/zabbix_agentd.d/check_mysql.sh [root@centos8 ~]#systemctl restart zabbix-agent.service [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -p 10050 -k 'mysql.version' mysql Ver 8.0.21 for Linux on x86_64 (Source distribution) [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -p 10050 -k 'mysql.status[Uptime]' 1141 [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -p 10050 -k 'mysql.status[Slow_queries]' 0 [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -p 10050 -k 'mysql.ping' 1 #停止MySQL服务后再测试看到下面结果 [root@zabbix-server ~]#zabbix_get -s 10.0.0.8 -p 10050 -k 'mysql.ping' 0
按下面操作导入自定义模板
[root@centos8 ~]#cat/etc/zabbix/zabbix_agent2.d/mysql_repl_status.sh
#!/bin/bash
KEY=$1
PASS='123456'
mysql -uroot -p$PASS -e "show slave status\G"|grep "${KEY}"|awk '{print $NF}'
[root@centos8 ~]#cat /etc/zabbix/zabbix_agentd.d/mysql.conf
UserParameter=mysql.repl.status[*],
/etc/zabbix/zabbix_agent2.d/mysql_repl_status.sh "$1"
#服务器取值测试
[root@zabbix ~]#zabbix_get -s 10.0.0.8 -k mysql.repl.status[Slave_SQL_Running]
[root@zabbix ~]#zabbix_get -s 10.0.0.8 -k mysql.repl.status[Slave_IO_Running]
[root@zabbix ~]#zabbix_get -s 10.0.0.8 -k
mysql.repl.status[Second_Behind_Master]
#触发器1:名称:复制线程异常, 两个复制线程状态都要为 Yes
{Template MysQL slave {Temp1ate MySQL repl
status:mysql.repl.status[Slave_IO_Running].str(Yes)}=0 or {Template MySQL repli
status :mysql.repl.status[Slave_SQL_Running].str(Yes)}=0
#触发器2: 名称:复制延时不超过100s
{Template MysQL repl
status:mysql.repl.status[Second_Behind_Master].last()]}>=100
脚本思路:变量定义网段,for遍历ping通的ip传到字符串变量里,然后再遍历字符串,调接口post传入json格式模板信息
获取token
在访问Zabbix内部的任何数据之前,需要登录并获得身份验证令牌。这可以使用user.login方法来完成。
假设以Zabbix的Admin用户登录。那么JSON请求将是这样的:
[root@zabbix-server ~]#yum -y install python3 [root@zabbix-server ~]#cat zabbix-api-token.sh #!/bin/bash # #******************************************************************** #Author: wangxiaochun #QQ: 29308620 #Date: 2020-09-08 #FileName: zabbix-api-token.sh #URL: http://www.wangxiaochun.com #Description: The test script #Copyright (C): 2020 All rights reserved #******************************************************************** ZABBIX_SERVER=zabbix.wang.org curl -s -XPOST -H "Content-Type: application/json-rpc" -d ' { "jsonrpc": "2.0", "method": "user.login", "params": { "user": "Admin", "password": "zabbix" }, "id": 1, "auth": null }' http://${ZABBIX_SERVER}/zabbix/api_jsonrpc.php [root@zabbix-server ~]#./zabbix-api-token.sh | python3 -m json.tool { "jsonrpc": "2.0", "result": "6e936114704269310d372a19c409e93d", #此为获取的Token "id": 1 }
#!/bin/bash # #******************************************************************** #Author: Mr.Song #QQ: 1132197391 #Date: 2022-12-02 #Description: The test script #Copyright (C): 2022 All rights reserved #******************************************************************** ZABBIX_SERVER=10.0.0.100 TOKEN=$(./zabbix-api-token.sh| awk -F'"' '{print $8}') IPLIST=() read -p "请输入IP网络位:" NET for i in {1..254} do ping -c 1 -w 2 ${NET}${i} >/dev/null && { echo "${NET}${i} is up"; IPLIST[${#IPLIST[@]}]=$i; } done #echo "${IPLIST[@]}" for ((i=0; i<${#IPLIST[@]}; i++ ));do curl_content=' { "jsonrpc": "2.0", "method": "host.create", "params": { "host": "'${IPLIST[$i]}'", "name": "'web-${IPLIST[$i]}'", "interfaces": [ { "type": 1, "main": 1, "useip": 1, "ip": "'${IPLIST[$i]}'", "dns": "", "port": "10050" } ], "groups": [ { "groupid": "2" } ], "templates": [ { "templateid": "10001" } ] }, "id": 1, "auth": "'$TOKEN'" }' curl_proxy_content=' { "jsonrpc": "2.0", "method": "host.create", "params": { "host": "'${IPLIST[$i]}'", "name": "'web-proxy-api-${IPLIST[$i]}'", "proxy_hostid": "10276", "interfaces": [ { "type": 1, "main": 1, "useip": 1, "ip": "'${IPLIST[$i]}'", "dns": "", "port": "10050" } ], "groups": [ { "groupid": "2" } ], "templates": [ { "templateid": "10001" } ] }, "id": 1, "auth": "'$TOKEN'" }' if [ $i -gt 2 ];then curl -s -XPOST -H \"Content-Type: application/json-rpc\" -d "$curl_proxy_content" http://${ZABBIX_SERVER}/zabbix/api_jsonrpc.php | python3 -m json.tool else curl -s -XPOST -H \"Content-Type: application/json-rpc\" -d "$curl_content" http://${ZABBIX_SERVER}/zabbix/api_jsonrpc.php | python3 -m json.tool fi done
Zabbix WEB管理页面验证结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。