package com.sohu.cache.inspect.impl;
import com.sohu.cache.alert.impl.BaseAlertService;
import com.sohu.cache.entity.AppDesc;
import com.sohu.cache.entity.InstanceInfo;
import com.sohu.cache.entity.InstanceStats;
import com.sohu.cache.inspect.InspectParamEnum;
import com.sohu.cache.inspect.Inspector;
import com.sohu.cache.stats.app.AppStatsCenter;
import com.sohu.cache.stats.instance.InstanceStatsCenter;
import com.sohu.cache.util.ConstUtils;
import com.sohu.cache.util.TypeUtil;
import com.sohu.cache.web.vo.AppDetailVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 应用客户端连接监控
*
* @author leifu
* @Date 2016年6月16日
* @Time 上午9:44:34
*/
public class AppClientConnInspector extends BaseAlertService implements Inspector {
/**
* app统计相关
*/
private AppStatsCenter appStatsCenter;
/**
* 实例统计相关
*/
private InstanceStatsCenter instanceStatsCenter;
@Override
public boolean inspect(Map<InspectParamEnum, Object> paramMap) {
Long appId = MapUtils.getLong(paramMap, InspectParamEnum.SPLIT_KEY);
AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId);
if (appDetailVO == null) {
logger.warn("appId {} appDetailVO is empty", appId);
return true;
}
List<InstanceInfo> appInstanceInfoList = (List<InstanceInfo>) paramMap.get(InspectParamEnum.INSTANCE_LIST);
if (CollectionUtils.isEmpty(appInstanceInfoList)) {
logger.warn("appId {} instanceList is empty", appId);
return true;
}
// 报警阀值
int appClientConnThreshold = getClientConnThreshold(appDetailVO.getAppDesc());
int appClientConnNum = appDetailVO.getConn();
// 阀值乘以分片个数
int instanceCount = appInstanceInfoList.size();
if (appClientConnNum > appClientConnThreshold * instanceCount) {
alertAppClientConn(appDetailVO, appClientConnThreshold, instanceCount);
} else {
for (InstanceInfo instanceInfo : appInstanceInfoList) {
if (instanceInfo == null) {
continue;
}
if (instanceInfo.isOffline()) {
continue;
}
if (!TypeUtil.isRedisType(instanceInfo.getType())) {
continue;
}
// 忽略sentinel观察者
if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {
continue;
}
long instanceId = instanceInfo.getId();
InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId);
if (instanceStats == null) {
continue;
}
double instanceClientConnNum = instanceStats.getCurrConnections();
// 大于标准值
if (instanceClientConnNum > appClientConnThreshold) {
alertInstanceClientConn(instanceStats, appDetailVO, appClientConnThreshold);
}
}
}
return true;
}
/**
* 获取报警阀值(如果用户预设超过系统预设,以系统为准,反之以用户为准)
* @param appDesc
* @return
*/
private int getClientConnThreshold(AppDesc appDesc) {
int userClientConnThreshold = appDesc.getClientConnAlertValue();
int systemClientConnThreshold = ConstUtils.APP_CLIENT_CONN_THRESHOLD;
return userClientConnThreshold > systemClientConnThreshold ? systemClientConnThreshold : userClientConnThreshold;
}
/**
* 应用连接数报警
* @param appDetailVO
* @param appClientConnThreshold
* @param instanceCount
*/
private void alertAppClientConn(final AppDetailVO appDetailVO, final int appClientConnThreshold, final int instanceCount) {
AppDesc appDesc = appDetailVO.getAppDesc();
String content = String.format("应用(%s)-客户端连接数报警-预设阀值每个分片为%s-现已达到%s(分片个数:%s)-请及时关注",
appDesc.getAppId(), appClientConnThreshold, appDetailVO.getConn(), instanceCount);
String title = "CacheCloud系统-客户端连接数报警";
logger.warn("app title {}", title);
logger.warn("app content {}", content);
emailComponent.sendMail(title, content, appDetailVO.getEmailList(),
Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));
}
/**
* 单个分片连接数报警
* @param instanceStats
* @param appDetailVO
* @param appClientConnThreshold
*/
private void alertInstanceClientConn(final InstanceStats instanceStats, final AppDetailVO appDetailVO,
final int appClientConnThreshold) {
String instanceHostPort = instanceStats.getIp() + ":" + instanceStats.getPort();
String content = String.format("分片(%s,应用(%s))客户端连接数报警-预设%s-现已达到%s-请及时关注", instanceHostPort,
instanceStats.getAppId(), appClientConnThreshold, instanceStats.getCurrConnections());
String title = "CacheCloud系统-分片客户端连接数报警";
logger.warn("instance title {}", title);
logger.warn("instace content {}", content);
emailComponent.sendMail(title, content, appDetailVO.getEmailList(),
Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)));
}
public void setAppStatsCenter(AppStatsCenter appStatsCenter) {
this.appStatsCenter = appStatsCenter;
}
public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) {
this.instanceStatsCenter = instanceStatsCenter;
}
}