Authored by linlong

memcached监控

... ... @@ -45,6 +45,12 @@
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
... ...
package com.monitor.middleware.memcached.constant;
import com.monitor.middleware.memcached.model.MemcachedInfo;
import com.monitor.middleware.redis.model.RedisInfo;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by yoho on 2016/10/11.
*/
public interface MemConstants {
//key: "ip:port"
Map<String, MemcachedInfo> MEMCACHED_INFO_MAP = new ConcurrentHashMap<>();
Map<String,String> MEMCACHED_NAME_MAP = new ConcurrentHashMap<>(); //用于缓存memcached的l1、l2
}
... ...
package com.monitor.middleware.memcached.ctrl;
import com.monitor.cmdb.service.IMObjectInfoService;
import com.monitor.cmdb.service.ITypeInfoService;
import com.monitor.middleware.memcached.constant.MemConstants;
import com.monitor.middleware.memcached.model.MemcachedInfo;
import com.monitor.middleware.memcached.model.MemcachedVo;
import com.monitor.model.response.BaseResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.DecimalFormat;
import java.util.*;
/**
* Created by yoho on 2016/9/21.
*/
@RestController
@RequestMapping(value = "memcachedMonitor")
public class MemcachedCtrl {
public static final Logger DEBUG = LoggerFactory.getLogger(MemcachedCtrl.class);
@Autowired
IMObjectInfoService imObjectInfoService;
@Autowired
ITypeInfoService iTypeInfoService;
@RequestMapping(value = "/allMemcached")
public BaseResponse queryAllMemcached() {
BaseResponse response = new BaseResponse();
List<MemcachedVo> memList = new ArrayList<>();
if (!CollectionUtils.isEmpty(MemConstants.MEMCACHED_INFO_MAP)) {
for (Map.Entry<String, MemcachedInfo> entry : MemConstants.MEMCACHED_INFO_MAP.entrySet()) {
String key = entry.getKey();
MemcachedInfo info = entry.getValue();
MemcachedVo vo = new MemcachedVo();
bulidMemcachedVo(info, vo,key);
memList.add(vo);
}
}
Collections.sort(memList, new Comparator<MemcachedVo>() {
@Override
public int compare(MemcachedVo o1, MemcachedVo o2) {
if (o1.getName().compareTo(o2.getName()) > 0) {
return 1;
} else if (o1.getName().compareTo(o2.getName()) < 0) {
return -1;
}
return 0;
}
});
response.setData(memList);
return response;
}
/**
* 组装返回对象
* @param info
* @param vo
* @param key
*/
private void bulidMemcachedVo(MemcachedInfo info, MemcachedVo vo,String key) {
if(null!=info.getCmdGet()){
vo.setCmdGet(new DecimalFormat("0.00").format(info.getCmdGet()));
}
if(null!=info.getCmdSet()){
vo.setCmdSet(new DecimalFormat("0.00").format(info.getCmdSet()));
}
vo.setUpTime(info.getUpTime());
vo.setCurItems(info.getCurItems());
vo.setMaxMemory(info.getMaxMemory());
vo.setCurConnections(info.getCurConnections());
vo.setHitRate(info.getHitRate());
vo.setUseMemory(info.getUseMemory());
vo.setUrl(key);
vo.setName(MemConstants.MEMCACHED_NAME_MAP.get(key));
}
}
\ No newline at end of file
... ...
package com.monitor.middleware.memcached.model;
import lombok.Data;
/**
* Created by yoho on 2016/10/11.
*/
@Data
public class MemcachedInfo {
private String upTime; //运行时间
private Integer curItems; //当前items数量
private String useMemory; //使用内存
private Integer curConnections; //当前连接数
private Double cmdGet; //get频率,单位为秒
private Double cmdSet; //set频率,单位为秒
private String hitRate; //get命令命中率
private String maxMemory; //最大内存
private Long oldGet; //前一次监控的get数
private Long oldSet; //前一次监控的set数
}
... ...
package com.monitor.middleware.memcached.model;
import lombok.Data;
/**
* Created by yoho on 2016/10/11.
*/
@Data
public class MemcachedVo {
private String upTime; //运行时间
private Integer curItems; //当前items数量
private String useMemory; //使用内存
private Integer curConnections; //当前连接数
private String cmdGet; //get频率,单位为秒
private String cmdSet; //set频率,单位为秒
private String hitRate; //get命令命中率
private String maxMemory; //最大内存
private String url; //memcached地址
private String name; //memcached缓存类型 L1、L2
}
... ...
package com.monitor.middleware.memcached.service;
import com.model.MObjectInfo;
import com.model.TypeInfo;
import com.monitor.cmdb.service.IMObjectInfoService;
import com.monitor.cmdb.service.ITypeInfoService;
import com.monitor.common.config.SnsMobileConfig;
import com.monitor.common.service.AlarmMsgService;
import com.monitor.middleware.memcached.constant.MemConstants;
import com.monitor.middleware.memcached.model.MemcachedInfo;
import lombok.Getter;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.XMemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import net.rubyeye.xmemcached.utils.AddrUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeoutException;
/**
* Created by yoho on 2016/10/11.
*/
@Service
@EnableScheduling
public class MemcachedMonitorImpl {
public static final Logger LOGGER = LoggerFactory.getLogger(MemcachedMonitorImpl.class);
private Map<String, List<MObjectInfo>> serversMap;
@Autowired
private ITypeInfoService typeService;
@Autowired
private IMObjectInfoService mobjectService;
@Getter
private AlarmMsgService alarmMsgService;
@Getter
private SnsMobileConfig snsMobileConfig;
@Scheduled(fixedRate = 2 * 60 * 1000)
public void monitor() {
//遍历所有的redis / twemproxy
serversMap = getServersMap();
List<MObjectInfo> memcachedList = new ArrayList<>();
StringBuffer monitorUrl = new StringBuffer(); //监控url,将所有memcached的ip port进行拼接
for (Map.Entry<String, List<MObjectInfo>> entry : serversMap.entrySet()) {
List<MObjectInfo> info = entry.getValue();
if (!CollectionUtils.isEmpty(info)) {
for (MObjectInfo mobjectInfo : info) {
memcachedList.add(mobjectInfo);
String ip = mobjectInfo.getMoHostIp();
String port = mobjectInfo.getMoTags().split(":")[1];
MemConstants.MEMCACHED_NAME_MAP.put(ip + ":" + port,mobjectInfo.getMoName());
monitorUrl.append(ip + ":" + port + " ");
}
}
}
doMonitor(monitorUrl);
}
private void doMonitor(StringBuffer monitorUrl) {
Map<InetSocketAddress, Map<String, String>> result = new HashMap<>();
try {
MemcachedClient client = new XMemcachedClient(AddrUtil.getAddresses(monitorUrl.toString().trim()));
result = client.getStats();
LOGGER.debug("MemcachedMonitorImpl.doMonitor:get memcached status is {}",result);
client.shutdown();
} catch (IOException e) {
LOGGER.error("MemcachedMonitorImpl.doMonitor:creatr/shutdown memcached client occurs Exception: ", e.getMessage());
this.getAlarmMsgService().sendSms("Memcached", "Can not connect to Memcached " + monitorUrl.toString() + " .", this.getSnsMobileConfig().getBaseMobile());
} catch (MemcachedException e) {
LOGGER.error("MemcachedMonitorImpl.doMonitor:get memcached status occurs Exception: ", e.getMessage());
this.getAlarmMsgService().sendSms("Memcached", "Can not get Memcached status" + monitorUrl.toString() + " .", this.getSnsMobileConfig().getBaseMobile());
} catch (InterruptedException e) {
LOGGER.error("MemcachedMonitorImpl.doMonitor:get memcached status occurs Exception: ", e.getMessage());
this.getAlarmMsgService().sendSms("Memcached", "Can not get Memcached status" + monitorUrl.toString() + " .", this.getSnsMobileConfig().getBaseMobile());
} catch (TimeoutException e) {
LOGGER.error("MemcachedMonitorImpl.doMonitor:get memcached status occurs Exception: ", e.getMessage());
this.getAlarmMsgService().sendSms("Memcached", "Can not get Memcached status" + monitorUrl.toString() + " .", this.getSnsMobileConfig().getBaseMobile());
}
checkAllStatus(monitorUrl.toString().trim(),result);
if(!CollectionUtils.isEmpty(result)){
for(Map.Entry<InetSocketAddress, Map<String, String>> entry : result.entrySet()){
InetSocketAddress address = entry.getKey();
Map<String, String> value = entry.getValue();
String url = address.getAddress()+":"+address.getPort();
url = url.substring(1,url.length());
MemcachedInfo info = new MemcachedInfo();
//每秒请求数
long cmdGet = Long.parseLong(value.get("cmd_get"));
long cmdSet = Long.parseLong(value.get("cmd_set"));
info.setOldGet(cmdGet);
info.setOldSet(cmdSet);
if (MemConstants.MEMCACHED_INFO_MAP.containsKey(url)) {
long oldGet = MemConstants.MEMCACHED_INFO_MAP.get(url).getOldGet();
info.setCmdGet((cmdGet-oldGet)/120.0);
long oldSet = MemConstants.MEMCACHED_INFO_MAP.get(url).getOldSet();
info.setCmdSet((cmdSet-oldSet)/120.0);
}
info.setCurConnections(Integer.parseInt(value.get("curr_connections")));
info.setCurItems(Integer.parseInt(value.get("curr_items")));
long get_hit = Long.parseLong(value.get("get_hits"));
long get_misses = Long.parseLong(value.get("get_misses"));
long limit_maxbytes = Long.parseLong(value.get("limit_maxbytes"));
long bytes = Long.parseLong(value.get("bytes"));
long uptime = Long.parseLong(value.get("uptime"));
LOGGER.info(url+" monitor info: com_get is {},cmd_set is {},get_hit is {},get_misses is {},limit_maxbytes is {},bytes is {},uptime is {}",cmdGet,cmdSet,get_hit,get_misses,limit_maxbytes,bytes,uptime);
if((get_hit+get_misses)==0){
info.setHitRate("100.0%");
}else{
info.setHitRate(new DecimalFormat("0.00").format((get_hit*100.0/(get_hit+get_misses)))+"%");
}
info.setMaxMemory(new DecimalFormat("0.00").format(limit_maxbytes*1.0/1024/1024/1024)+" G");
info.setUpTime(uptime/(60*60*24)+" Days");
info.setUseMemory(new DecimalFormat("0.00").format(bytes*1.0/1024/1024/1024)+" G");
MemConstants.MEMCACHED_INFO_MAP.put(url,info);
}
}
}
/**
* 检查monitorUrl的地址是否都有返回状态
* @param monitorUrl
* @param result
*/
private void checkAllStatus(String monitorUrl, Map<InetSocketAddress, Map<String, String>> result) {
String[] monitorUrls = monitorUrl.split(" ");
Set<String> monitorSet = new HashSet(Arrays.asList(monitorUrls));
for(String s:monitorSet ){
s="/"+s;
}
//如果监控url的地址 多于返回的状态条数,则检查哪个url未得到状态并告警
if(!CollectionUtils.isEmpty(result)&&monitorUrls.length>result.size()){
Set<InetSocketAddress> statusSet = result.keySet();
monitorSet.removeAll(statusSet);
StringBuffer failUrl = new StringBuffer();
for(String s:monitorSet){
failUrl.append(s+" ");
}
this.getAlarmMsgService().sendSms("Memcached", "Failed to get Memcached status" + failUrl.toString() + " .", this.getSnsMobileConfig().getBaseMobile());
}
}
private Map<String, List<MObjectInfo>> getServersMap() {
Map<String, List<MObjectInfo>> serversMap = new HashMap<>();
List<TypeInfo> typeList = typeService.queryAllTypesInfo();
TypeInfo parentTypeInfo = null;
for (TypeInfo typeInfo : typeList) {
if (StringUtils.equals("memcached", typeInfo.getTypeName()) && 0 == typeInfo.getTypeIsLeaf()) {
parentTypeInfo = typeInfo;
break;
}
}
List<TypeInfo> childTypeList = typeService.queryChildTypesInfo(parentTypeInfo.getTypeId());
for (TypeInfo typeInfo : childTypeList) {
List<MObjectInfo> mObjectInfos = mobjectService.queryMObjectsInfoByType(typeInfo.getTypeId());
if (!CollectionUtils.isEmpty(mObjectInfos)) {
if (serversMap.containsKey(typeInfo.getTypeName())) {
serversMap.get(typeInfo.getTypeName()).addAll(mObjectInfos);
} else {
serversMap.put(typeInfo.getTypeName(), mObjectInfos);
}
}
}
return serversMap;
}
}
... ...