一、简介



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



java守护线程有什么用 java守护进程_Server





最新内容请见作者的GitHub页:http://qaseven.github.io/