qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          打造自己的Linux服務器監控小工具

           周末在家蠻無聊的,思考人生的同時突發奇想就寫一個服務器監控的小工具吧。學JAVA快1年了,剛好檢驗一下自己!
            仔細想想呢估計作用可能也有限,畢竟外面各種監控工具也很多,初衷其實也只是練練手,加上平時比較懶,那么為了更方便的看服務器性能指標,所以就選了這個題材咯,那么就開始吧。
            不過優點也是有的嘛,至少不需要在服務器端裝一個腳本之類的了。
            一、小工具的功能
            1 能夠讀取服務器CPU,IO,Memory的性能指標并在頁面展示出來
            2 把監控的信息打印到文件,方便進行數據分析
            二、準備工作
            java開發環境、JDK1.7+、 Eclipse
            maven環境
            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頁面就可以了。
            七、感謝幫助過我的人
            1 感謝張少能、朱際華、陳淼杰等小伙伴在我開發這個小工具過程中的指點,真的學到了很多。

          posted on 2014-07-21 10:18 順其自然EVO 閱讀(2123) 評論(0)  編輯  收藏 所屬分類: 測試學習專欄

          <2014年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 那坡县| 扶余县| 佛冈县| 枣阳市| 台山市| 崇义县| 资溪县| 大石桥市| 平凉市| 株洲市| 攀枝花市| 潞城市| 方正县| 昌宁县| 买车| 井冈山市| 尉氏县| 南陵县| 龙泉市| 阿拉善右旗| 称多县| 明光市| 西吉县| 大城县| 昌图县| 贞丰县| 偃师市| 静海县| 曲靖市| 奉新县| 宽甸| 南木林县| 岳西县| 电白县| 津市市| 普定县| 安康市| 科技| 桓台县| 乐昌市| 阿坝县|