1. Introduction
Many of today's server-side programs are developed based on Java. For Socket programs developed in Java, if a problem occurs after such a server-side goes online, it needs to be restarted manually. If it hangs up in the middle of the night, it is still very troublesome.
Most solutions are to use other processes to guard the server program. If the server program hangs, start the server program through the daemon process.
What if the daemon process hangs? Use dual guards to improve stability. Guard A is responsible for monitoring the server program and guard B. Guard B is responsible for monitoring guard A. If there is a problem on either side, the program can be quickly started to improve the stability of the server program.
The running environment of Java is different from programs developed in languages such as C. Java programs run on the JVM. Unlike C language, which can directly create a process, creating a process in Java is equivalent to using java -jar xxx.jar to start a program.
The Java startup program does not have a single instance limit similar to C#. You can start multiple, but you cannot start more than one. You cannot have multiple guardians A to guard the server program. What if multiple server programs are started?
2. Technical explanation
The technical explanation here is relatively rough. Please check Baidu for details. I only explain the functions here.
1. jps command.
The command tool that comes with the JDK, use jps -l to list the running Java programs and display the pid and name of the Java program. Only valid for Java programs. In fact, what you are viewing is the running JVM.
2. Use of the java.nio.channels.FileLock class. This is a class in Java new IO. You can use it to lock the file while reading the file. When you determine whether the file is locked, you can determine whether the file is locked by other programs. use
3. ProcessBuilder and Process
The two principles are similar. They both call system commands to run and then return information. But hard coding will cause your Java program to lose portability. You can separate the commands into the configuration file.
3. Design principles
Server: server program
A: Daemon A
B: Daemon B
A.lock: file lock of daemon A
B.lock: File lock of daemon B
-------------------------------------------------- --------------------------------
Step 1: First, do not consider the server, only consider the protection between A and B.
1.A determines whether B is alive, and if not, starts B
2.B determines whether A is alive, and starts A if not.
3. During the running process, A and B go to each other to get each other's file lock. If they get it, it proves that the other party is down, and then starts the other party.
4. When A starts, obtain the lock of the A.lock file. If it is obtained, it proves that A is not started, then A runs; if it does not obtain the lock, it proves that A has already started, or B obtained the lock when judging. If A has already started, and there is no need to start A again. If B gets the lock when making the judgment, it doesn't matter, B will start A again anyway.
5. When B is started, the principle is the same as A.
6. If A hangs up during operation, B determines that A has hung up and starts A. BSimilarly.
Step 2: Join Server
1.A is used to protect B and Server, and B is used to protect A.
2. The principle is the same as Step 1, except that A has multiple tasks of guarding Serer.
3. When A is running, use the process pid to detect that the server has hung up, and then start the server.
4. If both Server and A are down, B will start A, and then A will start Server.
5. If Server and B are down, A starts Server and B
6. If both A and B die, the guard ends
Step 3: Use Shutdown to end the guard, otherwise it will start automatically after ending the server.
4. Realization
1. Implementation of GuardA
Copy the code code as follows:
public class GuardA {
// GuardA is used to maintain its own lock
private File fileGuardA;
private FileOutputStream fileOutputStreamGuardA;
private FileChannel fileChannelGuardA;
private FileLock fileLockGuardA;
// GuardB is used to detect B's lock
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();
}
//Acquire the file lock, and exit if it cannot prove that GuardA has been started.
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();
}
/**
* Check whether B exists
*
* @return true B already exists
*/
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. Implementation of GuardServer
Copy the code code as follows:
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);
//separate commands
// String[] cmds = cmd.split(" ");
// ProcessBuilder builder = new ProcessBuilder(cmds);
//
ProcessBuilder builder=new ProcessBuilder(new String[]{"/bin/sh","-c",cmd});
//Locate the output of the server program to /dev/tty
builder.redirectOutput(new File("/dev/tty"));
builder.redirectError(new File("/dev/tty"));
builder.start(); // throws IOException
Thread.sleep(10000);
}
/**
* Check whether the service exists
*
* @return Returns the pid of the configured java program
* @return pid >0 returns pid <=0, which means the specified java program is not running.
* **/
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("//s{1,}");
if (strings. length < 2)
continue;
if (strings[1].contains(servername)) {
pid = Integer.parseInt(strings[0]);
break;
}
}
reader.close();
process.destroy();
return pid;
}
}
3. GuardAMain implementation
Copy the code code as follows:
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) {
// Run GuardB if GuardB is not running
if (!guardA.checkGuardB()) {
System.out.println("Start GuardB....");
Runtime.getRuntime().exec(configure.getStartguardb());
}
// Check server survival
if (server.checkServer() <= 0) {
boolean isServerDown = true;
// trip check
for (int i = 0; i < 3; i++) {
// If the service is alive
if (server.checkServer() > 0) {
isServerDown = false;
break;
}
}
if(isServerDown)
server.startServer(configure.getStartserver());
}
Thread.sleep(configure.getInterval());
}
}
}
4. Shutdown implementation
Copy the code code as follows:
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("//s{1,}");
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 is similar to GuardA
5. Download and use
Project folder: guard_demo
Download address: http://pan.baidu.com/s/1bn1Y6BX
If you have any questions or suggestions, please contact me