周末在家蛮无聊的,思考人生的同时突发奇想就写一个服务器监控的小工具吧。学JAVA快1年了,刚好检验一下自己!
仔细想想呢估计作用可能也有限,毕竟外面各种监控工具也很多,初衷其实也只是练练手,加上平时比较懒,那么为了更方便的看服务器性能指标,所以就选了这个题材咯,那么就开始吧。
不过优点也是有的嘛,至少不需要在服务器端装一个脚本之类的了。
一、小工具的功能
1 能够读取服务器CPU,IO,Memory的性能指标并在页面展示出来
2 把监控的信息打印到文件,方便进行数据分析
二、准备工作
1.java开发环境、JDK1.7+、 Eclipse
2.maven环境
3.git
三、使用到的框架
前台:JS的FLOT框架
后台:SpringMVC框架
工作流程图(其实蛮简单的)
项目结构目录
四、实现代码
主要的功能类
1 LinuxService 提供服务器指令输入的服务入口
2 LinuxConnectionPool 把服务器连接对象保存起来,每一次获得请求时会先检查连接是否在池子中存在,有的话直接用,没有的话就创建一个新的
3 LinuxConnection 服务器连接对象,负责创建connection
4 LinuxSessionHandle 负责创建session并执行CMD指令最后销毁session
5 EntityBaseUtil 提供了把Linux返回的结果转换成比较适合装入实体类的方法String
Transfer ListString[]
代码
1 LinuxService
package com.sunfan.monitor.service; import java.io.IOException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.sunfan.monitor.manager.pool.LinuxConnectionPool; import com.sunfan.monitor.platform.IConnectable; import com.sunfan.monitor.platform.linux.LinuxSessionHandle; /** * * @author sunfan * */ @Component public class LinuxService { private String defaultTopComand = "top -b -n 1"; private String defaultMpstatComand = "mpstat -P ALL"; private String defaultFreeCommand = "free -m"; private String defaultIostatCommand = "iostat -d -m"; @Autowired private LinuxConnectionPool pool ; @Autowired private LinuxSessionHandle handle; /** * execute default command "top -b -n 1" and return String type reslut * * @param url server's ip * @param user login name * @param password login password * @return * @throws IOException */ public String topMonitor(String url,String user,String password) throws IOException{ return this.executeCommand(url, user, password, defaultTopComand); } /** * execute default command "mpstat -P ALL" to get cpus performance * * @param url * @param user * @param password * @return * @throws IOException */ public String cpuMonitor(String url,String user,String password) throws IOException{ return this.executeCommand(url, user, password, defaultMpstatComand); } /** * execute default command "free -m" to get memory performance * @param url * @param user * @param password * @return * @throws IOException */ public String memoryMonitor(String url,String user,String password) throws IOException{ return this.executeCommand(url, user, password, defaultFreeCommand); } /** * execute default command "free -m" to get memory performance * @param url * @param user * @param password * @return * @throws IOException */ public String inputOutputMonitor(String url,String user,String password) throws IOException{ return this.executeCommand(url, user, password, defaultIostatCommand); } public String executeCommand(String url,String user,String password,String command) throws IOException{ IConnectable lc = pool.borrowObject(url,user,password); return handle.executeCommand(lc.getConnection(),command); } } |
2 LinuxConnectionPool
package com.sunfan.monitor.manager.pool; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.sunfan.monitor.manager.IConnectionPool; import com.sunfan.monitor.platform.IConnectable; import com.sunfan.monitor.platform.linux.LinuxConnection; /** * * @author sunfan * */ @Component public class LinuxConnectionPool implements IConnectionPool { private Logger logger = LoggerFactory.getLogger(getClass()); private Map<String, IConnectable> connectionPool = new HashMap<String, IConnectable>(); /** * save connecion in the connectionPool,if conn is already exist return * false else return true * * @param conn * @return */ public synchronized Boolean saveObject(IConnectable conn) { String key = rewardConnectionKey(conn); if (isExist(key)) { logger.info("this key{} has already exist", key); return false; } connectionPool.put(key, conn); return true; } /** * borrow connection object in the connect-pool * * @param key * @return */ public IConnectable borrowObject(String key) { if (!isExist(key)) { throw new IllegalArgumentException("key not found:" + key); } return connectionPool.get(key); } public IConnectable borrowObject(String url,String user,String password){ String key = this.rewardConnectionKey(url, user, password); if (!isExist(key)){ try { LinuxConnection connect = new LinuxConnection(url, user, password); connectionPool.put(key, connect); return connect; } catch (IOException e) { throw new RuntimeException("connection error"+url,e); } }else { return connectionPool.get(key); } } /** * borrow connection object in the connect-pool if the connection hasn't in * the connectionPool return null,else return connect object * * @param conn * @return */ public IConnectable borrowObject(IConnectable conn) { String key = rewardConnectionKey(conn); return borrowObject(key); } /** * close single connection in the connection-pool and close/release of this * connection * * @param conn * @throws IOException */ public void remove(IConnectable conn) throws IOException { String key = rewardConnectionKey(conn); remove(key); } /** * close single connection in the connection-pool and close/release of this * connection * * @param conn * @throws IOException */ public synchronized void remove(String key) throws IOException { if (!isExist(key)) { throw new IllegalArgumentException(key + "is not exist"); } connectionPool.get(key).close(); connectionPool.remove(key); } /** * delete every connection in the connection-pool and also close/release of * all connection * * @throws IOException */ public void clear() throws IOException { for (String keyString : connectionPool.keySet()) { connectionPool.get(keyString).close(); } connectionPool.clear(); } /** * according to the connection to generate key if the connecion is not equal * null return url/usr/password * * @param conn * @return */ public String rewardConnectionKey(IConnectable conn) { return conn.getUrl() + "/" + conn.getUser() + "/" + conn.getPassword(); } public String rewardConnectionKey(String url, String user, String password) { return url + "/" + user + "/" + password; } /** * To confirm whether the connectionPool has this key if already has return * true else return false * * @param key * @return */ public Boolean isExist(String key) { return connectionPool.containsKey(key); } } |
3 LinuxConnection
package com.sunfan.monitor.platform.linux; import java.io.Closeable; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sunfan.monitor.platform.IConnectable; import com.trilead.ssh2.Connection; import com.trilead.ssh2.ConnectionInfo; /** * * @author sunfan * */ public class LinuxConnection implements IConnectable, Closeable { Logger log = LoggerFactory.getLogger(LinuxConnection.class); private String url, user, password; private Connection connection; /** * init server's connect * * @param url * @param user * @param password * @throws IOException */ public LinuxConnection(String url, String user, String password) throws IOException{ this.url = url; this.user = user; this.password = password; this.connection = createConnection(); } /** * this method will establish connection unless username or password * incorrect and remote server is not find * * @return connection * @throws IOException */ private Connection createConnection() throws IOException { connection = new Connection(url); ConnectionInfo info = connection.connect(); // establish connection if (false == connection.authenticateWithPassword(user, password)){ log.error("connect server failed,please check the username and password. " + this.user + " " + this.password); throw new IllegalArgumentException("connection remote server fail"); } return connection; } /** * close connection */ @Override public void close() throws IOException { if (connection != null) this.connection.close(); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Connection getConnection() { return connection; } public void setConnection(Connection connection) { this.connection = connection; } } |
4 LinuxSessionHandle
package com.sunfan.monitor.platform.linux; import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.sunfan.monitor.platform.IMonitorable; import com.trilead.ssh2.Connection; import com.trilead.ssh2.Session; import com.trilead.ssh2.StreamGobbler; /** * * @author sunfan * */ @Component public class LinuxSessionHandle implements IMonitorable,Closeable{ Logger logger = LoggerFactory.getLogger(LinuxSessionHandle.class); private Session session; /** * open session then execute commands on remote server and return the result of it * @param command * @return String * @throws IOException */ public synchronized String executeCommand(Connection conn,String command) throws IOException { String str=""; try { session = conn.openSession(); session.execCommand(command); str = this.read().toString(); } catch (Exception e) { session.ping(); throw new IOException("session exception",e); } finally{ close(); } return str; } /** * read the result of remote server execute commands * @return * @throws IOException */ private StringBuffer read() throws IOException{ InputStream stdout = new StreamGobbler(session.getStdout()); BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); String tempString = null; // readLine()每次调用都默认会读一行 StringBuffer str = new StringBuffer(); while ((tempString = br.readLine()) != null) { str.append(tempString+"\r\n"); } br.close(); return str; } /** * close session */ @Override public void close() throws IOException { if (this.session != null) this.session.close(); } } 5 EntityBaseUtil package com.sunfan.monitor.entity.util; import java.util.ArrayList; import java.util.List; /** * * @author sunfan * */ public class EntityBaseUtil { /**change String result to List<String> result by split "\r\n" * remove the content above flag * to transfer List<String> ---> list<String[]> by .split("\\s{1,}") * @param result * @param flag * @return */ public List<String[]> transferListofStringArray(String result,String flag){ List<String> resList = this.transferList(result); List<String> contentList = this.removeResultHead(resList,flag); return this.transferArrayOfList(contentList); } /** * change String result to List<String> result by split "\r\n" * @param result * @return List<String> */ public List<String> transferList(String result){ String[] strs = result.split("\r\n"); List<String> list = new ArrayList<String>(); for(String s:strs){ list.add(s); } return list; } /**remove the content above flag * * @return List<String> */ public List<String> removeResultHead(List<String> resultList,String flag){ List<String> contentList = new ArrayList<String>(); contentList.addAll(resultList); for(String res:resultList){ if(res.contains(flag)){ break; } contentList.remove(res); } return contentList; } /**to transfer List<String> ---> list<String[]> by .split("\\s{1,}") * * @param contentList * @return List<String[]> */ public List<String[]> transferArrayOfList(List<String> contentList){ List<String[]> contentLists =new ArrayList<>(); for(String content:contentList){ contentLists.add(content.split("\\s{1,}")); } return contentLists; } /**get result of reference by title * * @param head data of reference title * @param title reference title * @param infos data of each reference * @return String result of reference by title ,if title is not matched ,return " " */ public String resolveValueByTagName(List<String> head,String[] infos,String title){ if(head.indexOf(title)>0){ return infos[head.indexOf(title)]; } return ""; } } |
五、测试
这个小工具耗时2个周末终于搞定了,感谢大家的观看,写的不好或者欠缺考虑的地方请@我,谢谢各位老师。
如果喜欢请点一下推荐哦,谢谢!
源码地址:https://github.com/sunfan1988/sunfan
六 将来的扩展
1 把日志功能完善
2 按照今后的需求把性能监控器逐个配置上去,基本上只要改一下controller和JSP页面就可以了。
|