开发者学堂课程【PostgreSQL快速入门:21 PostgreSQL 监控2 趋势监控数据收集和分析nagios实时监控部署和自定义监控】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/16/detail/80
21 PostgreSQL 监控2 趋势监控数据收集和分析 nagios 实时监控部署和自定义监控
内容介绍:
一、OS 层面的统计信息
二、nagios 服务端安装
三、nagios 客户端安装
四、nagios 服务端配置
五、自定义脚本
六、自写脚本
一、OS 层面的统计信息
本节接着前面的数据库监控继续讲解操作系统层面的监控。
先举一个例子,使用 sar 命令来获取数据,操作系统定时任务中抓取到的操作系统运行的一些状态。
例如看这样一台服务器,输入
which sar
先查看 sar 来自哪个包,输入
rpm -qf /usr/bin/sar
结果显示来自sysstat的一个包,所以如果系统中没有sar命令可以安装该包。
输入sar -q
就会显示出sar负载的情况。输入sar -b
就会显示出数据块的一些信息,例如bread/s每秒的读,bwrtn/s 每秒的写的数据块、读的请求、写的请求、总的请求数这类统计信息。
输入 man sar 可以看到统计的信息,一般输入 sar -可以看到结果为十分钟统计一次,如果觉得频率太长需要一分钟统计一次。可以进行修改,输入
man sar
less
该文件中配置了每十分钟统计会执行sar命令/usr/lib64/sa/sa1,可以去掉/10,就会变成一分钟一次。
输入vi /etc/cron.d/sysstat
删除掉/10,就会变成每分钟统计一次。
输入 sar -q,即可显示。
再来查看 sar 中可以统计哪些内容。
输入 man sar
-b 报告 I/O 以及传输速率的统计。例如 tps 是总共的到物理设备的一个请求,rtps 与 wtps 分别表示向物理设备递交的读的请求与写的请求,bread/s 与 bwrtn/s 指每秒写的数据块的请求数(例如每秒有100,就有100×512个字节即50k/s)
-B 指页面的统计信息。pgpgin/s 指每秒从磁盘读取到系统内核的页面数,pgpgout/s 指从内存中写入磁盘的页面数,fault/s 及其它表示系统层面的一些信息例如 fault/s 表示 I/O 产生页错误的统计。
一般比较关注系统读写的请求情况、每秒写的数量。若 bread/s 与 bwrtn/s 大,而 rtps 与 wtps 小代表 I/O 请求大,但是请求数小。若 bread/s 与 bwrtn/s 小,而 rtps 与 wtps 大即请求量很大但是写的数或者读的数很小,有可能为 I/O 每次请求的比较少但是请求次数比较频繁。一般会出现在索引扫描或是对索引、表进行更新。一般索引扫描请求数较多,例如从索引检索到磁盘时因为物理数据可能为随机分布而不是连续分布,但索引扫描时是连续的,从索引的顺序进行扫描,此时就会发现请求数很大但是 bread/s 与 bwrtn/s 并不快。对于机械键盘,rtps比较多但是bread/s 比较少。
-d 指设备的统计,如果要统计-d,必须要开启一样操作,如果没有开启默认-d 不统计。此处 5.0 的系统没有开启。输入 cat/etc/redhat-release,结果显示 CentOS release 5.7。之前演示的版本为6.0,输入 cat/etc/redhat-release,结果显示CentOS release 6.4 。在开启后的版本上输入 sar -d,显示每个设备的请求量,可以看出哪个设备请求比较繁忙。await 代表对于 I/O 请求平均等待时间为多少。%util 指在 I/O 请求过程中有多少时间处于CPU,可以看出物理设备的全部性能是否已经占满,如果为100%代表物理设备的 I/O 能力已经完全体现。
-q 为负载的统计
-r 为内存的统计
-R 也为内存的统计
-u[ALL]代表 CPU 的使用分布情况。%user 代表 CPU 时间有多少%属于 user,%system 代表 CPU 时间有多少%属于system,%iowait 代表 CPU 时间有多少%属于 iowait。
-w 也比较关注,其中 proc/s 代表系统每秒创建任务的速度,每秒创建任务多代表不断有新的进程产生,proc/s 也可以反映出是否使用短连接,长连接再连接后不需要申请新的进程,但短连接在连上后会断掉,断掉时进程也会释放掉,再连接后 proc/s 会再产生一个进程,可以看出是否使用短连接。使用短连接性能开销大,尽量使用长连接。
上述讲解了 sar 的帮助文件以及能够输出的内容。
(一)总结:
1、系统的每秒读写 IO 请求
2、每秒系统写入或从磁盘读出的 page 数
3、系统每秒创建的进程数,如果这个数字很大可能是应用程序连接数据库是短连接,并且请求数据库频繁,而PostgreSQL 采用的是客户端连接过来 fork 新进程然后这个新进程与客户端进行交互的模式,因此这种情况会造成数据库服务器大量的关闭和创建进程(并发连接下降,使用长连接不会出现该问题), sar -c 能反映这种情况.使用短连接还有一个坏处就是当系统中使用到 sequence,并且这个 sequence 被大量的这种短连接进程请求,那么它设置的sequence cache 没有效果并且会造成大量的跳号。(cache 为会话层面,一旦退出就会失效。例如 cache 为100,每次使用连接短连接后,插一条记录就退掉,此时100就会消费掉,下次从101开始,所以会导致大量的序列的跳号。)
4、系统的负载
5、系统的内存和 SWAP 的使用情况
6、每秒被 free 的内存,新增绘 buffer 的内存,新增绘 cache 的内存
7、系统 CPU 在 user, nice, system, iowait,steal,idle 的使用占比
8、inode,file 或其他内核表的报告
9、每秒上下文的切换数量
10、SWAP 每秒被换进或换出的数量
此处例子
http://blog.163.com/digoal@126/blog/static/163877040201211354145701/
为使用 Postgre 将服务器每天产生的sar统计信息录入到数据库,输出各 sar 维度的 TOP10。
输出样本:
例如每天平均的 CPU 负载以及排在前十的服务器。图上 get_ifo 为服务器信息,自主填写,get_ip 录入到,ldavg_15算出平均负载。这样对于大批量管理服务器的管理员可以减轻工作量,因为对于负载高的服务器关注度很高,对于负载低的服务器不需要太高的关注。
当你管理的服务器越来越多的时候.哪个服务器才是你最需要关注的?
通过各个监控维度的排行.可以知道你到底需要关注或者优先关注哪些服务器.这个通过 nagios.cacti 等监控软件当然是可以做到的。
测试环境:OS:RHEL5(如果为6,有些脚本需要修改)
(二)收集信息
我这里举了一个简单的例子.收集前一天 sar 的统计报告.如下:
1.sar -b
反映系统的每秒读写IO请求等
2.sar -B
反映每秒系统写入或从磁盘读出的page数
3.sar -c
反映系统每秒创建的进程数,如果这个数字很大可能是应用程序连接数据库是短连接,并且请求数据库频繁.而PostgreSQL 采用的是客户端连接过来 fork 新进程然后这个新进程与客户端进行交互的模式,.因此这种情况会造成数据库服务器大量的关闭和创建进程, sar -c 能反映这种情况.使用短连接还有一个坏处就是当系统中使用到 sequence,并且这个 sequence 被大量的这种短连接进程请求,那么它设置的 sequence cache 没有效果并且会造成大量的跳号
4.sar -q
反映系统的负载
5.sar -r
反映系统的内存和SWAP的使用情况
6.sar -R
反映每秒被free的内存,新增给buffer的内存,新增给cache的内存
7.sar -u
反映系统 CPU 在 user, nice, system, iowait, steal, idle 的分配比例
8.sar -v
inode, file 或其他内核表的报告
9.sar -w
反映每秒上下文的切换数量
10.sar -w
反映 SWAP 每秒被换进或换出的数量
(三)接下来看看数据库表的设计:
1.这里使用的是 sar 用户和 sar 库以及 tbs_sar 表空间,首先初始化数据库(创建数据库,用于存储 sar 信息,从各个服务器上搜出来的信息)create role sar nosuperuser nocreatedb nocreaterole noinherit login encrypted password ' DIGOAL' ;//创建一个角色
create tablespace tbs_sar owner digoal location ‘/homel sar/tbs_sar’; //创建表空间
create database sar with owner digoal template template0 encoding 'UTF8’ tablespace tbs_sar ;//创建数据库
grant all on database sar to sar ;
grant all on tablespace tbs_sar to sar ; //连接到数据库
\c sar sar
create schema sar authorization sar ;
2.再来创建序列,函数和表:
create sequence seq_ server id start with 1 increment by 1;
//创建序列
//创建表
create table server(
//存放 server 信息
id int primary key,
//默认 id 使用上述序列,id 为主键
ip inet not null unique,
//ip 存储 sar 信息
info text);
//info 更新,例如有100个服务器就会有100条记录 server,上传时会自动生成一个 server,如果 ip已经存在就往 ip 中插记录,info 就去更新,例如ip对应的是哪个业务的数据库或者对应哪个服务器
3.根据 IP 地址获取 ServerlD 的函数,没有则新分配
create or replace function get_server_id (i_ip int) returns int as $BODY$
declare
v_id int;
begin
select id into v_id from server where ip=i_ip;
if not found then
insert into server(id, ip) values (nextval(‘ seq_server_id ’: :regclass), i_ip);
select id into v_id from server where ip=i_ip;
end if;
return v_id;
exception
when others then
return -1 ;
end
$BODY$ language plpgsoql;
4.根据ServerID获取IP的函数
create or replace function get_ip (i_id int) returns inet as $BODY$
declare
v_ip inet ;
begin
select ip into v_ip from server where id=i_id;
return v_ip;
exception
when others then
return '0.0.0.0/0’ : : inet ;
end
$BODY$ language plpgsql ;
5.根据 ServerlD 获取服务器 info 的函数
create or replace function get_info (i_id int) returns text as $BODY$
declare
v_info text ;
begin
select info into v_info from server where id=i_id;
return v_info;
exception
when others then
return 'no info’;
end
$BODY$ language plpgsgl ;
6.统计昨天未收集到 SAR 日志的函数
如果每天都需要收集 sar,昨天有原因未能收集,就可以通过该函数将没有上传的信息找出,得知服务器
截取部分代码:
create or replace function get_server_nodata_yesterday () returns setof text as $BODY$
declare
v_result text ;
begin
perform 1 from (select s1.* from server s1 left outer join
(select * from (select server_id, row_number () over (partition by server_id order by s_date desc) from sar_context where
//对应的为一个表,sar_context 中存储的为上下文切换的一些信息
s_date=current_date-1) t1
where row_number=1) t2 on (s1. id=t2.server_id) where t2.server_id is null) t;
if found then
return next ' sar_context : ’;
//如果没有则返回 sar_context 没有收到信息
return query select s1.ip ||’,’||s1.info from server s1 left outer join
(select * from (select server_id, row_number () over (partition by server_id order by s_date desc) from sar_context where
s_date=current_date-1) t1
where row_number=1) t2 on (s1 . i d=t2.server_id) where t2.server_id is null;
end if;
perform 1 from (select s1.* from server s1 left outer join
(select * from (select server_id ,row_number () over (partition by server_id order by s_date desc) from sar_cpu where //sar_cpu类似
s_date=current_date-1) t1
where row_number=1 ) t2 on (s1.i d=t2.server_id) where t2.server_id is null) t;
if found then
return next ' sar_cpu: '; //没有收到信息
return query select s1.ip ||’,’||s1.info from server s1 left outer join
(select * from (select server_id,row_number () over partition by server_id order by s_date desc) from sar_cpu where
s_date=current_date-1) t1
where row_number=1) t2 on (s1.id=t2.server_id) where t2.server_id is null;
end if;
erform 1 from (select s1.* from server s1 left outer join
(select * from (select server_id,row_number () over (partition by server_id order by s_date desc) from sar _inode where
s_date=current_date-1) t1
where row_rumber=1) t2 on (s1.id=t2,server_id) where t2.server_id is null) t ;
if found then
return next ' sar _inode: ’ ;
return query select s1.ip ||’,’||s1.info from server s1 left outer join
7.sar 信息存放表
截取部分代码:
create table sar_io
//存放 io 信息
(server_id int not null,
//对应报表关联到 server 表
s_date date not null,
//统计信息日期 server 表中显示只有一个时间点,没有日期,日期直接使用 date 获取到然后进行上传
s_time time not null,
//时间
tps numeric, //sar
报告中显示出的一些统计字段
rtps numeric,
wtps numeric,
bread_p_s numeric,
bwrtn_p_s numeric,
unique (server_id s_date, s_time));
//三个组成唯一键值,确保不会有重复数据进行上传
create table sar_page //存放page
(server_id int not null,
s_date date not null,
s_time time not null,
pgpgin p_s numeric,
pgpgout_p_s numeric,
fault_p_s numeric,
majflt_p_s numeric,
unique (server_id, s_date, s_time)) ;
create table sar_proc //存放proc
(server_id int not null,
s _date date not null,
s_time time not null,
proc_p_s num eric,
unique (server _id,s_date, s_time));
create table sar_load //存放load
(server_id int not null,
s_date date not null,
s_time time not null,
runq_sz numeric,
plist_sz numeric,
ldavg_1 numeric,
ldavg_5 numeric,
ldavg_15 numeric,
unique (server_id, s_date, s_time)) ;
create table sar_mem_swap //存放mem_swap
(server_id int not null,
s_date date not null,
s _time time not null,
kbmemfree numeric,
kbmemused numeric,
percnt_memused numeric,
kbbuffers numeric,
kbcached numeric,
kbswpfree numeric,
kbswpused numeric,
percnt_swpused numeric,
kbswpcad numeric,
unique (server_id,s_date, s_time));
create table sar_mem //存放mem
(server_id int not null,
s_date date not null,
s_time time not null,
frmpg_p_s numeric,
bufpg_p_s numeric,
campg_p_s numeric,
unique (server_id, s_date, s_time));
等等,分别使用上述一些表来进行存储
(四)在需要收集 sar 报告的操作系统中配置如下程序用来收集 sar 信息:
收集用到了 PostgreSQL 的 psql 程序,所以需要在系统中安装 PostgreSQL 客户端
假设 PostgreSQL 数据库的连接信息如下.IP 10.10.10.1,Port 1931 , DBNAME sar , USER sar ,PASSWORD DIGOAL
1.配置~/ .pgpass 文件
10.10.10.1:1931:sar : sar:DIGOAL
chmod 400 ~/.pgpass
//将密码文件改为400
2.编写 sar_collect.sh 脚本,用于收集昨天的SAR报告
截取部分代码:
vi /home/post gres/sar_collect. Sh
该脚本通过对sar的输出做一些字符处理后就将它 copy 到对应的表中
截取部分代码:
#!/bin/bash
#环境变量,数据库连接,避免风暴随机等待60秒内
./home/postgres/ . bash_profile
DB_URL="-h 10.10.10.1 -p 1931 -U sar -d sar”
sleep $(($RANDOM%60))
//在数据库中存储前先随机sleep一个事件来减少风暴产生。例如系统中服务器较多有上万台服务器在一个时间点上传数据库压力大。所以此处在60s 中随机 sleep 一个事件来减少风暴的产生
NET_DEV=" ‘/sbin/route -n|grep UG/awk '{print $8}’|head -n 1’ "
//执行该命令获取到端口即物理设备端口IP_ADDR="’/sbin/ip addr show $NET_DEV|grep inet|grep " global $NET_DEV$"|awk ' {print $2}’"' "
//通过该物理设备的端口获取到 ip
SAR_FILE="/var/log/sa/sa date -d -1day +%d"
//文件通过时间来指定
SAR_DATE=" 'date -d -1day +%Y-%m_%d"’"
//通过该命令获取时间
SERVER_ID="psql -A -t $DB_URL -c "select * from get_server_id ($IP_ADDR)""
//通过该命令获取server_id,ip
为前面得到的 ip
# sar -b, sar_io tps rtps wtps bread/s bwrtn/ s
SQL=’sar -b -f $SAR_FILE|grep -E’AM[ ]+([0-9]+|\.+|all|-)|PM[ ]+([0-9]+]\.+[all]-)' |awk ' {print "insert into sar_io(server_id s_date,s_time,tps,rtps,wtps,bread_p_s, bwrtn_p_s) values("$SERVER_ID',
”$SAR_DATE’,","\47"$1$2"\47,",$3",",$4",”$5",",$6",”$7");”}’
//获取到 sql 后通过 awk 转换为一个 insert 语句。-f 指定 sar 文件。过滤掉时间内容,取出字段
psql $DB_URL-c “$SQL"
//插入到数据库
之后都是将每一个 sar 的统计维度转换为 sql 语句插入数据库中。
3.修改权限
chmod 500 sar_collect.sh
新建执行计划.
crontab -e
1 2** * /home/postgres/ sar_collect. sh
//每天两点定时统计搜集信息。相当于所有服务器每天都有 sar的报告
4、看看几条简单的报告 SQL,使用 row_number 窗口函数(根据这些报告可以对所有服务器进行一些排行,例如排在前十的负载最高的服务器)
截取部分代码:
#昨天15分钟最大负载排名前10,后一条为平均值排行
#负载过高需要关注这些服务器上运行的数据库和业务是否健康,例如是否需要建索引,是否需要使用绑定变量等.select get_ip(server_id),* from (select *,row_number () over (partition by server_id order by ldavg_15 desc) from sar_load
//此处使用到一个窗口函数,收集到的数据有很多 server_id,所以需要对单个 server 进行分组,根据 load 做抽取,将 row_number 排在前十的服务器取出
where s_date=current_date-1) t where row_number=1 order by ldavg_15 desc limit 10;
select get._info (server_id), get.ip(server_id) ,round (avg(ldavg.15),2)ldavg_15 from sar_load where s_date=curent_date-1 group
by server_id, s_date order by ldavg_15 desc limit 10;
报告如图:
此处取出十行,15分钟的平均负载排在前十的如图,最高为18.47.需要关注排在前十的服务器,排在18.47比较高即刻查看发生什么事情致使负载变高。
5、最后通过邮件将报告发送给自己(这样减轻了对于服务器比较多的情况下关注的服务器的工作量)
以上都是对于隔天的统计以及对于趋势分析的统计。例如过去一个月需要将全部服务器的负载取出,取出每一个时间点的负载生成一个图表就可以看出负载趋势。会形成一个规律性,例如每晚8点会造成高峰,那么认为业务高峰在夜晚8点。同时也可以看出该服务器在哪段时间内比较空闲,需要在空闲时间做一些操作可以通过分析报告。通过图表也可以做一些预警,例如每晚八点注意会出现的问题。但是对于实时的监控不能使用该方法,因为该方法相当于一天搜集一次。需要用到 nagios 监控套件。Nagios 可以每分钟抓取当前状态。使用 nagios 可以做到实时监控,解放平时工作的人为压力。
二、nagios 服务端安装
首先查看 nagios 是如何架构如何安装。
1、安装 nagios 依赖包
[root@db-172-16-3-33 soft_bak]#yum install -y wget httpd php gcc glibc glibc- common gd gd-devel make net-snmp
2、下载 nagios core 以及 plugins 源码包
http://www.nagios.org/download
下载最新的稳定开源版本.
wget http://prdownloads. sourceforge.net/sourceforge/nagios/nagios-4.0.3.tar . gz
wget http://prdownloads. sourceforge.net/ sourceforge/nagiosplug/nagios-plugins-1.5.tar . gz
到 nagios 官网上查看最新版本,打开 nagios 官网,点击 download,点击 Nagios Core ,下载如图免费版本。
可以看到目前版本已经为4.0.3,下载新版本
第一步下载 core,第二步下载插件 Plugins,可以看到插件最新为1.5版本
3、解压
[root@db-172-16-3-33 soft_bak]# tar-zxvf nagios-4.0.3.t ar . gz
[root@db-172-16-3-33 soft_bak]# tar -zxvf nagios-plugins-1.5.tar .gz
4、新建运行 nagios 的操作系统用户
user add nagios
groupadd nagcmd
uzermod -a -G nagcmd nagios
//若不想用 nagios 运行可以不添加
[root@db-172-16-3-33 soft_bak]# id nagios
uid=513(nagios) gid=513(nagios) groups=513(nagios),514(nagcmd)
5、安装 nagios
[root@db-172-16-3-33 soft_bak]# cd nagios
[root@db-172-16-3-33 nagios]# ./configure--prefix=/opt/nagios-4.0.3--with nagios-user=nagios --with-nagios-group=nagios --
with-command-group=nagcmd
[root@db-172-16-3-33 nagios]# make all
[root@db-172-16-3-33 nagios]# make install
[root@db-172-16-3-33 nagios]# make install-init
[root@db-172-16-3-33 nagios]# make install-config
[root@db-172-16-3-33 nagios]# make install-commandmode
[root@db-172-16-3-33 nagios]# make install-webconf
过程显示如图配置完成:显示 nagios 的主是什么、用户是什么、安装在哪个地方等。
解释:
make install-init
- This installs the init script in /etc/rc.d/init.d
//初始化到 init 脚本,服务器在启动时会启动该服务
make install-commandmode
- This installs and configures permissions on the directory for holding the external command file
//安装命令模式
make install-config
- This installs sample config files in /opt/nagios-4.0.3/etc
//安装配置文件
6、拷贝用于被动监控的时间处理程序到程序目录:
[root@db-172-16-3-33 nagios]# cp -R contrib/ eventhandlers/ /opt/nagios-4.0.3/libexec/
[root@db-172-16-3-33 nagios]# chown -k nagios:nagios /opt/nagios-4.0.3/libexec/ eventhandlers
检查 nagios 配置文件是否正确:
[root@db-172-16-3-33 nagios]# /opt/nagios-4.0.3/bin/nagios -v /opt/nagios-4.0.3/ etc/nagios.cfg
过程显示如图:显示配置8个服务、1台主机等。
启动 nagios
[root@db-172-16-3-33 nagios]# /etc/init. d/ nagios start
Starting nagios: done.
启动 httpd 服务
[root@db-172-16-3-33 nagios]# /etc/init.d/httpd start
Starting httpd: [ 0K ]
创建 WEB 接口访问用户:
[root@db-172-16-3-33 nagios]# httpasswd -c / opt/nagios-4.0.3/etc/htpasswd. users nagiosadmin
New password:
Re-type new password:
Adding password for user nagiosadmin
7、安装 nagios plugins.
[root@db-172-16-3-33 nagios]# cd ../ nagios-plugins-1.5
[root@db-172-16-3-33 nagios-plugins-1.4.16]# ./configure --with-nagios-user=nagios --with-nagios- group=nagios --
prefix=/opt/nagios-4.0.3 --with-pgsql=/opt/pgsql9.2.4
[root@db-172-16-3-33 nagios-plugins-1.5]# make
[root@db-172-16-3-33 nagios-plugins-1.5]# make install
8、将 apache 用户添加到 nagcmd 组.
[root@db-172-16-3-33 rw]# id apache
uid=48(apache) gid=48(apache) groups=48 (apache)
[root@db-172-16-3-33 rw]# usermod -a -G nagcmd apache
//首先查看是否有 apache 用户
[root@db-172-16-3-33 rw]# id apache
uid=48(apache) gid=48(apache) groups=48 (apache) , 514 (nagcmd)
//apache 已经添加到 nagcmd组
[root@db-172-16-3-33 rw]# service http restart
//此时将 http 提拔起来
Stopping httpd: [ OK]
Starting httpd: [ OK ]
因为在web页面需要调用 nagios cmd 时,需要对以下文件有写的权限.
[root@db-172-16-3-33 rw]# pwd
/opt./nagios-4.0.3/var/rw
[root@db-172-16-3-33 rw]# ll
total 0
prw rw--- 1 nagios nagcmd 0 Jun 3 14:18 nagios.cmd
//可以看到主用户有写的权限,apache 也有写的权限
9、将 nagios 和 httpd 加入自启动
[root@db-172-16-3-33 rw]# chkconfig --add nagios
[root@db-172-16-3-33 rw]#chkconfig --level 35 nagios on
//打开3和5服务
[root@db-172-16-3-33 rw]# chkconfig --add httpd
[root@db-172-16-3-33 rw]# chkconfig --level 35 httpd on
//3和5服务都已经打开
10、连接 WEB
网址上输入172.16.3.150可以看到 apache 正常,输入172.16.3.150/nagios 进行身份验证。验证时使用第5步创建的, nagiosadmin 用户密码。验证后现在使用的为最新版本,点击左侧 HOST Groups,HOST Groups 指本机,右侧可以看到有 warning
点击后可以看到是一个 http 存在错误。先不考虑
接着讲解,根据下面内容配置将其它的配置添加到 nagios 平台中。