java编程之方法模板模型

来源:互联网 发布:2017年女声网络红歌 编辑:程序博客网 时间:2024/06/06 01:05

java编程之方法模板模型

在日常开发过程中,难免遇到相对独立的功能模块的开发,如 监控告警 功能 ,
如何将此部分代码有效的管理起来,保证代码的可读性及易维护性是我们经常需要考虑的问题。 下面为大家介绍一种简单有效的编程模型-
方法模板模型,现以 监控告警 这个功能作为样例,为大家介绍‘方法模板模型’的使用。


  • 监控告警功能-方法模板关系模型Visio
  • 代码部分

方法模板关系模型Visio

这里写图片描述

代码部分

由于监控维度较多,以下只以AVG基线监控告警为例

/** * 监控告警任务上下文 */public class TaskContext {    private AlarmConfig ac;    public TaskContext(AlarmConfig alarmConfig){        this.ac = alarmConfig;    }    public TaskContext(){}    public boolean getResult(String message){        return ac.warning(message);    }    public AlarmConfig getAc() {        return ac;    }    public void setAc(AlarmConfig ac) {        this.ac = ac;    }}/** * 监控告警 配置 方法模板 */public interface AlarmConfig<T> {    String getType();    String getIntervalTime();    String getConfigJson();    boolean warning(String message);}/** * AVG基线监控配置类: * @author xiaoxiangxu * */public class AvgBaseLineConfig implements AlarmConfig{    private  String type = AlarmTypeEnum.AVG_BASELINE_LIMIT.getType();    /** 下降百分比*/    private Long threshold;    private int numberOfTimes;    //告警时间间隔    private Integer warningIntervalTime;    private String intervalTime;    private String configJson;    @Override    public String getConfigJson() {        return configJson;    }    public void setConfigJson(String configJson) {        this.configJson = configJson;    }    @Override    public String getType() {        return type;    }    @Override    public boolean warning(String message) {        return false;    }    public AvgBaseLineConfig(LinkedTreeMap<String,Object> map ,QueryServiceImpl queryService) {        List<EmergencyDefaultConfigModel> dec = queryService.queryAllEmergencyConfigModel();        if(map!=null && map.size() > 0){                NumberFormat formatter = new DecimalFormat("0");                this.setThreshold(Long.parseLong(formatter.format(map.get("threshold"))));                this.setNumberOfTimes(ParmsUtils.getSafeValue_Integer(formatter.format(map.get("numberOfTimes"))));                this.setIntervalTime((String) map.get("intervalTime"));                this.setConfigJson((String)map.get("configJson"));        }        if(dec!=null && dec.size() >0) {            EmergencyDefaultConfigModel config = dec.get(0);            if (!StringUtil.isEmpty(config.getDefultConfigJson())) {                String jsonParm = config.getDefultConfigJson().trim();                WarningDefaultConfigJsonBean depts = new Gson().fromJson(jsonParm, WarningDefaultConfigJsonBean.class);                this.setWarningIntervalTime(depts.getAvgBaseLineConfig().getWarningIntervalTime());            }        }    }    public AvgBaseLineConfig(WarningDefaultConfigJsonBean.AvgBaseLineConfig_ t) {        this.setConfigJson(t.getConfigJson());        this.setIntervalTime(t.getIntervalTime());        this.setWarningIntervalTime(t.getWarningIntervalTime());        this.setThreshold(NumberUtil.toLong(String.valueOf(t.getThreshold())));        this.setNumberOfTimes(t.getNumberOfTimes());    }    public void setType(String type) {        this.type = type;    }    public long getThreshold() {        return threshold;    }    public void setThreshold(long threshold) {        this.threshold = threshold;    }    public int getNumberOfTimes() {        return numberOfTimes;    }    public void setNumberOfTimes(int numberOfTimes) {        this.numberOfTimes = numberOfTimes;    }    public Integer getWarningIntervalTime() {        return warningIntervalTime;    }    public void setWarningIntervalTime(Integer warningIntervalTime) {        this.warningIntervalTime = warningIntervalTime;    }    @Override    public String getIntervalTime() {        return intervalTime;    }    public void setIntervalTime(String intervalTime) {        this.intervalTime = intervalTime;    }    public AvgBaseLineConfig() {}}/** * Created by xiaoxiangxu on 2015/12/14. */@Componentpublic abstract class AlarmTaskTemplate {    private static final Logger LOG = new Logger(AlarmTaskTemplate.class);    public static final int DEFAULT_BATCH_SIZE = 1;//默认一个批次数量    private String CQL_RESULT_QUERY = "select b_content from test.baseline_result where b_id='_KEY'";    @Resource    protected CacheDomain cacheDomain;    @Resource    protected SearchDomain searchDomain;    @Resource    protected CacheClient cacheClient;    @Resource    protected QueryServiceImpl queryService;    protected ReadWriteLock lock = new ReentrantReadWriteLock(false);    private String warningKey = "";    private AlarmTaskModel tm ;    private Long startTime;    private Long endTime;    private List<EmergencyDefaultConfigModel> dec;    /**     * 过滤满足条件的监控数据     * @param taskModelList     * @param interval     */    protected abstract boolean toWarning(List<AlarmTaskModel> taskModelList,String interval);    /**     * 告警信息     * @param     * @param config     * @param yearMonthIndex     * @param searchModel     * @return     */    protected abstract String getAlarmMessage(Object config, String yearMonthIndex, SearchModel searchModel) ;    /**     * 获取基线key     * @param     * @param key     * @return     */    protected abstract String getBaselineKey(String key) ;    /**     * 开始执行JOB     * @param scheduleContext     * @return     * @throws Exception     */    public String getIntervalTime(ScheduleContext scheduleContext) throws Exception {        return scheduleContext.getTaskGetResponse().getParameter().get("interval");    }    /**     * 根据type获取默认告警时间间隔,默认1分钟     * @param type     * @return     */    public   int getDefaultIntervalTime(String type){        if(dec==null || dec.size() ==0) {            dec = queryService.queryAllEmergencyConfigModel();        }        try {            Validate.notEmpty(dec, "warning : warningDefaultConfig has not config , please config default config as soon as possible !");            EmergencyDefaultConfigModel config = dec.get(0);            if (!StringUtil.isEmpty(config.getDefultConfigJson())) {                WarningDefaultConfigJsonBean depts = new Gson().fromJson(config.getDefultConfigJson().trim(), WarningDefaultConfigJsonBean.class);                if (type.equals(AlarmTypeEnum.FAILURES.getType())) {                    return depts.getFailuresConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.AVG_BASELINE_LIMIT.getType())) {                    return depts.getAvgBaseLineConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.AVG_TIME.getType())) {                    return depts.getAvgTimeConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.LOWERLIMIT_MONITOR.getType())) {                    return depts.getLowerLimitConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.RET_CODE_MONITOR.getType())) {                    return depts.getRetCodeConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.TIME_OUT.getType())) {                    return depts.getTimeOutConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.TP_MONITOR.getType())) {                    return depts.getTpConfig().getWarningIntervalTime();                } else if (type.equals(AlarmTypeEnum.TPS_BASELINE_LIMIT.getType())) {                    return depts.getTpsBaseLineConfig().getWarningIntervalTime();                }            }        }catch (Exception e){            LOG.error(e.getMessage());            return 1;        }        return 1;    }    /**     * ES 查询条件     * @param att     * @return     */    protected SearchModel searchModel(AlarmTaskTemplate att){        try {            SearchModel searchModel = new SearchModel();            if (att != null) {                searchModel.setStartTime(att.getStartTime());                searchModel.setEndTime(att.getEndTime());                searchModel.setAppName(att.getTm().getAppName());                searchModel.setServiceName(att.getTm().getServiceName());                searchModel.setMethodName(att.getTm().getMethodName());            }            return searchModel;        }catch (Exception e){            LOG.error("CacheDomain saveWarningInterval() error : ", e);            return null;        }    }    /**     * 获取配制的监控数据列表     * @return     */    protected List<AlarmTaskModel> getTaskModelList(String interval){        // 获取设置的参数(json格式)        List<AlarmTaskModel> taskModelList= null;        //如 缓存中间隔时间列表为空,则查全部监控数据,否则按间隔时间查询        if(isEmpty(interval)) {            taskModelList = searchDomain.queryAllAlarmTaskModel();        }else {            AlarmTaskModel alarmTaskModel = new AlarmTaskModel();            alarmTaskModel.setCronExpression(interval);            taskModelList = searchDomain.queryAlarmTaskModelByInterval(alarmTaskModel);        }        return taskModelList==null?new ArrayList<AlarmTaskModel>():setOtherInfo(taskModelList);    }    /**     * 按KEY获取应用基线数据     * @return     */    public  Map<String,List<BaselinePointModel>> getBaseLineByKey(String key){        LOG.info("按KEY获取应用基线数据" ,key);        Validate.notEmpty(key, "key is empty");        return  searchDomain.searchBaselineByKey(key, CQL_RESULT_QUERY.replace("_KEY",getBaselineKey(key)));    }    /**     * 增加告警邮箱与手机号     * @param taskModelList     * @return     */    protected List<AlarmTaskModel>  setOtherInfo(List<AlarmTaskModel> taskModelList){       DepartmentOrApp departmentOrApp = null;        try {            for (AlarmTaskModel alarmTaskModel : taskModelList) {                Set<String> alarmMobiles = new HashSet<String>();                Set<String> alarmEmails = new HashSet<String>();                if (alarmTaskModel == null || StringUtil.isEmpty(alarmTaskModel.getAppName())) {                    continue;                }                alarmMobiles = StringUtil.isEmpty(alarmTaskModel.getMobiles())?new HashSet<String>():new HashSet<String>(Arrays.asList(alarmTaskModel.getMobiles().split(",")));                departmentOrApp = searchDomain.getAppCenterInfo(alarmTaskModel.getAppName());                if (departmentOrApp == null || departmentOrApp.getUser() == null) {                    continue;                }                //来源:appCenter                for (AlamUser alamUser : departmentOrApp.getUser()) {                    alarmMobiles.add(alamUser.getPhone());                    alarmEmails.add(alamUser.getMail());                }                //来源:默认配置                for(String defaultEmailAddress : Constant.BASELINE_DEFAULT_EMAIL_ADDRESS.split(",")){                    alarmEmails.add(defaultEmailAddress);                }                alarmTaskModel.setMobiles(new Gson().toJson(alarmMobiles));                alarmTaskModel.setEmails(new Gson().toJson(getWarningEmailAddressByMobileFromCache(alarmMobiles,alarmEmails)));            }        }catch (Exception e){            LOG.error("setOtherInfo error : ",e);        }        return taskModelList;    }    /**     * 通过告警手机号,查询缓存中对应的email地址     * @param alarmMobiles     * @param alarmEmails     */   public Set<String> getWarningEmailAddressByMobileFromCache(Set<String> alarmMobiles,Set<String> alarmEmails){       if(alarmMobiles==null){           return alarmMobiles;       }       try{           Map<String,LdapUserModel>  userModelMap = (Map<String,LdapUserModel>) cacheClient.getObjcet(Constant.LDAP_USER_INFO_CACHE);           if(userModelMap!=null){               Set<Map.Entry<String, LdapUserModel>> set = userModelMap.entrySet();               for(Map.Entry<String, LdapUserModel> entry : set){                   alarmEmails.add(entry.getValue().getMail());               }           }       }catch (Exception e){           LOG.error("getWarningEmailAddressByMobileFromCache error :",e);       }       return alarmEmails;   }    /**     * 获取当前数据     * @param app     */    protected Map<String, Integer> getPonitFromCassandraByKey(String type,String app,AlarmTaskTemplate template){        Map<String, Integer> map = new HashMap<String, Integer>();        //获取上次执行AlarmTask的时间戳,用于cassandra查询条件        try {            //查询cassandra AVG表数据            List<List<Map<String, Object>>> result = searchDomain.getAppDataForWarning(app,type, cacheClient.getData(template.getWarningKey()), TimeUtils.getNowDay());            if (result == null || result.size() == 0) {                return map;            }            for (int i = 0; i < result.size(); i++) {                List<Map<String, Object>> eachAppDateList = result.get(i);                if(eachAppDateList==null || eachAppDateList.size()== 0){                    continue;                }                for (int j = 0; j < eachAppDateList.size(); j++) {                    map.put(TimeUtils.dateFormatForHH_MM_SS((Long) eachAppDateList.get(j).get("t")), (Integer) eachAppDateList.get(j).get("_"));                }            }        } catch (Exception e) {            LOG.error(e.getMessage(), e);            return null;        }        return map;    }    public AlarmTaskTemplate() {}    public AlarmTaskTemplate(String warningKey, AlarmTaskModel tm, Long startTime, Long endTime) {        lock.writeLock().lock();        this.warningKey = warningKey;        this.tm = tm;        this.startTime = startTime;        this.endTime = endTime;        lock.writeLock().unlock();    }    public SearchDomain getSearchDomain() {        return searchDomain;    }    public void setSearchDomain(SearchDomain searchDomain) {        this.searchDomain = searchDomain;    }    public CacheDomain getCacheDomain() {        return cacheDomain;    }    public void setCacheDomain(CacheDomain cacheDomain) {        this.cacheDomain = cacheDomain;    }    public CacheClient getCacheClient() {        return cacheClient;    }    public void setCacheClient(CacheClient cacheClient) {        this.cacheClient = cacheClient;    }    public QueryServiceImpl getQueryService() {        return queryService;    }    public void setQueryService(QueryServiceImpl queryService) {        this.queryService = queryService;    }    public String getWarningKey() {        return warningKey;    }    public void setWarningKey(String warningKey) {        this.warningKey = warningKey;    }    public AlarmTaskModel getTm() {        return tm;    }    public void setTm(AlarmTaskModel tm) {        this.tm = tm;    }    public Long getStartTime() {        return startTime;    }    public void setStartTime(Long startTime) {        this.startTime = startTime;    }    public Long getEndTime() {        return endTime;    }    public void setEndTime(Long endTime) {        this.endTime = endTime;    }}/** * 报警任务 - 平均响应时间 * * @author */@Componentpublic class AVGBaselineAlarmTask extends AlarmJobTemplate implements SchedulerJob {    private static final Logger LOG = new Logger(AVGBaselineAlarmTask.class);    private AVGBaselineAlarmTask avg;    @Override    public void doJob(ScheduleContext scheduleContext) throws Exception {        //告警入口        long startTime = System.currentTimeMillis();        LOG.info("# AVGBaselineAlarmTask do job start ");        String interval = getIntervalTime(scheduleContext);        toWarning(getTaskModelList(interval), interval);        LOG.info("# AVGBaselineAlarmTask do job end, use ", System.currentTimeMillis() - startTime, " ms");    }    /**     * 过滤满足条件的监控数据     * @param taskModelList     * @param interval     */    @Override    protected boolean toWarning(List<AlarmTaskModel> taskModelList,String interval){        if(taskModelList==null || taskModelList.size()==0){            return false;        }        LOG.info("Alarm step2: taskModelList.size(): ",taskModelList.size(),",interval :",interval);        AvgBaseLineConfig ac;        try{            for (AlarmTaskModel taskModel : taskModelList) {                //解析监控规则 JSON 串                if (taskModel.getType().contains(AlarmTypeEnum.AVG_BASELINE_LIMIT.getType())) {                    //获取查询时间区间                    Map<String, Long> map = TimeUtils.getTimeRangesAddOffsetTime(IntervalTimeEnum.getTimeUnitByTimeFlag(interval), Constant.getOFFSETS_TIME());                    //告警任务:告警关键字,告警对象,开始时间,结束时间**avg =new AVGBaselineAlarmTask(taskModel.getType() + "-" + taskModel.getAppName() + "-" + taskModel.getServiceName() + "-" + taskModel.getMethodName() + "-" + taskModel.getType(),taskModel,map.get("startTime"), map.get("endTime") );                    //告警参数配置                    //ac = new AvgBaseLineConfig(AlarmUtil.findAlarmConfigFromList(AlarmTypeEnum.AVG_BASELINE_LIMIT.getType(), new Gson().fromJson(taskModel.getRuleParameters(), List.class)),queryService){                    ac = new AvgBaseLineConfig( new Gson().fromJson(taskModel.getRuleParameters(), WarningDefaultConfigJsonBean.AvgBaseLineConfig_.class)){                       //告警入口                        @Override                        public boolean warning(String message) {                            //告警方法:缓存对象,告警内容,告警任务模板对象,告警间隔时间                            return AlarmUtil.sendAlarmMessage(cacheDomain,message,avg,getDefaultIntervalTime(AlarmTypeEnum.AVG_BASELINE_LIMIT.getType()));**                        }                    };                    //通过告警上下文触发告警动作                    return new TaskContext(ac).getResult(getAlarmMessage(ac, "", this.searchModel(avg)));                }            }        }catch (Exception e){            LOG.info("AvgBaseLineConfig run error ",e);        }finally {            if( !StringUtil.isEmpty(interval)){                //缓存执行规则interval,作为对应用监控类型下拉选项                cacheDomain.saveWarningInterval(AlarmTypeEnum.AVG_BASELINE_LIMIT.getType(),interval);            }        }        return false;    }    /**     * @param searchModel     * @return     * @description avg基线报警     */    @Override    protected String getAlarmMessage(Object ac,String yearMonthIndex ,SearchModel searchModel) {            Validate.notNull(ac, "warning object - ac  is null");            String message = "";            AvgBaseLineConfig c = (AvgBaseLineConfig)ac;            try {                String key = searchModel.getAppName();                if(!StringUtil.isEmpty(searchModel.getServiceName())){                    key+=":"+searchModel.getServiceName();                    if(!StringUtil.isEmpty(searchModel.getMethodName())){                        key+=":"+searchModel.getMethodName();                    }                }                //通过比对基线与当前值进行比较获取告警信息                message = this.getWarningMessage(getBaseLineByKey(key),key,c,this.getPonitFromCassandraByKey(Constant.AVG_BASE_LINE,key,avg));            } catch (Exception e) {                LOG.error(e.getMessage(), e);            }        return isEmpty(message)?"": "【" + message + "】";    }    @Override    protected String getBaselineKey(String key) {        return Constant.AVG_BASE_LINE+key+TimeUtils.getBeforeDateForDay(1);    }    /**     * 根据基线值获取告警信息     * @param key_     * @param baselineMaps 基线值     * @param currentMap 当前值     * @param c 告警值     * @return     */    public String getWarningMessage(Map<String,List<BaselinePointModel>> baselineMaps,String key_,AvgBaseLineConfig c,Map<String, Integer> currentMap){        if(baselineMaps == null || baselineMaps.size() ==0 || currentMap==null || currentMap.size() ==0){            return "";        }        LOG.info("Alarm step3: AVGBaselineAlarmTask getWarningMessage currentKey:",key_,",baseline.size():",baselineMaps.size(),",currentMap.size():"+currentMap.size());        List<BaselinePointModel> baselineList  = baselineMaps.get(key_);        if(baselineList == null || baselineList.size() == 0){            return "";        }        int times_ = 0 ;        int total = 0;        for(BaselinePointModel baselinePointModel : baselineList){            if(!currentMap.containsKey(baselinePointModel.getK())){                continue;            }            int temp = currentMap.get(baselinePointModel.getK()) - baselinePointModel.getV();            //如果平均响应时间大于基线            if(temp > 0 && temp / Double.valueOf(baselinePointModel.getV()) * 100 > NumberUtil.toInt(String.valueOf(c.getThreshold()), DEFAULT_BATCH_SIZE)){                times_ ++;            }            total++;        }        if(times_ >= c.getNumberOfTimes() && total>0){            return  "AVG基线告警:KEY名称为:" + key_  + ",平均响应时间突破基线阈值:" + c.getThreshold() +  ",超出阈值:" + times_ + "次,占比为" +                    new DecimalFormat("######0.00").format((times_ / NumberUtils.toDouble(String.valueOf(total))) * 100) + "%";        }        return "";    }    /**     * 求AVG 占比     * @param     * @param key     * @param value     * @return     */    private long getBaseLinePointValue(BaselinePointModel baselinePointModel,String key,String value){        try {            Long totalValue = ParmsUtils.getSafeValue_Long(String.valueOf(baselinePointModel.getV()));            Integer pointValue = ParmsUtils.getSafeValue_Integer(value);            return totalValue - pointValue;        }catch (Exception e){            return 0L;        }    }    /**     * 获取pointMap key     * @param key_     * @return     */    private String getPonitKey(Object key_){        return ParmsUtils.getSafeValue_String(key_);    }    /**     * 求占比     * @param numerator     * @param denominator     * @return     */    private int getPercent(int numerator,int denominator){        NumberFormat formatter = new DecimalFormat("0");        Double quotient=new Double(Double.valueOf(numerator)/Double.valueOf(denominator));        return ParmsUtils.getSafeValue_Integer(formatter.format(quotient));    }    public AVGBaselineAlarmTask() {        super();    }    public AVGBaselineAlarmTask(String warningKey, AlarmTaskModel tm, Long startTime, Long endTime) {        super(warningKey, tm, startTime, endTime);    }}

到此 方法模板模型 样例介绍结束,代码量比较大未做过多删减,希望大家能够感受其中精妙之处。

0 0
原创粉丝点击