Bitly运维团队的10个监控教训

bit.ly 是一个全球知名的短网址服务商,为网民提供网址和链接缩短服务。Bitly 公司2008年成立于纽约。据说 bitly  每月缩短超过10亿个网址用于社交网络分享传播。2009年5月6日 bit.ly 一度成为 Twitter 默认的短网址,后来被 Twitter 自家的 t.co 取代。今年年初 bitly 运维团队官方技术博客发了一篇文章,分享了他们的一些经验教训。以下是全文。 我们总是会监控很多指标(比如硬盘利用率、内存利用率、负载、ping等等)。除了这些,我们还从运营自家产品系统的过程中吸取了很多经验教训,这些经验教训帮助我们扩充了在bitly的监控范围。 下面是我最喜欢的推特之一,来自@DevOps_Borat           开发者的墨菲定律:如果一件事情可能会出现错误,那么这就意味着它已经出错了,只不过你还没有发现罢了。   下面是一个我们运营bitly时的监控清单,这些例子的背后故事,有时甚至可以称为痛苦的经历,帮助了bitly的成长。     1.叉率 | Fork Rate   我们曾经遇到过这样一个问题:通过设置options ipv6 disable=1和在/etc/modprobe.conf中的alias ipv6 off,将一台服务器的IPv6关闭。不过这可给我们找了一个大麻烦:每次创建一个新的curl对象,modprobe都会被调用,并通过检查net-pf-10来确定IPv6的状态。这可给服务器带来了很大的负担,最终我们发现了/proc/stat下的进程计数器会以每秒数以百计的速度增长,进而发现了上面说到的那些现象的原因。通常你会希望在一台流量稳定的机器上的叉率保持在1-10/s。
#!/bin/bash
# Copyright bitly, Aug 2011 
# written by Jehiah Czebotar

DATAFILE="/var/tmp/nagios_check_forkrate.dat"
VALID_INTERVAL=600

OK=0
WARNING=1
CRITICAL=2
UNKNOWN=-1

function usage()
{
    echo "usage: $0 --warn= --critical="
    echo "this script checks the rate processes are created"
    echo "and alerts when it goes above a certain threshold"
    echo "it saves the value from each run in $DATAFILE"
    echo "and computes a delta on the next run. It will ignore"
    echo "any values that are older than --valid-interval=$VALID_INTERVAL (seconds)"
    echo "warn and critical values are in # of new processes per second"
}

while [ "$1" != "" ]; do
    PARAM=`echo $1 | awk -F= '{print $1}'`
    VALUE=`echo $1 | awk -F= '{print $2}'`
    case $PARAM in
        -w | --warn)
            WARN_THRESHOLD=$VALUE
            ;;
        -c | --critical)
            CRITICAL_THRESHOLD=$VALUE
            ;;
        --valid-interval)
            VALID_INTERVAL=$VALUE
            ;;
        -h | --help)
            usage
            exit 0;
            ;;
    esac
    shift
done

if [ -z "$WARN_THRESHOLD" ] || [ -z "$CRITICAL_THRESHOLD" ]; then
    echo "error: --warn and --critical parameters are required"
    exit $UNKNOWN
fi
if [[ $WARN_THRESHOLD -ge $CRITICAL_THRESHOLD ]]; then
    echo "error: --warn ($WARN_THRESHOLD) can't be greater than --critical ($CRITICAL_THRESHOLD)"
    exit $UNKNOWN
fi

NOW=`date +%s`
min_valid_ts=$(($NOW - $VALID_INTERVAL))
current_process_count=`awk '/processes/ {print $2}' /proc/stat`

if [ ! -f $DATAFILE ]; then
    mkdir -p $(dirname $DATAFILE)
    echo -e "$NOW\t$current_process_count" > $DATAFILE
    echo "Missing $DATAFILE; creating"
    exit $UNKNOWN
fi

# now compare this to previous
mv $DATAFILE{,.previous}
while read ts process_count; do
    if [[ $ts -lt $min_valid_ts ]]; then
        continue
    fi
    if [[ $ts -ge $NOW ]]; then
        # we can't use data from the same second
        continue
    fi
    # calculate the rate
    process_delta=$(($current_process_count - $process_count))
    ts_delta=$(($NOW - $ts))
    current_fork_rate=`echo "$process_delta / $ts_delta" | bc`
    echo -e "$ts\t$process_count" >> $DATAFILE
done < $DATAFILE.previous
echo -e "$NOW\t$current_process_count" >> $DATAFILE

echo "fork rate is $current_fork_rate processes/second (based on the last $ts_delta seconds)"
if [[ $current_fork_rate -ge $CRITICAL_THRESHOLD ]]; then
    exit $CRITICAL
fi
if [[ $current_fork_rate -ge $WARN_THRESHOLD ]]; then
    exit $WARNING
fi
exit $OK
2.流控制包   参考网卡控制 如果你的网络设置中包括流控制包,并且你没有设置禁止它们,那么它们有时可能会引起流量丢失。(如果你觉得这听起来还不够严重,那你也许该检查下你的脑袋里都装了些什么了)。
$ /usr/sbin/ethtool -S eth0 | grep flow_control
rx_flow_control_xon: 0
rx_flow_control_xoff: 0
tx_flow_control_xon: 0
tx_flow_control_xoff: 0
注:阅读这个来更加详细的了解当你使用某些博通网卡时,这些流控制帧是如何和链接的损耗联系在一起的。   3.交换输入/输出速率   人们通常会检查超过某一阈值的交换使用率。不过即便你仅仅只有一小部分内存被交换,实际上影响性能的却是交换输入/输出的速率,而不是数量。检查交换输入/输出速率会更直观。
#!/bin/bash
# Show the rate of swapping (in number of pages) between executions

OK=0
WARNING=1
CRITICAL=2
UNKNOWN=-1
EXITFLAG=$OK

WARN_THRESHOLD=1
CRITICAL_THRESHOLD=100

IN_DATAFILE="/var/tmp/nagios_check_swap_pages_in.dat"
OUT_DATAFILE="/var/tmp/nagios_check_swap_pages_out.dat"
VALID_INTERVAL=600

function usage()
{
    echo "usage: $0 --warn= --critical="
    echo "Script checks for any swap usage"
}

while [ "$1" != "" ]; do
    PARAM=`echo $1 | awk -F= '{print $1}'`
    VALUE=`echo $1 | awk -F= '{print $2}'`
    case $PARAM in
        --warn)
            WARN_THRESHOLD=$VALUE
            ;;
        --critical)
            CRITICAL_THRESHOLD=$VALUE
            ;;
        -h | --help)
            usage
            exit 0;
            ;;
    esac
    shift
done

NOW=`date +%s`
min_valid_ts=$(($NOW - $VALID_INTERVAL))

CURRENT_PAGES_SWAPPED_IN=`vmstat -s | grep 'pages swapped in' | awk '{print $1}'`
CURRENT_PAGES_SWAPPED_OUT=`vmstat -s | grep 'pages swapped out' | awk '{print $1}'`

mkdir -p $(dirname $IN_DATAFILE)
if [ ! -f $IN_DATAFILE ]; then
    echo -e "$NOW\t$CURRENT_PAGES_SWAPPED_IN" > $IN_DATAFILE
    echo "Missing $IN_DATAFILE; creating"
    EXITFLAG=$UNKNOWN
fi
if [ ! -f $OUT_DATAFILE ]; then
    echo -e "$NOW\t$CURRENT_PAGES_SWAPPED_OUT" > $OUT_DATAFILE
    echo "Missing $OUT_DATAFILE; creating"
    EXITFLAG=$UNKNOWN
fi

if [ $EXITFLAG != $OK ]; then
    exit $EXITFLAG
fi

function swap_rate() {
    local file=$1
    local current=$2
    local rate=0

    mv $file ${file}.previous
    while read ts swap_count; do
        if [[ $ts -lt $min_valid_ts ]]; then
            continue
        fi
        if [[ $ts -ge $NOW ]]; then
            # we can't use data from the same second
            continue
        fi
        # calculate the rate
        swap_delta=$(($current - $swap_count))
        ts_delta=$(($NOW - $ts))
        rate=`echo "$swap_delta / $ts_delta" | bc`
        echo -e "$ts\t$swap_count" >> $file
    done < ${file}.previous
    echo -e "$NOW\t$current" >> $file
    echo $rate
}

in_rate=`swap_rate $IN_DATAFILE $CURRENT_PAGES_SWAPPED_IN`
out_rate=`swap_rate $OUT_DATAFILE $CURRENT_PAGES_SWAPPED_OUT`

echo "swap in/out is $in_rate/$out_rate per second"
if [[ $in_rate -ge $CRITICAL_THRESHOLD ]] || [[ $out_rate -ge $CRITICAL_THRESHOLD ]]; then
    exit $CRITICAL
fi
if [[ $in_rate -ge $WARN_THRESHOLD ]] || [[ $out_rate -ge $WARN_THRESHOLD ]]; then
    exit $WARNING
fi
exit $OK
4.服务器启动通知   意外的重启是生活的一部分。你知道你的服务器何时重启了吗?很多人都不知道。这里我们会使用一个当系统重启时会发送邮件通知的简单的初始化脚本。当添加新服务器的时候,这会很有用。同时,当服务器出现异常时,能优雅的使人了解服务器状态的变化,而不是只提供一个报警。
#!/bin/bash
#
# *************************************************
# chkconfig: 2345 99 99
# description: notify email address on system boot.
# *************************************************
# Installing:
# 1) save as /etc/rc.d/init.d/notify
# 2) set the desired email address in "MAILADD" variable
# 3) chmod a+w /etc/rc.d/init.d/notify
# 4) /sbin/chkconfig --level 2345 notify on

PATH=/bin:/usr/sbin:/usr/bin
SERVER=`hostname`
case $1 in
    start)
        PUBLIC_IP=`curl --connect-timeout 5 -s icanhazip.com`
        PUBLIC_IPV6=`curl -6 --connect-timeout 5 -s icanhazip.com`
        MAILADD=your@email.example
        mail -s " Boot of $SERVER" $MAILADD <
5.NTP的时钟偏移
 
如果这货不被检测,是的,你的某台服务器也许已经挂了。如果你从未考虑过时钟偏离,那么你甚至可能没有在你的服务器上跑过ntpd命令。通常来说,有三点可以作为检查的切入点。
    []ntpd是否在运行。[/][]你的资料中心内的时钟脉冲相位差。[/][]你的主时间服务器和外部之间的时钟脉冲相位差。[/]
  我们使用naginx check_ntp_time Plugin 做检查。   6.DNS决议 内部DNS-这是一个你会依赖却常被忽略掉的、你的构架的隐藏部分。检查它的切入点如下: 1)每个服务器的本地决议。 2)如果你的数据中心有本地DNS服务器,那么你应该检查决议,和查询的数量。 3)检查你用的每个上行DNS解析器是否可用。 外部DNS-最好能核实你的外部域名解析能正确的和你已经发布的外部域名服务器对应上。在bitly我们也依靠一些CC顶级域名,而且我们也直接监测这些认证服务器。(是的,这发生在所有的顶级域名服务器离线的时候。)     7.SSL过期   因为这种情况发生的如此之少,以至于很多人都忘记了它。修复很简单,试试更新一下SSL证书吧。
define command{
    command_name    check_ssl_expire
    command_line    $USER1$/check_http --ssl -C 14 -H $ARG1$
}
define service{
    host_name               virtual
    service_description     bitly_com_ssl_expiration
    use                     generic-service
    check_command           check_ssl_expire!bitly.com
    contact_groups          email_only
    normal_check_interval   720
    retry_check_interval    10
    notification_interval   720
}
 8.DELL服务器管理器(OMSA) 我们将bitly分别部署在两个数据中心,一个在DELL的设备上,另一个是亚马逊EC2。对于我们的DELL设备而言,监测OMSA的输出是十分重要的。它会让我们留意磁盘阵列的状态,坏掉的磁盘(可预见性的硬件故障),内存问题,能源供应状态等等。 9.连接限制   你可能在连接限制的情况下运行过例如memcached和mysql这样的东西,但是当你向外扩展应用程序层的时候,你真的监测过你离那些限制到底有多接近吗?     与此相关的是解决遇到文件修饰符限制的进程的问题。在实际操作中,我们经常在启动脚本中加入ulimit -n 65535来启动服务以最小化连接限制带来的影响。我们也可以通过 worker_rlimit_nofile来设置Nginx。   10.负载均衡器的状态   我们可以设置负载均衡器的健康检查(health check),这样我们就可以轻松的将某台服务器从轮转中剔除。(假设一个服务器挂掉了,负载均衡器将会探测到同时停止向这台服务器发送信息—译者注)我们发现健康检查的可视化十分重要,于是我们基于相同的健康检查来监控、报警。(如果你使用EC2负载均衡器,你可以通过亚马逊的API来监测ELB的状态) 一些碎碎念(这些东西也要监测) Nginx错误日志,服务重启(假设遇到错误时,会重启),numa统计,新进程核心转储。 结语 以上仅仅是我们保证bitly稳定运营的一些皮毛,如果打动了你,那么请戳。 中文原文:http://blog.jobbole.com/62783/ 英文原文:http://word.bitly.com/post/74839060954/ten-things-to-monitor

0 个评论

要回复文章请先登录注册