Chinaunix首页 | 论坛 | 博客
  • 博客访问: 834258
  • 博文数量: 167
  • 博客积分: 7173
  • 博客等级: 少将
  • 技术积分: 1671
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-04 23:07
文章分类

全部博文(167)

文章存档

2018年(1)

2017年(11)

2012年(2)

2011年(27)

2010年(88)

2009年(38)

分类: 系统运维

2010-07-06 18:13:09

    今天一个应用的memcache停了两次,在停的过程中,页面出现报错(在这里做漏一件事情,没有立刻去看看页面报什么错误---观察故障现场,而是立刻重启memcache,最后在resin的log中发现相应的错误信息),重启memcache后应用回复正常,在第一次和第二memcache down的过程中我是停留在机器上并观察负载、memcache状态等情况,发现并没有重启,但memcache在我眼皮底下就down。(后来发现同事用了一个比较旧memcache的启动脚本引起,因为该脚本在停止应用的时候把所有名为memcached的进程都杀)。以前所接触的memcache的异常是由于网络原因,但由

于代码中捕捉了异常,所以页面显示会比原来慢点,不至于报错。

   因为平时memcache运行都没发生异常情况,所以对memcache变得松懈,刚好这次相应的监控都没部署到这个应用上,同时,今次开发的同事代码没做捕捉异常,所以就发生了页面显示错误信息。

   现更新一下自己的认识;


我是这样理解,memcache是一个分布式、不冗余的cache,如果其中一个down应用是会报错误,举个java的例子,并是以简单的memcache调用为例。



一个简单的java客户端连接memcache代码如下(中间清楚了很多代码;,可以只看标示红色):

import java.util.Date;   

import com.danga.MemCached.MemCachedClient;   

import com.danga.MemCached.SockIOPool;   

  

/** 

使用memcached的缓存实用 类

*  

*/  

public class MemCached   

{   

    // 创建全局 的唯一实例  

    protected static MemCachedClient mcc = new MemCachedClient();   

       

    protected static MemCached memCached = new MemCached();   

       

    // 设置与缓 存服务器的连接池  

    static {   

        // 服 务器列表和其权重  

       String[] servers = {"127.0.0.1:11211"};   

        Integer[] weights = {3};   

  

       // 获 取socke连接池的实例对象  

        SockIOPool pool = SockIOPool.getInstance();   

  

        // 设 置服务器信息  

        pool.setServers( servers );   

        pool.setWeights( weights );   

  

        // 设 置初始连接数、最小和最大连接数以及最大处理时间  

        pool.setInitConn( 5 );   

        pool.setMinConn( 5 );   

        pool.setMaxConn( 250 );   

        pool.setMaxIdle( 1000 * 60 * 60 * 6 );   

  

        // 设 置主线程的睡眠时间  

        pool.setMaintSleep( 30 );   

  

        // 设 置TCP的参数,连接超时等  

        pool.setNagle( false );   

        pool.setSocketTO( 3000 );   

        pool.setSocketConnectTO( 0 );   

  

        // 初 始化连接池  

        pool.initialize();   

  

        // 压 缩设置,超过指定大小(单位为K)的数据都会被压缩  

        mcc.setCompressEnable( true );   

        mcc.setCompressThreshold( 64 * 1024 );   

    }   

       

    /** 

     * 保护型构造方法,不允许 实例化! 

     * 

     */  

    protected MemCached(){}   

       

    /** 

     * 获取唯一实例

     * @return 

     */  

    public static MemCached getInstance()   

    {   

        return memCached;   

    }   

       

  ……

    public static void main(String[] args)   

    {   

        MemCached cache = MemCached.getInstance();   

       ……

    }   

}

可以见到两个问题:

1. Memcache存在socket的链接

2. 有超时的错误产生

 MemCached cache = MemCached.getInstance();  

这代码中只创造memcache,却没有对socket连接超时的异常就行捕捉,所以从这看出如果代码的健壮性不够好,如果memcache down了页面就会立刻报错。

如果代码健壮性好,页面不会报错,只是数据库压力会增大,如果对小查询和小对象提取是对应用没什么影响;如果是进行大查询或大对象提取,应用就会有影响,但还是不会报错误,只是提示页面打开会很慢。


增强memcache的监控

1.增加插件对memcache进行进一步监控,已开发完成;


代码在后面贴出;
2.增加memcache_top工具帮助我们更有利的找问题所在。


3.增加网上所有的php memcache性能图表(这个是方便自己使用)

4.增加日志功能(非必须);因为
a memcache的日志功能是通过启动的时候增加vv参数进行;如果要进行日志回滚可能要重启memcache,要不然会出现日志很大。
b memcache
内存使用是直接进行内存操作,如果硬件没问题基本不会出现异常;
 有出现问题,如无意外在
dmesg下能看到;所以在以后我的启动脚本中加入该功能:
 如果半个小时内重启三次,就在下一次启动参数中加入
vv进行log输出。



check_memcache.py:
#!/usr/bin/python
#coding:utf-8
# check memcached stats
# author: oubin
# version: 1.0

import telnetlib,sys,os
import cPickle as pickle

IP='127.0.0.1'
tmpPort=os.popen(" xx'").readlines();//获取端口,因为我是写在监控配置文件中。
portLen=len(tmpPort)
if portLen <1 :
  print "mc-stats_=0"
  print "mc-uptime_=0"
  print "mc-limit-maxbytes_=0"
  print "mc-hit-rate_=0"
  print "mc-requests_=0"
  print "mc-hits_=0"
  print "mc-sets_=0"
  print "mc-cached-mem_=0"
  print "mc-bytes_=0"
  print "mc-curr-items_=0"
  print "mc-curr-connections_=0"
  sys.exit(1)
 
for i in range(0,portLen):
  list = tmpPort[i].split('\n')
  PORT = list[0]
  tn = telnetlib.Telnet()
  try:
      tn.open(IP,PORT)
  except:
      print "mc_stats_%s=%s" %(PORT,'1')
      sys.exit(2)
  tn.read_until('Escape character',0.1)
  tn.write('stats\n')
  stats=tn.read_until('END',0.1)
  tn.close()

  if len(stats) < 1:
      print "stats=%s" % 'up'
      sys.exit(1)

  list=stats.split('\n')
  stats={}
  for i in list:
      l=i.split()
      if len(l)==3:
          stats[l[1]]=l[2]


  version=stats['version']
  uptime=int(stats['uptime'])
  limit_maxbytes=int(stats['limit_maxbytes'])
  bytes=int(stats['bytes'])
  curr_items=int(stats['curr_items'])
  curr_connections=int(stats['curr_connections'])
  get_hits=int(stats['get_hits'])
  get_misses=int(stats['get_misses'])
  cmd_get=int(stats['cmd_get'])
  cmd_set=int(stats['cmd_set'])

  tmp="/tmp/.memcached/"
  path=tmp+PORT
  if os.path.exists(path):
      cache = open(path,'r')
      last_stats=pickle.load(cache)
      cache.close()
  else:
      if not os.path.exists(tmp):
          os.makedirs(tmp,mode=511)
      cache = open(path, 'wb')
      pickle.dump(stats,cache,True)
      cache.close()
      sys.exit(0)

  if len(last_stats)<=0 or (get_hits+get_misses) == 0:
      sys.exit(0)

  last_uptime=int(last_stats['uptime'])
  last_get_hits=int(last_stats['get_hits'])
  last_cmd_get=int(last_stats['cmd_get'])
  last_cmd_set=int(last_stats['cmd_set'])

  hit_rate=int(100*get_hits/(get_hits+get_misses))
  rate=(uptime-last_uptime)
  requests=(cmd_get-last_cmd_get)/rate
  hits=(get_hits-last_get_hits)/rate
  sets=(cmd_set-last_cmd_set)/rate

  cached_mem=int(100*bytes/limit_maxbytes)
  limit_maxbytes=int(limit_maxbytes/1048576)
  bytes=int(bytes/1048576)

  cache = open(path, 'wb')
  pickle.dump(stats,cache,True)
  cache.close()


  print "mc-stats_%s=%s" %(PORT,'0')
  print "mc-uptime_%s=%d" %(PORT,int(uptime/86400))
  print "mc-limit-maxbytes_%s=%d" %(PORT,limit_maxbytes)
  print "mc-hit-rate_%s=%d" %(PORT,hit_rate)
  print "mc-requests_%s=%d" %(PORT,requests)
  print "mc-hits_%s=%d" %(PORT,hits)
  print "mc-sets_%s=%d" %(PORT,sets)
  print "mc-cached-mem_%s=%d" %(PORT,cached_mem)
  print "mc-bytes_%s=%d" %(PORT,bytes)
  print "mc-curr-items_%s=%d" %(PORT,curr_items)
  print "mc-curr-connections_%s=%d" %(PORT,curr_connections)

以上脚本大家可以通过增加相应的参数进行提取。

文件:check_memcached.zip
大小:1KB
下载:下载

2.memcache_top(perl脚本)我自己使用是进行了一些修改。大家也可以按需修改。
文件:memcache-top.zip
大小:4KB
下载:下载
3.php页面显示,只在某个机器上搭个php环境,把这个memcache.php文件放上去就行了。我自己
使用也是做一些修改,大家也可以按需修改。
文件:memcache.zip
大小:7KB
下载:下载


其他的还有配合cacti,nagio进行的监控


阅读(2245) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~