qileilove

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

          java實現守護服務器程序

          一、簡介
            現在的服務器端程序很多都是基于Java開發,針對于Java開發的Socket程序,這樣的服務器端上線后出現問題需要手動重啟,萬一大半夜的掛了,還是特別麻煩的。
            大多數的解決方法是使用其他進程來守護服務器程序,如果服務器程序掛了,通過守護進程來啟動服務器程序。
            萬一守護進程掛了呢?使用雙守護來提高穩定性,守護A負責監控服務器程序與守護B,守護B負責監控守護A,任何一方出現問題,都能快速的啟動程序,提高服務器程序的穩定性。
            Java的運行環境不同于C等語言開發的程序,Java程序跑在JVM上面。不同于C語言可以直接創建進程,Java創建一個進程等同于使用java -jar xxx.jar啟動一個程序。
            Java啟動程序并沒有C#類似的單實例限制,你可以啟動多個,但是你不能啟動多個,不能讓多個守護A去守護服務器程序,萬一啟動了多個服務器程序怎么辦?
            二、技術講解
            這里的技術講解比較粗略,具體請百度一下,這里只講解作用。
            1、jps命令。
            JDK自帶的命令工具,使用jps -l可以列出正在運行的Java程序,顯示Java程序的pid與Name。只對Java程序有效,其實查看的是運行的JVM
            2、java.nio.channels.FileLock類的使用
            這個是Java new IO中的類,使用他可以維持在讀取文件的給文件加上鎖,判斷文件時候有鎖可以判斷該文件是否被其他的程序使用
            3、ProcessBuilder與Process
            這兩個原理差不多,都是調用系統的命令運行,然后返回信息。但是硬編碼會導致你的Java程序失去可移植性,可以將命令獨立到配置文件中。
            三、設計原理
            Server:服務器程序
            A:守護進程A
            B:守護進程B
            A.lock:守護進程A的文件鎖
            B.lock:守護進程B的文件鎖
            ----------------------------------------------------------------------------------
            Step 1:首先不考慮Server,只考慮A與B之間的守護
            1.A判斷B是否存活,沒有就啟動B
            2.B判斷A是否存活,沒有就啟動A
            3.在運行過程中A與B互相去拿對方的文件鎖,如果拿到了,證明對面掛了,則啟動對方。
            4.A啟動的時候,獲取A.lock文件的鎖,如果拿到了證明沒有A啟動,則A運行;如果沒有拿到鎖,證明A已經啟動了,或者是B判斷的時候拿到了鎖,如果是A已經啟動了,不需要再次啟動A,如果是B判斷的時候拿到了鎖,沒關緊  要,反正B會再次啟動A。
            5.B啟動的時候原理與A一致。
            6.運行中如果A掛了,B判斷到A已經掛了,則啟動A。B同理。
            Step 2:加入Server
            1.A用于守護B和Server,B用于守護A。
            2.原理與Step 1 一致,只是A多個一個守護Serer的任務。
            3.當A運行的時候,使用進程pid檢測到Server已經掛了,就啟動Server
            4.如果Server與A都掛了,B會啟動A,然后A啟動Server
            5.如果Server與B掛了,A啟動Server與B
            6.如果A與B都掛了,守護結束
            Step 3:使用Shutdown結束守護,不然結束Server后會自動啟動
           四、實現
            1、GuardA的實現
          1 public class GuardA {
          2     // GuardA用于維持自己的鎖
          3     private File fileGuardA;
          4     private FileOutputStream fileOutputStreamGuardA;
          5     private FileChannel fileChannelGuardA;
          6     private FileLock fileLockGuardA;
          7     // GuardB用于檢測B的鎖
          8     private File fileGuardB;
          9     private FileOutputStream fileOutputStreamGuardB;
          10     private FileChannel fileChannelGuardB;
          11     private FileLock fileLockGuardB;
          12
          13     public GuardA() throws Exception {
          14         fileGuardA = new File(Configure.GUARD_A_LOCK);
          15         if (!fileGuardA.exists()) {
          16             fileGuardA.createNewFile();
          17         }
          18         //獲取文件鎖,拿不到證明GuardA已啟動則退出
          19         fileOutputStreamGuardA = new FileOutputStream(fileGuardA);
          20         fileChannelGuardA = fileOutputStreamGuardA.getChannel();
          21         fileLockGuardA = fileChannelGuardA.tryLock();
          22         if (fileLockGuardA == null) {
          23             System.exit(0);
          24         }
          25
          26         fileGuardB = new File(Configure.GUARD_B_LOCK);
          27         if (!fileGuardB.exists()) {
          28             fileGuardB.createNewFile();
          29         }
          30         fileOutputStreamGuardB = new FileOutputStream(fileGuardB);
          31         fileChannelGuardB = fileOutputStreamGuardB.getChannel();
          32     }
          33
          34     /**
          35      * 檢測B是否存在
          36      *
          37      * @return true B已經存在
          38      */
          39     public boolean checkGuardB() {
          40         try {
          41             fileLockGuardB = fileChannelGuardB.tryLock();
          42             if (fileLockGuardB == null) {
          43                 return true;
          44             } else {
          45                 fileLockGuardB.release();
          46                 return false;
          47             }
          48         } catch (IOException e) {
          49             System.exit(0);
          50             // never touch
          51             return true;
          52         }
          53     }
          54 }
            2、GuardServer的實現
          1 public class GuardServer {
          2     private String servername;
          3
          4     public GuardServer(String servername) {
          5         this.servername = servername;
          6     }
          7
          8     public void startServer(String cmd) throws Exception {
          9         System.out.println("Start Server : " + cmd);
          10         //將命令分開
          11 //        String[] cmds = cmd.split(" ");
          12 //        ProcessBuilder builder = new ProcessBuilder(cmds);
          13
          14         //
          15         ProcessBuilder builder=new ProcessBuilder(new String[]{"/bin/sh","-c",cmd});
          16         //將服務器程序的輸出定位到/dev/tty
          17         builder.redirectOutput(new File("/dev/tty"));
          18         builder.redirectError(new File("/dev/tty"));
          19         builder.start(); // throws IOException
          20         Thread.sleep(10000);
          21     }
          22
          23     /**
          24      * 檢測服務是否存在
          25      *
          26      * @return 返回配置的java程序的pid
          27      * @return pid >0 返回的是 pid <=0 代表指定java程序未運行
          28      * **/
          29     public int checkServer() throws Exception {
          30         int pid = -1;
          31         Process process = null;
          32         BufferedReader reader = null;
          33         process = Runtime.getRuntime().exec("jps -l");
          34         reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
          35         String line;
          36         while ((line = reader.readLine()) != null) {
          37             String[] strings = line.split("\\s{1,}");
          38             if (strings.length < 2)
          39                 continue;
          40             if (strings[1].contains(servername)) {
          41                 pid = Integer.parseInt(strings[0]);
          42                 break;
          43             }
          44         }
          45         reader.close();
          46         process.destroy();
          47         return pid;
          48     }
          49 }
            3、GuardAMain實現
          1 public class GuardAMain {
          2     public static void main(String[] args) throws Exception {
          3         GuardA guardA = new GuardA();
          4         Configure configure = new Configure();
          5         GuardServer server = new GuardServer(configure.getServername());
          6         while (true) {
          7             // 如果GuardB未運行 運行GuardB
          8             if (!guardA.checkGuardB()) {
          9                 System.out.println("Start GuardB.....");
          10                 Runtime.getRuntime().exec(configure.getStartguardb());
          11             }
          12             // 檢測服務器存活
          13             if (server.checkServer() <= 0) {
          14                 boolean isServerDown = true;
          15                 // trip check
          16                 for (int i = 0; i < 3; i++) {
          17                     // 如果服務是存活著
          18                     if (server.checkServer() > 0) {
          19                         isServerDown = false;
          20                         break;
          21                     }
          22                 }
          23                 if (isServerDown)
          24                     server.startServer(configure.getStartserver());
          25             }
          26             Thread.sleep(configure.getInterval());
          27         }
          28     }
          29 }
          4、Shutdown實現
          1 public class ShutDown {
          2     public static void main(String[] args) throws Exception {
          3         Configure configure = new Configure();
          4         System.out.println("Shutdown Guards..");
          5         for (int i = 0; i < 3; i++) {
          6             Process p = Runtime.getRuntime().exec("jps -l");
          7             BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
          8             String line;
          9             while ((line = reader.readLine()) != null) {
          10                 if (line.toLowerCase().contains("Guard".toLowerCase())) {
          11                     String[] strings = line.split("\\s{1,}");
          12                     int pid = Integer.parseInt(strings[0]);
          13                     Runtime.getRuntime().exec(configure.getKillcmd() + " " + pid);
          14                 }
          15             }
          16             p.waitFor();
          17             reader.close();
          18             p.destroy();
          19             Thread.sleep(2000);
          20         }
          21         System.out.println("Guards is shutdown");
          22     }
          23 }
            5、GuardB與GuardA類似
            五、下載與使用
            項目文件夾:guard_demo
            下載地址:http://pan.baidu.com/s/1bn1Y6BX

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

          <2014年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 鸡东县| 望都县| 民县| 沙坪坝区| 车险| 吴忠市| 九江市| 乌兰浩特市| 柞水县| 永城市| 河间市| 昌黎县| 高密市| 革吉县| 南投县| 开封县| 竹溪县| 黔江区| 中宁县| 黄陵县| 太谷县| 甘孜| 丰台区| 大港区| 奎屯市| 嘉义县| 扶风县| 惠州市| 米易县| 罗定市| 封丘县| 宁海县| 襄汾县| 赤水市| 开封市| 隆林| 望江县| 定襄县| 衡阳县| 离岛区| 辉南县|