بسم الله الرحمن الرحيم
لايخفى عليكم أهمية الانظمة الموزعة (Distributed System) في عصرنا الحاضر. فأصبح من المستحيل ان تجد برنامج يعمل منعزلا عن البيئة التي وجد فيها. فالتطبيقات الموجودة على اكثر من جهاز في بيئة معينة تحتاج للتخاطب فيما بينها لاتمام عملية معينة. دعنا ننظر الى بعض الامثلة على ذلك:
1. تصور انك تريد تصميم مشروع بحيث ان كل عميل (Client) يود ان يتصل بقاعدة البيانات واستخراج البيانات منها. ولكن المشكلة انك لاتود ان يكون هناك 10000 اتصال او اكثر بقاعدة البيانات. عندها ستحتاج ان يكون هناك component على الخادم تقوم بالاتصال بقاعدة البيانات كل وقت معين ومن ثم توزيع هذه البيانات على جميع العملاء المتصلين حاليا.
2. تود ان تجري خوارزمية تستغرق الكثير من الوقت ( هناك خوارزميات تأخذ اسابيع وحتى أحيانا شهور لاتمامها) فالحل الامثل ان تقوم بتجزئ هذه الخوارزمية وتوزيع كل جزء على جهاز معين بحيث تتمكن من استغلال الاجهزة المتوفرة لديك.
وقس على ذلك الكثير من الأمثلة.
جافا وفرت الكثير من الامكانيات للانظمة الموزعة. فهناك JMS ويطول الشرح فيها لانها مبنية على J2EE (سأقوم بطرح مقال صغير عن J2EE قريبا ان شاء الله) وهناك RMI (Remote Method Invocation) وهناك تقنيات اخرى مثل EJB و Java Distributed Object.
سوف نعرض مثالا هنا لذلك بواسطة Java RMI .
البداية مع RMI :
لانك مبرمج جافا؛ فانت تعرف انك وبكل سهولة تستطيع استدعاء كائن واجراء عملية معينة يقوم بها هذا الكائن. ولكن هذا الكائن يعيش على جهازك انت فقط. ماذا لو اردت استدعاء كائن يعيش على الخادم او على جهاز اخر واجراء عملية بداخلة والحصول على الناتج!. ببساطة : RMI تسمح لك بعمل هكذا عملية.
اذا انت تحصل على مرجع (Reference) للكائن البعيد Remote Object ثم تجري العملية المطلوبة.
ضع في عين الاعتبار انك عندما تود العمل مع RMI تحتاج لانشاء Remote Interface وهي ببساطة واجهة تبين لك الطرق التي سوف يقوم بعملها ال Remote Object. وهناك شروط معينة لهذه الواجهة حتى تستطيع العمل مع RMI :
اولا: الواجهة البعيدة Remote Interface يجب ان تكون من نوع Remote اي ان تعريفها يكون بالشكل التالي:
اقتباسpublic interface ServerIterface extends java.rmi.Remote
ثانيا: الواجهة البعيدة يجب ان تكون public . لكي يستطيع العميل الوصول لها.
ثالثا: جميع الطرق الموجودة في الواجهة يجب ان ترمي استثناء من نوع
java.rmi.RemoteException
دعنا نبدأ ونعمل تطبيق بسيط يوضح الصورة. تخيل انك تود ان تطلب من السيرفر ان يحسب حاصل ضرب عددين ويرجع الناتج فحتما ستكون الواجهة البعيدة بهذا الشكل:
import java.rmi.*;
public interface ServerInterface extends Remote{
public double getResult(double x, double y)throws RemoteException;
}الان دعنا نصمم Remote Class وايضا هناك شروط لهذه الفئة:
اولا: يجب ان تكون من نوع ServerInterface وهذا يعني انها يجب ان تحتوي على كل الطرق التي بداخلها.
ثانيا: يجب ان تكون من نوع UnicastRemoteObject.
ملاحظة: العميل سوف يحصل على مرجع من نوع ServerInterface اي ان العميل لن يستطيع تنفيذ الا طريقة واحدة وهي getResult حتى وان احتوى Remote Class على طرق اخرى.
وهنا ServerClass :
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class ServerClass extends UnicastRemoteObject implements ServerInterface
{
public ServerClass()throws RemoteException{}
public double getResult(double x, double y)throws RemoteException {
return x*y;
}
public static void main(String[] args) throws Exception {
ServerClass sc = new ServerClass();
Naming.rebind("//Localhost/PerfectTime", sc);
}
}وتلاحظ اننا في الطريقة الرئيسية قد قمنا بانشاء كائن من نوع ServerClass وقمنا بتسجيلة في Localhost .
لتنفيذ المثال السابق قم بعمل الاتي:
انشئ مجلد على القرص سي ( كمثال) وسمه RMIExample . ضع فيه الواجهة والفئة السابقتين ثم توجه الى موجه دوس واعمل الاتي:
C:\RMIExample>start rmiregistry
C:\RMIExample>rmic ServerClass
الان نود ان نستخدم هذه الفئة ServerClass لاجراء عملية الضرب.
import java.rmi.*;
public class Client{
public static void main(String[]args) throws Exception{
// ßãÇ ÞáÊ áß äÍÕá Úáì ãÑÌÚ ãä ÇáæÇÌå É
ServerInterface rr = (ServerInterface)Naming.lookup("//Localhost/ServerClass");
System.out.println(rr.getResult(3.0 , 4.0));
}
}قم بتشغيل هذه الفئة وسيظهر لك الناتج 12.0 .
هذه فكرة جدا بسيطة عن Java RMI. وقد تجاوزت عن الكثير من النقط املا مني انتها سوف تأتي من خلال الاسئلة انا بانتظاركم.