1. Pendahuluan
Banyak program sisi server saat ini dikembangkan berdasarkan Java. Untuk program Socket yang dikembangkan di Java, jika terjadi masalah setelah sisi server tersebut online, program tersebut perlu di-restart secara manual , itu masih sangat merepotkan.
Kebanyakan solusinya adalah dengan menggunakan proses lain untuk menjaga program server. Jika program server hang, jalankan program server melalui proses daemon.
Bagaimana jika proses daemon hang? Gunakan penjaga ganda untuk meningkatkan stabilitas. Penjaga A bertanggung jawab untuk memantau program server dan penjaga B. Penjaga B bertanggung jawab untuk memantau penjaga A. Jika ada masalah di kedua sisi, program dapat segera dimulai untuk meningkatkan stabilitas server. program server.
Lingkungan berjalan Java berbeda dengan program yang dikembangkan dalam bahasa seperti C. Program Java dijalankan di JVM. Berbeda dengan bahasa C yang dapat langsung membuat suatu proses, membuat proses di Java sama dengan menggunakan java -jar xxx.jar untuk memulai suatu program.
Program startup Java tidak memiliki batas instance tunggal seperti C#. Anda dapat memulai lebih dari satu, tetapi Anda tidak dapat memulai lebih dari satu. Anda tidak dapat memiliki beberapa penjaga A untuk menjaga program server.
2. Penjelasan teknis
Penjelasan teknis disini relatif kasar, silahkan cek Baidu untuk detailnya Saya hanya menjelaskan fungsinya disini.
1. perintah jps.
Alat perintah yang disertakan dengan JDK, gunakan jps -l untuk membuat daftar program Java yang sedang berjalan dan menampilkan pid dan nama program Java. Hanya valid untuk program Java. Faktanya, yang Anda lihat adalah JVM yang sedang berjalan.
2. Penggunaan kelas java.nio.channels.FileLock. Ini adalah kelas di Java IO baru. Anda dapat menggunakannya untuk mengunci file saat membaca file file dikunci oleh penggunaan program lain
3. Pembangun Proses dan Proses
Kedua prinsip tersebut serupa. Keduanya memanggil perintah sistem untuk menjalankan dan kemudian mengembalikan informasi. Tetapi pengkodean yang sulit akan menyebabkan program Java Anda kehilangan portabilitas. Anda dapat memisahkan perintah ke dalam file konfigurasi.
3. Prinsip desain
Server: program server
J: Daemon A
B: Daemon B
A.lock: kunci file daemon A
B.lock: Kunci file daemon B
--------------------------------------------------- --------------------------------
Langkah 1: Pertama, jangan pertimbangkan servernya, hanya pertimbangkan perlindungan antara A dan B.
1.A menentukan apakah B masih hidup, dan jika tidak, memulai B
2.B menentukan apakah A masih hidup, dan memulai A jika tidak.
3. Selama proses berjalan, A dan B saling pergi untuk mendapatkan kunci file masing-masing. Jika mereka mendapatkannya, itu membuktikan bahwa pihak lain sedang down, dan kemudian memulai pihak lain.
4. Saat A dimulai, dapatkan kunci dari file A.lock. Jika diperoleh, itu membuktikan bahwa A belum dimulai, maka A berjalan; jika tidak mendapatkan kunci, itu membuktikan bahwa A sudah dimulai, atau B memperoleh kunci saat melakukan penilaian. Jika A sudah memulai, dan tidak perlu memulai A lagi. Jika B mendapatkan kunci saat melakukan penilaian, tidak masalah, B tetap memulai A lagi.
5. Saat B dimulai, prinsipnya sama dengan A.
6. Jika A terputus selama pengoperasian, B menentukan bahwa A telah menutup telepon dan memulai A. Demikian pula.
Langkah 2: Bergabunglah dengan Server
1.A digunakan untuk melindungi B dan Server, dan B digunakan untuk melindungi A.
2. Prinsipnya sama dengan Langkah 1, hanya saja A mempunyai tugas ganda yaitu menjaga Serer.
3. Saat A sedang berjalan, gunakan proses pid untuk mendeteksi bahwa server telah ditutup, lalu mulai server.
4. Jika Server dan A tidak aktif, B akan memulai A, dan kemudian A akan memulai Server.
5. Jika Server dan B mati, A memulai Server dan B
6. Jika A dan B mati, penjagaannya berakhir
Langkah 3: Gunakan Shutdown untuk mengakhiri penjagaan, jika tidak maka akan dimulai secara otomatis setelah mengakhiri server.
4. Realisasi
1. Implementasi PenjagaA
Copy kode kodenya sebagai berikut:
Penjaga kelas publikA {
// GuardA digunakan untuk menjaga kuncinya sendiri
File File pribadiGuardA;
FileOutputStream fileOutputStreamGuardA pribadi;
file FileChannel pribadiChannelGuardA;
file FileLock pribadiLockGuardA;
// GuardB digunakan untuk mendeteksi kunci B
File pribadi fileGuardB;
FileOutputStream fileOutputStreamGuardB pribadi;
file FileChannel pribadiChannelGuardB;
file FileLock pribadiLockGuardB;
public GuardA() memunculkan Pengecualian {
fileGuardA = File baru(Konfigurasi.GUARD_A_LOCK);
if (!fileGuardA.exists()) {
fileGuardA.createNewFile();
}
//Dapatkan kunci file, dan keluar jika tidak dapat membuktikan bahwa GuardA telah dimulai.
fileOutputStreamGuardA = FileOutputStream baru(fileGuardA);
fileChannelGuardA = fileOutputStreamGuardA.getChannel();
fileLockGuardA = fileChannelGuardA.tryLock();
jika (fileLockGuardA == null) {
Sistem.keluar(0);
}
fileGuardB = File baru(Konfigurasi.GUARD_B_LOCK);
if (!fileGuardB.exists()) {
fileGuardB.createNewFile();
}
fileOutputStreamGuardB = FileOutputStream baru(fileGuardB);
fileChannelGuardB = fileOutputStreamGuardB.getChannel();
}
/**
* Periksa apakah B ada
*
* @return true B sudah ada
*/
checkGuardB boolean publik() {
mencoba {
fileLockGuardB = fileChannelGuardB.tryLock();
jika (fileLockGuardB == null) {
kembali benar;
} kalau tidak {
fileLockGuardB.rilis();
kembali salah;
}
} tangkapan (IOException e) {
Sistem.keluar(0);
// jangan pernah menyentuh
kembali benar;
}
}
}
2. Implementasi GuardServer
Copy kode kodenya sebagai berikut:
GuardServer kelas publik {
nama server String pribadi;
public GuardServer(String nama server) {
this.namaserver = namaserver;
}
public void startServer(String cmd) memunculkan Pengecualian {
System.out.println("Mulai Server : " + cmd);
//perintah terpisah
// String[] cmds = cmd.split(" ");
// Pembuat ProcessBuilder = ProcessBuilder baru(cmds);
//
Pembuat ProcessBuilder=ProsesBuilder baru(String baru[]{"/bin/sh","-c",cmd});
//Cari output program server ke /dev/tty
pembangun.redirectOutput(File baru("/dev/tty"));
pembangun.redirectError(File baru("/dev/tty"));
pembangun.mulai(); // melempar IOException
Thread.tidur(10000);
}
/**
* Periksa apakah layanan itu ada
*
* @return Mengembalikan pid dari program java yang dikonfigurasi
* @return pid >0 mengembalikan pid <=0, yang berarti program java yang ditentukan tidak berjalan.
* **/
public int checkServer() melempar Pengecualian {
int pid = -1;
Proses proses = null;
Pembaca BufferedReader = null;
proses = Runtime.getRuntime().exec("jps -l");
pembaca = BufferedReader baru(InputStreamReader baru(proses.getInputStream()));
garis senar;
while ((baris = pembaca.readLine()) != null) {
String[] string = baris.split("//s{1,}");
if (string.panjang <2)
melanjutkan;
if (string[1].berisi(nama server)) {
pid = Integer.parseInt(string[0]);
merusak;
}
}
pembaca.close();
proses.hancurkan();
kembalikan pid;
}
}
3. Implementasi GuardAMain
Copy kode kodenya sebagai berikut:
kelas publik GuardAMain {
public static void main(String[] args) melempar Pengecualian {
PenjagaA penjagaA = PenjagaA baru();
Konfigurasikan konfigurasi = konfigurasi baru();
Server GuardServer = GuardServer baru(configure.getServername());
sementara (benar) {
// Jalankan GuardB jika GuardB tidak berjalan
if (!guardA.checkGuardB()) {
System.out.println("Mulai PenjagaB....");
Runtime.getRuntime().exec(configure.getStartguardb());
}
// Periksa kelangsungan hidup server
if (server.checkServer() <= 0) {
boolean isServerDown = benar;
// pemeriksaan perjalanan
untuk (int saya = 0; saya < 3; saya++) {
// Jika layanan masih hidup
if (server.checkServer() > 0) {
isServerDown = salah;
merusak;
}
}
jika(isServerDown)
server.startServer(configure.getStartserver());
}
Thread.sleep(configure.getInterval());
}
}
}
4. Implementasi penutupan
Copy kode kodenya sebagai berikut:
Shutdown kelas publik {
public static void main(String[] args) melempar Pengecualian {
Konfigurasikan konfigurasi = konfigurasi baru();
System.out.println("Penjaga Shutdown..");
untuk (int saya = 0; saya < 3; saya++) {
Proses p = Runtime.getRuntime().exec("jps -l");
Pembaca BufferedReader = BufferedReader baru(InputStreamReader baru(p.getInputStream()));
garis senar;
while ((baris = pembaca.readLine()) != null) {
if (line.toLowerCase().contains("Penjaga".toLowerCase())) {
String[] string = baris.split("//s{1,}");
int pid = Integer.parseInt(string[0]);
Runtime.getRuntime().exec(configure.getKillcmd() + " " + pid);
}
}
p.tunggu();
pembaca.close();
p.hancurkan();
Thread.tidur(2000);
}
System.out.println("Penjaga sedang dimatikan");
}
}
5. GuardB mirip dengan GuardA
5. Unduh dan gunakan
Folder proyek: guard_demo
Alamat unduhan: http://pan.baidu.com/s/1bn1Y6BX
Jika Anda memiliki pertanyaan atau saran, silakan hubungi saya