package com.sohu.cache.web.controller; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.alibaba.fastjson.JSON; import com.sohu.cache.entity.ServerInfo; import com.sohu.cache.entity.ServerStatus; import com.sohu.cache.web.service.ServerDataService; /** * 获取服务器状态 */ @Controller @RequestMapping("/server") public class ServerController extends BaseController{ @Resource private ServerDataService serverDataService; private DecimalFormat df = new DecimalFormat("0.0"); /** * 跳转到主页 * @param request * @param response * @param model * @return */ @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); model.addAttribute("ip", ip); String date = request.getParameter("date"); if(date == null) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); date = sdf.format(new Date()); } model.addAttribute("date", date); return new ModelAndView("server/index"); } /** * 服务器信息概览 * @param request * @param response * @param model * @return */ @RequestMapping("/overview") public ModelAndView overview(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); //获取服务器静态信息 ServerInfo info = serverDataService.queryServerInfo(ip); if(info != null) { model.addAttribute("info", info); //解析ulimit String ulimit = info.getUlimit(); if(!StringUtils.isEmpty(ulimit)) { String[] tmp = ulimit.split(";"); if(tmp.length ==2) { String[] a = tmp[0].split(","); if(a != null && a.length == 2) { if("f".equals(a[0])) { model.addAttribute("file", a[1]); } } a = tmp[1].split(","); if(a != null && a.length == 2) { if("p".equals(a[0])) { model.addAttribute("process", a[1]); } } } } } //获取服务器状态 List<ServerStatus> list = serverDataService.queryServerOverview(ip, date); //x轴坐标 List<String> xAxis = new ArrayList<String>(); //1分钟最大load float maxLoad1 = 0; //load1总量 double totalLoad1 = 0; //最大user float maxUser = 0; //最大sys float maxSys = 0; //最大wio float maxWa = 0; //当前可用内存 float curFree = 0; //最大内存使用量 float maxUse = 0; //最大内存cache量 float maxCache = 0; //最大内存buffer量 float maxBuffer = 0; //最大swap使用量 float maxSwapUse = 0; //最大网络流入速度 float maxNetIn = 0; //最大网络流出速度 float maxNetOut = 0; //最大连接ESTABLISHED数 int maxConn = 0; //最大连接TIME_WAIT数 int maxWait = 0; //最大连接ORPHAN数 int maxOrphan = 0; //最大读取速率 float maxRead = 0; //最大写入速率 float maxWrite = 0; //最繁忙程度 float maxBusy = 0; //最大iops量 float maxIops = 0; //load serie Series<Float> load1Serie = new Series<Float>("1-min"); Series<Float> load5Serie = new Series<Float>("5-min"); Series<Float> load15Serie = new Series<Float>("15-min"); //cpu serie Series<Float> userSerie = new Series<Float>("user"); Series<Float> sysSerie = new Series<Float>("sys"); Series<Float> waSerie = new Series<Float>("wa"); //memory serie Series<Float> totalSerie = new Series<Float>("total"); Series<Float> useSerie = new Series<Float>("use"); useSerie.setType("area"); Series<Float> cacheSerie = new Series<Float>("cache"); cacheSerie.setType("area"); Series<Float> bufferSerie = new Series<Float>("buffer"); bufferSerie.setType("area"); Series<Float> swapSerie = new Series<Float>("total"); Series<Float> swapUseSerie = new Series<Float>("use"); //net serie Series<Float> netInSerie = new Series<Float>("in"); Series<Float> netOutSerie = new Series<Float>("out"); //tcp serie Series<Integer> establishedSerie = new Series<Integer>("established"); Series<Integer> twSerie = new Series<Integer>("time wait"); Series<Integer> orphanSerie = new Series<Integer>("orphan"); //disk serie Series<Float> readSerie = new Series<Float>("read"); readSerie.setType("column"); Series<Float> writeSerie = new Series<Float>("write"); writeSerie.setType("column"); Series<Float> busySerie = new Series<Float>("busy"); busySerie.setYAxis(1); Series<Float> iopsSerie = new Series<Float>("iops"); iopsSerie.setYAxis(2); for(int i = 0; i < list.size(); ++i) { ServerStatus ss = list.get(i); //x axis xAxis.add(ss.getCtime().substring(0, 2) + ":" + ss.getCtime().substring(2)); //load相关 load1Serie.addData(ss.getCload1()); load5Serie.addData(ss.getCload5()); load15Serie.addData(ss.getCload15()); maxLoad1 = getBigger(maxLoad1, ss.getCload1()); totalLoad1 += ss.getCload1(); //cpu相关 userSerie.addData(ss.getCuser()); sysSerie.addData(ss.getCsys()); waSerie.addData(ss.getCwio()); maxUser = getBigger(maxUser, ss.getCuser()); maxSys = getBigger(maxSys, ss.getCsys()); maxWa = getBigger(maxWa, ss.getCwio()); //memory相关 totalSerie.addData(ss.getMtotal()); float use = ss.getMtotal()-ss.getMfree()-ss.getMcache()-ss.getMbuffer(); useSerie.addData(use); cacheSerie.addData(ss.getMcache()); bufferSerie.addData(ss.getMbuffer()); maxUse = getBigger(maxUse, use); maxCache = getBigger(maxCache, ss.getMcache()); maxBuffer = getBigger(maxBuffer, ss.getMbuffer()); if(i == list.size() - 1) { curFree = ss.getMtotal() - use; } //swap相关 swapSerie.addData(ss.getMswap()); float swapUse = ss.getMswap() - ss.getMswapFree(); swapUse = floor(swapUse); swapUseSerie.addData(swapUse); maxSwapUse = getBigger(maxSwapUse, swapUse); //net相关 netInSerie.addData(ss.getNin()); netOutSerie.addData(ss.getNout()); maxNetIn = getBigger(maxNetIn, ss.getNin()); maxNetOut = getBigger(maxNetOut, ss.getNout()); //tcp相关 establishedSerie.addData(ss.getTuse()); twSerie.addData(ss.getTwait()); orphanSerie.addData(ss.getTorphan()); maxConn = getBigger(maxConn, ss.getTuse()); maxWait = getBigger(maxWait, ss.getTwait()); maxOrphan = getBigger(maxOrphan, ss.getTorphan()); //disk相关 readSerie.addData(ss.getDread()); writeSerie.addData(ss.getDwrite()); busySerie.addData(ss.getDbusy()); iopsSerie.addData(ss.getDiops()); maxRead = getBigger(maxRead, ss.getDread()); maxWrite = getBigger(maxWrite, ss.getDwrite()); maxBusy = getBigger(maxBusy, ss.getDbusy()); maxIops = getBigger(maxIops, ss.getDiops()); } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); //load model.addAttribute("load1", JSON.toJSONString(load1Serie)); model.addAttribute("load5", JSON.toJSONString(load5Serie)); model.addAttribute("load15", JSON.toJSONString(load15Serie)); model.addAttribute("maxLoad1", maxLoad1); model.addAttribute("avgLoad1", format(totalLoad1, list.size())); //cpu model.addAttribute("user", JSON.toJSONString(userSerie)); model.addAttribute("sys", JSON.toJSONString(sysSerie)); model.addAttribute("wa", JSON.toJSONString(waSerie)); model.addAttribute("maxUser", maxUser); model.addAttribute("maxSys", maxSys); model.addAttribute("maxWa", maxWa); //memory model.addAttribute("mtotal", JSON.toJSONString(totalSerie)); model.addAttribute("muse", JSON.toJSONString(useSerie)); model.addAttribute("mcache", JSON.toJSONString(cacheSerie)); model.addAttribute("mbuffer", JSON.toJSONString(bufferSerie)); model.addAttribute("curFree", format(curFree, 1024)); model.addAttribute("maxUse", format(maxUse, 1024)); model.addAttribute("maxCache", format(maxCache, 1024)); model.addAttribute("maxBuffer", format(maxBuffer, 1024)); //swap model.addAttribute("mswap", JSON.toJSONString(swapSerie)); model.addAttribute("mswapUse", JSON.toJSONString(swapUseSerie)); model.addAttribute("maxSwap", maxSwapUse); //net model.addAttribute("nin", JSON.toJSONString(netInSerie)); model.addAttribute("nout", JSON.toJSONString(netOutSerie)); model.addAttribute("maxNetIn", format(maxNetIn, 1024)); model.addAttribute("maxNetOut", format(maxNetOut, 1024)); //tcp model.addAttribute("testab", JSON.toJSONString(establishedSerie)); model.addAttribute("twait", JSON.toJSONString(twSerie)); model.addAttribute("torph", JSON.toJSONString(orphanSerie)); model.addAttribute("maxConn", maxConn); model.addAttribute("maxWait", maxWait); model.addAttribute("maxOrphan", maxOrphan); //disk model.addAttribute("dread", JSON.toJSONString(readSerie)); model.addAttribute("dwrite", JSON.toJSONString(writeSerie)); model.addAttribute("dbusy", JSON.toJSONString(busySerie)); model.addAttribute("diops", JSON.toJSONString(iopsSerie)); model.addAttribute("maxRead", format(maxRead, 1024)); model.addAttribute("maxWrite", format(maxWrite, 1024)); model.addAttribute("maxBusy", maxBusy); model.addAttribute("maxIops", maxIops); model.addAttribute("date", date); return new ModelAndView("server/overview"); } private String format(double a, int b) { if(b <= 0) { return "0"; } return df.format(a/b); } private float getBigger(float a, float b) { if(a > b) { return a; } return b; } private int getBigger(int a, int b) { if(a > b) { return a; } return b; } /** * 保留一位小数,四舍五入 * @param v * @return */ private float floor(float v) { return new BigDecimal(v).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue(); } /** * 获取服务器cpu各个核状态 * @param request * @param response * @param model * @return */ @RequestMapping("/cpu") public ModelAndView cpu(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); List<ServerStatus> list = serverDataService.queryServerCpu(ip, date); Map<String, CpuChart> subcpuMap = new TreeMap<String, CpuChart>(); //x轴坐标 List<String> xAxis = new ArrayList<String>(); for(ServerStatus ss : list) { String subcpuString = ss.getcExt(); String[] subCpuArray = subcpuString.split(";"); xAxis.add(ss.getCtime()); for(String subcpu : subCpuArray) { if(StringUtils.isEmpty(subcpu)) { continue; } String[] cpu = subcpu.split(","); CpuChart cpuChart = subcpuMap.get(cpu[0]); if(cpuChart == null) { cpuChart = new CpuChart(cpu[0]); subcpuMap.put(cpu[0], cpuChart); } float user = NumberUtils.toFloat(cpu[1]); float sys = NumberUtils.toFloat(cpu[2]); float wa = NumberUtils.toFloat(cpu[3]); cpuChart.addUserSeries(user); cpuChart.addSysSeries(sys); cpuChart.addWaSeries(wa); cpuChart.setMaxUser(user); cpuChart.setMaxSys(sys); cpuChart.setMaxWa(wa); cpuChart.addUser(user); cpuChart.addSys(sys); cpuChart.addWa(wa); } } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); model.addAttribute("cpu", subcpuMap.values()); return new ModelAndView("server/cpu"); } /** * 获取服务器各网卡状态 * @param request * @param response * @param model * @return */ @RequestMapping("/net") public ModelAndView net(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); List<ServerStatus> list = serverDataService.queryServerNet(ip, date); Map<String, NetChart> subnetMap = new TreeMap<String, NetChart>(); //x轴坐标 List<String> xAxis = new ArrayList<String>(); for(ServerStatus ss : list) { xAxis.add(ss.getCtime()); addNetMap(ss.getNinExt(), subnetMap, true); addNetMap(ss.getNoutExt(), subnetMap, false); } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); model.addAttribute("net", subnetMap.values()); return new ModelAndView("server/net"); } /** * parse net to map * @param netString * @param subnetMap * @param isIn */ private void addNetMap(String netString, Map<String, NetChart> subnetMap, boolean isIn) { String[] subnetArray = netString.split(";"); for(String subnet : subnetArray) { if(StringUtils.isEmpty(subnet)) { continue; } String[] net = subnet.split(","); NetChart netChart = subnetMap.get(net[0]); if(netChart == null) { netChart = new NetChart(net[0]); subnetMap.put(net[0], netChart); } float v = NumberUtils.toFloat(net[1]); if(isIn) { netChart.addInSeries(v); netChart.addTotalIn(v); netChart.setMaxIn(v); }else { netChart.addOutSeries(v); netChart.addTotalOut(v); netChart.setMaxOut(v); } } } /** * 获取硬盘各分区状态 * @param request * @param response * @param model * @return */ @RequestMapping("/disk") public ModelAndView disk(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); List<ServerStatus> list = serverDataService.queryServerDisk(ip, date); DiskChart readChart = new DiskChart(); DiskChart writeChart = new DiskChart(); DiskChart busyChart = new DiskChart(); DiskChart iopsChart = new DiskChart(); DiskChart spaceChart = new DiskChart(); //x轴坐标 List<String> xAxis = new ArrayList<String>(); for(ServerStatus ss : list) { xAxis.add(ss.getCtime()); //解析use String dext = ss.getdExt(); if(!StringUtils.isEmpty(dext)) { String[] items = dext.split(";"); if(items != null) { for(String item : items) { String[] sds = item.split("="); if(sds.length == 2) { if("DISKXFER".equals(sds[0])) { addToChart(sds[1], iopsChart); } else if("DISKREAD".equals(sds[0])) { addToChart(sds[1], readChart); } else if("DISKWRITE".equals(sds[0])) { addToChart(sds[1], writeChart); } else if("DISKBUSY".equals(sds[0])) { addToChart(sds[1], busyChart); } } } } } //解析space String space = ss.getDspace(); addToChart(space, spaceChart); } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); model.addAttribute("read", readChart); model.addAttribute("write", writeChart); model.addAttribute("busy", busyChart); model.addAttribute("iops", iopsChart); model.addAttribute("space", spaceChart); return new ModelAndView("server/disk"); } private void addToChart(String line, DiskChart chart) { String[] parts = line.split(","); for(String part : parts) { if(StringUtils.isEmpty(part)) { continue; } String[] values = part.split(":"); float d = NumberUtils.toFloat(values[1]); chart.addSeries(values[0], d); chart.setMax(d); chart.addTotal(d); } } /** * net chart */ public class NetChart{ private String name; private Series<Float> inSeries = new Series<Float>("in"); private Series<Float> outSeries = new Series<Float>("out"); private float maxIn; private float maxOut; private float totalIn; private float totalOut; public NetChart(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Series<Float> getInSeries() { return inSeries; } public void addInSeries(float d) { this.inSeries.addData(d); } public Series<Float> getOutSeries() { return outSeries; } public void addOutSeries(float d) { this.outSeries.addData(d); } public float getMaxIn() { return maxIn; } public void setMaxIn(float in) { if(this.maxIn < in) { this.maxIn = in; } } public float getMaxOut() { return maxOut; } public void setMaxOut(float out) { if(this.maxOut < out) { this.maxOut = out; } } public void addTotalIn(float in) { this.totalIn += in; } public void addTotalOut(float out) { this.totalOut += out; } public String getAvgIn() { return format(totalIn, inSeries.getData().size()); } public String getAvgOut() { return format(totalOut, outSeries.getData().size()); } } /** * disk chart */ public class DiskChart{ private float max; private float total; private Map<String, Series<Float>> seriesMap = new TreeMap<String, Series<Float>>(); public void addSeries(String partition, float d) { Series<Float> series = seriesMap.get(partition); if(series == null) { series = new Series<Float>(partition); seriesMap.put(partition, series); } series.addData(d); } public Collection<Series<Float>> getSeries() { return seriesMap.values(); } public float getMax() { return max; } public void setMax(float max) { if(this.max < max) { this.max = max; } } public String getAvg() { Collection<Series<Float>> coll = seriesMap.values(); int size = 0; if(coll != null) { for(Series<Float> series : coll) { size += series.getData().size(); } } return format(total, size); } public void addTotal(float total) { this.total += total; } } /** * cpu chart */ public class CpuChart{ private String name; private Series<Float> userSeries = new Series<Float>("user"); private Series<Float> sysSeries = new Series<Float>("sys"); private Series<Float> waSeries = new Series<Float>("wa"); private float maxUser; private float maxSys; private float maxWa; private float totalUser; private float totalSys; private float totalWa; public CpuChart(String name) { this.name = name; } public String getName() { return name; } public float getMaxUser() { return maxUser; } public void setMaxUser(float user) { if(this.maxUser < user) { this.maxUser = user; } } public float getMaxSys() { return maxSys; } public void setMaxSys(float sys) { if(this.maxSys < sys) { this.maxSys = sys; } } public float getMaxWa() { return maxWa; } public void setMaxWa(float wa) { if(this.maxWa < wa) { this.maxWa = wa; } } public String getAvgUser() { return format(totalUser, userSeries.getData().size()); } public String getAvgSys() { return format(totalSys, sysSeries.getData().size()); } public String getAvgWa() { return format(totalWa, waSeries.getData().size()); } public void addUser(float user) { this.totalUser += user; } public void addSys(float sys) { this.totalSys += sys; } public void addWa(float wa) { this.totalWa += wa; } public Series<Float> getUserSeries() { return userSeries; } public void addUserSeries(Float v) { this.userSeries.addData(v); } public Series<Float> getSysSeries() { return sysSeries; } public void addSysSeries(Float v) { this.sysSeries.addData(v); } public Series<Float> getWaSeries() { return waSeries; } public void addWaSeries(Float v) { this.waSeries.addData(v); } } /** * Highchars Series * @param <T> */ public class Series<T>{ private String name; private List<T> data = new ArrayList<T>(); private String type = "spline"; private int yAxis; public String toJson() { return JSON.toJSONString(this); } public Series(String name) { this.name = name; } public int getYAxis() { return yAxis; } public void setYAxis(int yAxis) { this.yAxis = yAxis; } public void setType(String type) { this.type = type; } public String getType() { return type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void addData(T d) { data.add(d); } public List<T> getData() { return data; } @Override public String toString() { return "Serie [name=" + name + ", data=" + data + ", type=" + type + ", yAxis=" + yAxis + "]"; } } }