1. مقدمة
يتم تطوير العديد من البرامج من جانب الخادم اليوم بناءً على Java. بالنسبة لبرامج المقبس التي تم تطويرها في Java، إذا حدثت مشكلة بعد اتصال جانب الخادم هذا، فيجب إعادة تشغيله يدويًا إذا توقف الاتصال في منتصف الليل ، فإنه لا يزال مزعجا للغاية.
تتمثل معظم الحلول في استخدام عمليات أخرى لحماية برنامج الخادم. في حالة توقف برنامج الخادم، قم ببدء تشغيل برنامج الخادم من خلال عملية البرنامج الخفي.
ماذا لو توقفت عملية البرنامج الخفي؟ استخدم الحراس المزدوجين لتحسين الاستقرار. الحرس أ مسؤول عن مراقبة برنامج الخادم والحارس ب. الحارس ب مسؤول عن مراقبة الحارس أ. إذا كانت هناك مشكلة في أي من الجانبين، فيمكن بدء تشغيل البرنامج بسرعة لتحسين استقرار الخادم. برنامج الخادم.
تختلف بيئة تشغيل Java عن البرامج التي تم تطويرها بلغات مثل C. تعمل برامج Java على JVM. على عكس لغة C، التي يمكنها إنشاء عملية مباشرة، فإن إنشاء عملية في Java يعادل استخدام java -jar xxx.jar لبدء البرنامج.
لا يحتوي برنامج بدء تشغيل Java على حد مثيل واحد مشابه لـ C#. يمكنك بدء أكثر من واحد، لكن لا يمكنك بدء أكثر من حارس واحد A لحماية برنامج الخادم. ماذا لو تم تشغيل برامج خادم متعددة؟
2. الشرح الفني
الشرح الفني هنا تقريبي نسبيًا، يرجى مراجعة Baidu للحصول على التفاصيل، وأشرح الوظائف هنا فقط.
1.أمر جي بي إس.
أداة الأوامر التي تأتي مع JDK، استخدم jps -l لسرد برامج Java قيد التشغيل وعرض معرف pid واسم برنامج Java. صالح فقط لبرامج Java. في الواقع، ما تشاهده هو JVM قيد التشغيل.
2. استخدام فئة java.nio.channels.FileLock هذه فئة في Java IO الجديدة، يمكنك استخدامها لقفل الملف أثناء قراءة الملف تم قفل الملف بواسطة برامج أخرى
3. منشئ العملية والعملية
المبدأان متشابهان، وكلاهما يستدعي أوامر النظام للتشغيل ثم إرجاع المعلومات. لكن البرمجة الصعبة ستؤدي إلى فقدان برنامج Java الخاص بك إمكانية النقل. يمكنك فصل الأوامر في ملف التكوين.
3. مبادئ التصميم
الخادم: برنامج الخادم
ج: الشيطان أ
ب: الشيطان ب
A.lock: قفل ملف البرنامج الخفي A
B.lock: قفل ملف البرنامج الخفي B
-------------------------------------------------- --------------------------------
الخطوة 1: أولاً، لا تضع في الاعتبار الخادم، بل ضع في اعتبارك فقط الحماية بين A وB.
1.أ يحدد ما إذا كان ب على قيد الحياة، وإذا لم يكن كذلك، يبدأ ب
2.ب يحدد ما إذا كان أ على قيد الحياة، ويبدأ أ إذا لم يكن كذلك.
3. أثناء عملية التشغيل، يذهب A وB إلى بعضهما البعض للحصول على قفل الملف الخاص بكل منهما. إذا حصلوا عليه، فهذا يثبت أن الطرف الآخر معطل، ثم يبدأ الطرف الآخر.
4. عندما يبدأ A، احصل على قفل ملف A.lock، إذا تم الحصول عليه، فهذا يثبت أن A لم يبدأ، ثم يعمل A إذا لم يحصل على القفل، فهذا يثبت أن A قد بدأ بالفعل، أو حصل B على القفل عند الحكم، إذا كان A قد بدأ بالفعل، وليست هناك حاجة لبدء A مرة أخرى. إذا حصل B على القفل عند إصدار الحكم، فلا يهم، فسيبدأ B مرة أخرى على أي حال.
5. عند بدء تشغيل B، يكون المبدأ هو نفس مبدأ A.
6. إذا قام A بتعليق الاتصال أثناء العملية، فإن B يحدد أن A قد قام بتعليق الاتصال ويبدأ تشغيل A. بالمثل.
الخطوة 2: الانضمام إلى الخادم
1. يتم استخدام A لحماية B والخادم، ويتم استخدام B لحماية A.
2. المبدأ هو نفس الخطوة 1، باستثناء أن A لديه مهام متعددة لحراسة Serer.
3. عند تشغيل A، استخدم معرف العملية لاكتشاف توقف الخادم، ثم قم بتشغيل الخادم.
4. إذا كان كل من الخادم و A معطلين، فسيقوم B ببدء تشغيل A، ثم سيقوم A ببدء تشغيل الخادم.
5. إذا كان الخادم وB معطلين، يبدأ A تشغيل الخادم وB
6. إذا مات كل من A وB، ينتهي الحارس
الخطوة 3: استخدم إيقاف التشغيل لإنهاء الحماية، وإلا فسيبدأ تلقائيًا بعد إنهاء الخادم.
4. الإدراك
1. تنفيذ GuardA
انسخ رمز الكود كما يلي:
الحرس الطبقة العامة {
// يتم استخدام GuardA للحفاظ على القفل الخاص به
ملف خاص fileGuardA؛
ملف خاص OutputStream fileOutputStreamGuardA؛
ملف خاص FileChannel fileChannelGuardA؛
FileLock الخاص fileLockGuardA؛
// يتم استخدام GuardB للكشف عن قفل B
ملف خاص fileGuardB؛
ملف خاص OutputStream fileOutputStreamGuardB؛
ملف خاص FileChannel fileChannelGuardB؛
FileLock الخاص fileLockGuardB؛
يلقي GuardA () العام استثناءً {
fileGuardA = ملف جديد(Configure.GUARD_A_LOCK);
إذا (! fileGuardA.exists()) {
fileGuardA.createNewFile();
}
// احصل على قفل الملف، واخرج إذا لم يتمكن من إثبات بدء GuardA.
fileOutputStreamGuardA = new FileOutputStream(fileGuardA);
fileChannelGuardA = fileOutputStreamGuardA.getChannel();
fileLockGuardA = fileChannelGuardA.tryLock();
إذا (fileLockGuardA == null) {
System.exit(0);
}
fileGuardB = ملف جديد(Configure.GUARD_B_LOCK);
إذا (! fileGuardB.exists()) {
fileGuardB.createNewFile();
}
fileOutputStreamGuardB = new FileOutputStream(fileGuardB);
fileChannelGuardB = fileOutputStreamGuardB.getChannel();
}
/**
* التحقق من وجود B
*
* @return true B موجود بالفعل
*/
checkGuardB المنطقية العامة () {
يحاول {
fileLockGuardB = fileChannelGuardB.tryLock();
إذا (fileLockGuardB == فارغة) {
عودة صحيحة؛
} آخر {
fileLockGuardB.release();
عودة كاذبة.
}
} قبض (IOException ه) {
System.exit(0);
// لا تلمس أبدًا
عودة صحيحة؛
}
}
}
2. تنفيذ GuardServer
انسخ رمز الكود كما يلي:
الطبقة العامة GuardServer {
اسم خادم السلسلة الخاصة؛
الحرس العام (اسم خادم السلسلة) {
this.servername = servername;
}
بداية الفراغ العام (سلسلة cmd) يلقي استثناء {
System.out.println("بدء الخادم:" + 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(); // يطرح IOException
Thread.sleep(10000);
}
/**
* التحقق من وجود الخدمة
*
* @return يُرجع معرف برنامج Java الذي تم تكوينه
* @return pid >0 يُرجع pid <=0، مما يعني أن برنامج Java المحدد لا يعمل.
* **/
public int checkServer() يلقي استثناء {
معرف الهوية int = -1;
عملية العملية = فارغة؛
قارئ BufferedReader = null;
عملية = Runtime.getRuntime().exec("jps -l");
Reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
خط السلسلة؛
بينما ((line = Reader.readLine()) != null) {
String[] strings = line.split("//s{1,}");
إذا (سلاسل. الطول <2)
يكمل؛
إذا (سلاسل [1]. يحتوي على (اسم الخادم)) {
معرف المنتج = Integer.parseInt(strings[0]);
استراحة؛
}
}
Reader.Close();
عملية. تدمير ()؛
معرف الإرجاع؛
}
}
3. تنفيذ GuardAMAin
انسخ رمز الكود كما يلي:
الطبقة العامة GuardAMAin {
public static void main(String[] args) يطرح الاستثناء {
GuardA GuardA = new GuardA();
تكوين التكوين = تكوين جديد ()؛
خادم GuardServer = new GuardServer(configure.getServername());
بينما (صحيح) {
// قم بتشغيل GuardB إذا لم يكن GuardB قيد التشغيل
إذا (!guardA.checkGuardB()) {
System.out.println("ابدأ GuardB...");
Runtime.getRuntime().exec(configure.getStartguardb());
}
// التحقق من بقاء الخادم
إذا (server.checkServer() <= 0) {
boolean isServerDown = true;
// فحص الرحلة
لـ (int i = 0; i < 3; i++) {
// إذا كانت الخدمة حية
إذا (server.checkServer() > 0) {
isServerDown = false;
استراحة؛
}
}
إذا (isServerDown)
server.startServer(configure.getStartserver());
}
Thread.sleep(configure.getInterval());
}
}
}
4. تنفيذ إيقاف التشغيل
انسخ رمز الكود كما يلي:
إيقاف تشغيل الطبقة العامة {
public static void main(String[] args) يطرح الاستثناء {
تكوين التكوين = تكوين جديد ()؛
System.out.println("حارس إيقاف التشغيل..");
لـ (int i = 0; i < 3; i++) {
العملية p = Runtime.getRuntime().exec("jps -l");
BufferedReader Reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
خط السلسلة؛
بينما ((line = Reader.readLine()) != null) {
إذا (line.toLowerCase().contains("Guard".toLowerCase())) {
String[] strings = line.split("//s{1,}");
int pid = Integer.parseInt(strings[0]);
Runtime.getRuntime().exec(configure.getKillcmd() + " " + pid);
}
}
انتظر () ؛
Reader.Close();
p.destroy();
Thread.sleep(2000);
}
System.out.println("تم إيقاف تشغيل الحراس");
}
}
5. GuardB يشبه GuardA
5. التنزيل والاستخدام
مجلد المشروع:guard_demo
عنوان التنزيل: http://pan.baidu.com/s/1bn1Y6BX
إذا كان لديك أي أسئلة أو اقتراحات، يرجى الاتصال بي