摘要:服务监控实践 服务监控实际上就是监控我们生产服务器中的所跑的各种服务,例如:mysql、nginx、redis、rabbitMQ、lvs、tomcat等等 这些服务都有它的一些监控指标,这些需要根据实际的服务器性能、业务指标去制定,…
服务监控实践
服务监控实际上就是监控我们
生产服务器中的所跑的各种服务,例如:mysql、nginx、redis、rabbitMQ、
lvs
、tomcat等等
这些服务都有它的一些监控指标,这些需要根据实际的服务器性能、业务指标去制定,你可以叫监控指标标准化吧
这些指标需要不断进行调整,最终形成适应公司架构、业务、产品的,不是一蹴而就的
自定义数据push
将其他服务监控之前先说下自定义的push数据。
原理图
就是通过Python、GO、shell常用的开发语言,把我们监控项的数据指标,所需要的数据抓取出来,然后发送到 Falcon的Agent端
举例子
所有运行的脚本都和agent在同一台服务器,当然也可以不在同一台服务器看你自己需求。你会那个语言用哪个就行。
Shell Push 数据
# 注意,http request body是个json,这个json是个列表
ts=`date +%s`;
curl -X POST -d "[{"metric": "test-metric", "endpoint": "test-endpoint", "timestamp": $ts,"step": 60,"value": 1,"counterType": "GAUGE","tags": "idc=lg,project=xx"}]" http://127.0.0.1:1988/v1/push
Python Push 数据
#!-*- coding:utf8 -*-
import requests
import time
import json
ts = int(time.time())
payload = [
{
"endpoint": "test-endpoint",
"metric": "test-metric",
"timestamp": ts,
"step": 60,
"value": 1,
"counterType": "GAUGE",
"tags": "idc=lg,loc=beijing",
},
{
"endpoint": "test-endpoint",
"metric": "test-metric2",
"timestamp": ts,
"step": 60,
"value": 2,
"counterType": "GAUGE",
"tags": "idc=lg,loc=beijing",
},
]
r = requests.post("http://127.0.0.1:1988/v1/push", data=json.dumps(payload))
print r.text
Go Push 数据
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
apiurl := "http://127.0.0.1:1988/v1/push"
type item struct {
Endpoint string `json:"endpoint"`
Metric string `json:"metric"`
Timestamp int64 `json:"timestamp"`
Step int `json:"step"`
Value int64 `json:"value"`
CounterType string `json:"counterType"`
Tags string `json:"tags"`
}
type message struct {
Item []item `json:"item"`
}
//json序列化
var post message
post.Item = append(post.Item, item{Endpoint: "test-endpoint", Metric: "test-metric", Timestamp: 1500804940,
Step: 60, Value: 10, CounterType: "GAUGE", Tags: "idc=xixian"})
jsonStr, _ := json.Marshal(post.Item)
req, err := http.NewRequest("POST", apiurl, bytes.NewBuffer([]byte(jsonStr)))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
Agent HTTP APi接口详解
metric: 最核心的字段,代表这个采集项具体度量的是什么, 比如是cpu_idle呢,还是memory_free, 还是qpsendpoint: 标明Metric的主体(属主),比如metric是cpu_idle,那么Endpoint就表示这是哪台机器的cpu_idletimestamp: 表示汇报该数据时的
unix时间戳
,注意是整数,代表的是秒value: 代表该metric在当前时间点的值,float64step: 表示该数据采集项的汇报周期,这对于后续的配置监控策略很重要,必须明确指定。counterType: 只能是COUNTER或者GAUGE二选一,前者表示该数据采集项为计时器类型,后者表示其为原值 (注意大小写)GAUGE:即用户上传什么样的值,就原封不动的存储COUNTER:指标在存储和展现的时候,会被计算为speed,即(当前值 - 上次值)/ 时间间隔tags: 一组逗号分割的键值对, 对metric进一步描述和细化, 可以是空字符串. 比如idc=lg,比如service=xbox等,多个tag之间用逗号分割 说明:这7个字段都是必须指定
Mysql 监控
想要监控Mysql 就需要知道我们监控Mysql需要看哪些指标,然后进行
数据收集
。
监控指标
通常会看 - 系统方面
由于太多我就不意义列举了,挑一些比较重要的
有人问这些指标都哪来的都是通过,mysql sql获取的
show master status;
show slave status;
show global status;
show global variables;
我知道指标了、也知道这些指标怎么获取,我们现在要将获得数据转化Json 数据 Push到 Agent API接口就可以了。
由于已经有第三方产品已经完成了,我们直接使用就行。当然你可以用Python、go去收集数据Push。
安装配置
mymon Github 地址
编译包
# 原来go包地址
cd /root/go/src/github.com/open-falcon/
git clone https://github.com/open-falcon/mymon.git
cd mymon
# 编译
[root@open-falcon-1 mymon]# make
[92mRun gofmt on all source files ...[0m
gofmt -l -s -w ...
==> Checking that build is using go version >= 1.10...
go build -o mymon
配置文件修改 vim etc/myMon.cfg
设置定时任务
[root@open-falcon-1 mymon]# pwd
/root/go/src/github.com/open-falcon/mymon
crontab -e
# 写入如下
* * * * * cd /root/go/src/github.com/open-falcon/mymon && ./mymon -c etc/myMon.cfg
web控制台
更多指标参考:各个指标在/mymon/metrics.txt
Redis
有很多方式: 1. go 参考这个redis-metrics
Python 参考这个
Redismon
或者直接写Python脚本
#!/bin/env python
#-*- coding:utf-8 -*-
import json
import time
import socket
import os
import re
import sys
import commands
import urllib2, base64
class RedisStats:
# 如果你是自己编译部署到redis,请将下面的值替换为你到redis-cli路径
_redis_cli = /usr/bin/redis-cli
_stat_regex = re.compile(ur(w+):([0-9]+.?[0-9]*)
)
def __init__(self, port=6379, passwd=None, host=127.0.0.1):
self._cmd = %s -h %s -p %s info % (self._redis_cli, host, port)
if passwd not in [, None]:
self._cmd = %s -h %s -p %s -a %s info % (self._redis_cli, host, port, passwd)
def stats(self):
Return a dict containing redis stats
info = commands.getoutput(self._cmd)
return dict(self._stat_regex.findall(info))
def main():
ip = socket.gethostname()
timestamp = int(time.time())
step = 60
# inst_list中保存了redis配置文件列表,程序将从这些配置中读取port和password,建议使用动态发现的方法获得,如:
# inst_list = [ i for i in commands.getoutput("find /etc/ -name redis*.conf" ).split(
) ]
insts_list = [ /etc/redis/redis.conf ]
p = []
monit_keys = [
(connected_clients,GAUGE),
(blocked_clients,GAUGE),
(used_memory,GAUGE),
(used_memory_rss,GAUGE),
(mem_fragmentation_ratio,GAUGE),
(total_commands_processed,COUNTER),
(rejected_connections,COUNTER),
(expired_keys,COUNTER),
(evicted_keys,COUNTER),
(keyspace_hits,COUNTER),
(keyspace_misses,COUNTER),
(keyspace_hit_ratio,GAUGE),
]
for inst in insts_list:
port = commands.getoutput("sed -n s/^port *([0-9]{4,5})/\1/p %s" % inst)
passwd = commands.getoutput("sed -n s/^requirepass *([^ ]*)/\1/p %s" % inst)
metric = "redis"
endpoint = ip
tags = port=%s % port
try:
conn = RedisStats(port, passwd)
stats = conn.stats()
except Exception,e:
continue
for key,vtype in monit_keys:
#一些老版本的redis中info输出的信息很少,如果缺少一些我们需要采集的key就跳过
if key not in stats.keys():
continue
#计算命中率
if key == keyspace_hit_ratio:
try:
value = float(stats[keyspace_hits])/(int(stats[keyspace_hits]) + int(stats[keyspace_misses]))
except ZeroDivisionError:
value = 0
#碎片率是浮点数
elif key == mem_fragmentation_ratio:
value = float(stats[key])
else:
#其他的都采集成counter,int
try:
value = int(stats[key])
except:
continue
i = {
Metric: %s.%s % (metric, key),
Endpoint: endpoint,
Timestamp: timestamp,
Step: step,
Value: value,
CounterType: vtype,
TAGS: tags
}
p.append(i)
print json.dumps(p, sort_keys=True,indent=4)
method = "POST"
handler = urllib2.HTTPHandler()
opener = urllib2.build_opener(handler)
url = http://127.0.0.1:1988/v1/push
request = urllib2.Request(url, data=json.dumps(p) )
request.add_header("Content-Type",application/json)
request.get_method = lambda: method
try:
connection = opener.open(request)
except urllib2.HTTPError,e:
connection = e
# check. Substitute with appropriate HTTP code.
if connection.code == 200:
print connection.read()
else:
print {"err":1,"msg":"%s"} % connection
if __name__ == __main__:
proc = commands.getoutput( ps -ef|grep %s|grep -v grep|wc -l % os.path.basename(sys.argv[0]))
sys.stdout.flush()
if int(proc) < 5:
main()

使用方法
根据实际部署情况,修改有注释位置附近的配置测试: python redis-monitor.py将脚本加入crontab执行即可
nginx
参考我另一篇文章 open-falcon nginx 监控
业务类型
参考我之前写的另一篇 Open-falcon 自定义监控一些应用
其他服务监控 参考
官网地址
,不觉得麻烦自己写就行。
各位小伙伴如果觉得还可以,请关注、点赞、收藏。感谢各位!