欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java实现Linux下双守护进程

程序员文章站 2024-02-29 16:14:40
一、简介   现在的服务器端程序很多都是基于java开发,针对于java开发的socket程序,这样的服务器端上线后出现问题需要手动重启,万一大半夜的挂了,还是特别麻...

一、简介

  现在的服务器端程序很多都是基于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的实现

复制代码 代码如下:

 public class guarda {
     // guarda用于维持自己的锁
     private file fileguarda;
     private fileoutputstream fileoutputstreamguarda;
     private filechannel filechannelguarda;
     private filelock filelockguarda;
     // guardb用于检测b的锁
     private file fileguardb;
     private fileoutputstream fileoutputstreamguardb;
     private filechannel filechannelguardb;
     private filelock filelockguardb;
 
     public guarda() throws exception {
         fileguarda = new file(configure.guard_a_lock);
         if (!fileguarda.exists()) {
             fileguarda.createnewfile();
         }
         //获取文件锁,拿不到证明guarda已启动则退出
         fileoutputstreamguarda = new fileoutputstream(fileguarda);
         filechannelguarda = fileoutputstreamguarda.getchannel();
         filelockguarda = filechannelguarda.trylock();
         if (filelockguarda == null) {
             system.exit(0);
         }
        
         fileguardb = new file(configure.guard_b_lock);
         if (!fileguardb.exists()) {
             fileguardb.createnewfile();
         }
         fileoutputstreamguardb = new fileoutputstream(fileguardb);
         filechannelguardb = fileoutputstreamguardb.getchannel();
     }
 
     /**
      * 检测b是否存在
      *
      * @return true b已经存在
      */
     public boolean checkguardb() {
         try {
             filelockguardb = filechannelguardb.trylock();
             if (filelockguardb == null) {
                 return true;
             } else {
                 filelockguardb.release();
                 return false;
             }
         } catch (ioexception e) {
             system.exit(0);
             // never touch
             return true;
         }
     }
 }

2、guardserver的实现

复制代码 代码如下:

 public class guardserver {
     private string servername;
 
     public guardserver(string servername) {
         this.servername = servername;
     }
 
     public void startserver(string cmd) throws exception {
         system.out.println("start server : " + cmd);
         //将命令分开
 //        string[] cmds = cmd.split(" ");
 //        processbuilder builder = new processbuilder(cmds);
    
         //
         processbuilder builder=new processbuilder(new string[]{"/bin/sh","-c",cmd});
         //将服务器程序的输出定位到/dev/tty
         builder.redirectoutput(new file("/dev/tty"));
         builder.redirecterror(new file("/dev/tty"));
         builder.start(); // throws ioexception
         thread.sleep(10000);
     }
 
     /**
      * 检测服务是否存在
      *
      * @return 返回配置的java程序的pid
      * @return pid >0 返回的是 pid <=0 代表指定java程序未运行
      * **/
     public int checkserver() throws exception {
         int pid = -1;
         process process = null;
         bufferedreader reader = null;
         process = runtime.getruntime().exec("jps -l");
         reader = new bufferedreader(new inputstreamreader(process.getinputstream()));
         string line;
         while ((line = reader.readline()) != null) {
             string[] strings = line.split(",}");
             if (strings.length < 2)
                 continue;
             if (strings[1].contains(servername)) {
                 pid = integer.parseint(strings[0]);
                 break;
             }
         }
         reader.close();
         process.destroy();
         return pid;
     }
 }

3、guardamain实现

复制代码 代码如下:

 public class guardamain {
     public static void main(string[] args) throws exception {
         guarda guarda = new guarda();
         configure configure = new configure();
         guardserver server = new guardserver(configure.getservername());
         while (true) {
             // 如果guardb未运行 运行guardb
             if (!guarda.checkguardb()) {
                 system.out.println("start guardb.....");
                 runtime.getruntime().exec(configure.getstartguardb());
             }
             // 检测服务器存活
             if (server.checkserver() <= 0) {
                 boolean isserverdown = true;
                 // trip check
                 for (int i = 0; i < 3; i++) {
                     // 如果服务是存活着
                     if (server.checkserver() > 0) {
                         isserverdown = false;
                         break;
                     }
                 }
                 if (isserverdown)
                     server.startserver(configure.getstartserver());
             }
             thread.sleep(configure.getinterval());
         }
     }
 }

4、shutdown实现

复制代码 代码如下:

 public class shutdown {
     public static void main(string[] args) throws exception {
         configure configure = new configure();
         system.out.println("shutdown guards..");
         for (int i = 0; i < 3; i++) {
             process p = runtime.getruntime().exec("jps -l");
             bufferedreader reader = new bufferedreader(new inputstreamreader(p.getinputstream()));
             string line;
             while ((line = reader.readline()) != null) {
                 if (line.tolowercase().contains("guard".tolowercase())) {
                     string[] strings = line.split(",}");
                     int pid = integer.parseint(strings[0]);
                     runtime.getruntime().exec(configure.getkillcmd() + " " + pid);
                 }
             }
             p.waitfor();
             reader.close();
             p.destroy();
             thread.sleep(2000);
         }
         system.out.println("guards is shutdown");
     }
 }

5、guardb与guarda类似

五、下载与使用

项目文件夹:guard_demo

下载地址:http://pan.baidu.com/s/1bn1y6bx

如果有什么疑问或者建议,请联系我

Java实现Linux下双守护进程