1 / 22

18. RMI 를 이용한 원격 배포

18. RMI 를 이용한 원격 배포. 원격 메소드 호출 방법 (1/2). 클라이언트와 서버 애플리케이션을 만든다 . 서버 애플리케이션은 클라이언트에서 호출하고자 하는 메소드를 가지고 있는 객체가 들어있는 원격 서비스이다 . 클라이언트 힙. 서버 힙. 클라이언트 객체. 서비스 객체. 원격 메소드 호출 방법 (2/2).

waseem
Download Presentation

18. RMI 를 이용한 원격 배포

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 18. RMI를 이용한 원격 배포

  2. 원격 메소드 호출 방법 (1/2) 클라이언트와 서버 애플리케이션을 만든다. 서버 애플리케이션은 클라이언트에서 호출하고자 하는 메소드를 가지고 있는 객체가 들어있는 원격 서비스이다. 클라이언트 힙 서버 힙 클라이언트 객체 서비스 객체 Head First JAVA

  3. 원격 메소드 호출 방법 (2/2) 클라이언트와 서버 보조 객체(helper)를 만든다. 이 보조 객체는 클라이언트와 서비스가 마치 같은 힙 안에 들어있는 것처럼 행동할 수 있도록 저 수준 네트워킹, 입출력과 관련된 자질구레한 일을 모두 처리해주는 역할을 한다. 클라이언트 보조 객체 클라이언트 객체 서비스 보조 객체 서비스 객체 클라이언트 힙 서버 힙 Head First JAVA

  4. 보조 객체의 역할 서비스 객체가 진짜 서비스이다. 클라이언트가 원했던 일을 처리하는 진짜 메소드는 바로 여기에 들어있다. 클라이언트 보조 객체는 서비스인 것처럼 행동하지만 사실은 매개해주는 역할을 할 뿐이다. 클라이언트 힙 서버 힙 클라이언트 보조 객체 클라이언트 객체 서비스 보조 객체 서비스 객체 클라이언트 객체는 진짜 서비스에 대해 메소드를 호출한다고 생각한다. 클라이언트 보조 객체가 실제로 자신이 원하는 작업을 처리해주는 객체라고 생각하는 것이다. 서비스 보조 객체는 클라이언트 보조 객체로부터 요청을 받아서 포장을 풀고 진짜 서비스에 있는 메소드를 호출한다. Head First JAVA

  5. 메소드 호출 과정 (1/3) 클라이언트 객체에서 클라이언트 보조 객체에 있는 doBigThing()을 호출한다. 클라이언트 힙 서버 힙 클라이언트 보조 객체 클라이언트 객체 서비스 보조 객체 서비스 객체 doBigThing() Head First JAVA

  6. 메소드 호출 과정 (2/3) 클라이언트 보조 객체에서 메소드 호출에 대한 정보(인자, 메소드명 등)를 포장해서 네트워크를 통해 서비스 보조 객체로 보낸다. 클라이언트 힙 서버 힙 클라이언트 보조 객체 클라이언트 객체 서비스 보조 객체 서비스 객체 클라이언트에서 메소드를 호출하고 싶어한다. Head First JAVA

  7. 메소드 호출 과정 (3/3) 서비스 보조 객체에서 클라이언트 보조 객체로부터 받은 정보를 풀어서 어떤 객체의 어떤 메소드를 호출할지 알아낸 다음 진짜 서비스 객체에 있는 진짜 메소드를 호출한다. 클라이언트 힙 서버 힙 클라이언트 보조 객체 클라이언트 객체 서비스 보조 객체 서비스 객체 doBigThing() Head First JAVA

  8. RMI 보조 객체 자바 RMI가 보조 객체를 제공하는데 클라이언트 보조 객체는 ‘스터브(stub)’고 서버 보조 객체는 ‘스켈레톤(skeleton)’이다. 클라이언트 힙 서버 힙 클라이언트 보조 객체 클라이언트 객체 서비스 보조 객체 서비스 객체 RMI 스터브 RMI 스켈레톤 Head First JAVA

  9. 원격 서비스를 만드는 방법 원격 인터페이스를 만든다. 원격 인터페이스를 구현한 클래스를 만든다. rmic를 이용하여 스터브와스켈레톤을 생성한다. RMI 레지스트리(rmiregistry)를 시작한다. 원격 서비스를 시작한다. Head First JAVA

  10. 원격 인터페이스 생성 (1/3) java.rmi.Remote를 확장한다. Remote는 표지 인터페이스(아무 메소드도 없는 인터페이스)이다. 하지만 RMI에서 특별한 의미를 가지기 때문에 이 규칙을 지켜야 한다. 여기에서 extends를 써야 하는데 이렇게 한 인터페이스 다른 인터페이스를 구현할 수는 없지만 확장하는 것은 가능하다. public interface MyRemote extends Remote {} MyRemote.java 인터페이스가 원격 메소드 호출을 위한 것이라고 선언해야 한다. public interface MyRemoteextends Remote { Head First JAVA

  11. 원격 인터페이스 생성 (2/3) 모든 메소드에서RemoteException을 던진다는 것을 선언한다. 원격 인터페이스는 클라이언트에서 서비스를 위한 다형적인 유형으로 사용하기 위한 것이다. 클라이언트에서 그 원격 인터페이스를 구현하는 객체(스터브 객체)에 대한 메소드를 호출하는데 스터브 객체에서는 네트워킹과 입출력을 처리하기 때문에 안 좋은 일이 일어날 수 있기 때문에 클라이언트에서는 원격 예외를 처리하거나 선언해야 한다. import java.rmi.*; // Remote 인터페이스는 java.rmi에 들어있다. public interface MyRemote extends Remote { public String sayHello() throws RemoteException; } 원격 메소드 호출은 모두 위험한 것으로 간주됨 Head First JAVA

  12. 원격 인터페이스 생성 (3/3) 인자나 리턴값이 원시유형 또는 Serializable유형인지 확인한다. 원격 메소드에 대한 인자(리턴값도 마찬가지)는 포장해서 네트워크를 통해 전달해야 하는데 그 과정에서 직렬화가 필요하다. 원시유형, String을 비롯한 API에 들어있는 대부분의 유형은 별 문제없이 쓸수 있지만 직접 만든 유형을 사용할 때는 그 클래스를 만들 때 Serializable인터페이스를 구현했는지 꼭 확인해봐야 한다. public StringsayHello() throws RemoteException; Head First JAVA

  13. 원격 인터페이스 구현 클래스 생성 (1/4) 원격 인터페이스를 구현한다. 서비스에서는 클라이언트에서 호출할 메소드가 있는 원격 인터페이스를 구현해야 한다. public interface MyRemote extends Remote {} MyRemoteImpl.java public class MyRemoteImpl extends UnicastRemoteOnjectimplements MyRemote { public String sayHello() { return “Server says, ‘Hey’”; } // 또 다른 코드 } 컴파일러에서 아까 구현한 인터페이스에 들어있는 모든 메소드를 구현했는지 확인해줌 Head First JAVA

  14. 원격 인터페이스 구현 클래스 생성 (2/4) UnicastRemoteObject를 확장한다. 원격 서비스 객체 역할을 하려면 ‘원격으로 돌아가는 것과 관련된 기능’이 들어있어야 하는데 UnicastRemoteObject(java.rmi.server패키지에 들어있음)를 확장하고 그 클래스에서 필요한 작업을 처리하게 하는 것이 가장 간단한 방법이다. public class MyRemoteImplextends UnicastRemoteOnject implements MyRemote { Head First JAVA

  15. 원격 인터페이스 구현 클래스 생성 (3/4) RemoteException을 선언하는 아무 인자도 없는 생성자를 만든다. 이 클래스의 상위클래스인 UnicastRemote의 한 가지 문제점은 RemoteException을 던진다는 것인데 이런 문제를 해결할 수 있는 유일한 방법은 원격 인터페이스를 구현한 클래스의 생성자도 RemoteException을 던지는 것으로 선언하는 것이다. 상위클래스 생성자에서 예외를 던지면 별 수 없이 그 클래스의 생성자에서도 예외를 던지는 것으로 선언해야 한다. public MyRemoteImpl() throws RemoteException { } 이 클래스의 생성자에서도 예외를 던질 수 있음을 선언하기 위한 코드이므로 아무 내용을 집어넣지 않아도 된다. Head First JAVA

  16. 원격 인터페이스 구현 클래스 생성 (4/4) 서비스를 RMI 레지스트리에 등록한다. 이제 원격 서비스가 만들어졌으므로 원격 클라이언트에서 그 서비스를 사용할 수 있게 클래스의 인스턴스를 만들고 RMI레지스트리에 집어넣는다. 원격 인터페이스를 구현한 클래스를 등록하면 클라이언트에서 써야하므로RMI 시스템에서는 서비스를 스터브로 대체하고 그 스터브를레지스트리에 집어넣는다. 서비스를 등록할 때는 java.rmi.Naming클래스에 있는 정적 메소드인rebind() 메소드를 이용하면 된다. try { MyRemote service = new MyRemoteImpl(); Naming.rebind(“Remote Hello”, service); } catch (Exception ex) { … } 서비스에 클라이언트의 레지스트리에서 이 서비스를 찾을 때 사용하는 이름을 붙여주고 RMI 레지스트리에 등록한다. Head First JAVA

  17. 스터브와스켈레톤 생성 101101 10 110 10 11 0001 1000 01 101101 10 110 10 11 0001 1000 01 원격 인터페이스를 구현한 클래스에 대해 rmic를 실행한다. 자바 SDK에 들어있는 rmic도구는 서비스 인터페이스를 구현한 클래스를 받아서 스터브와스켈레톤을 생성해준다. 이름을 정할 때는 dnjsrur인터페이스를구현한 클래스명 뒤에 _Stub와 _Skel을 각각 추가한다. 이렇게 만들어진 클래스는 현재 디렉토리에 저장되고 rmic에서 인터페이스를 구현한 클래스를 볼 수 있어야 하므로 그 클래스가 들어있는 디렉토리에서 rmic를 실행할 가능성이 높다. MyServiceImpl_Stub.class MyRemoteImpl_Skel.class Head First JAVA

  18. rmiregisty실행 및 서비스 시작 터미널을 열고 rmiregistry를 시작한다. 반드시 클래스에 접근할 수 있는 디렉토리에서 실행시켜야 하는데 가장 간단한 방법은 classex디렉토리에서 실행시키는 것이다. 다른 터미널을 열고 서비스를 시작한다. 원격 인터페이스를 구현한 클래스의 main() 메소드에서 시작할 수도 있고 다른 구동용 클래스에서 시작할 수도 있을 것이다. Head First JAVA

  19. 서버용 코드 (1/2) RemoteException과 Remote 인터페이스가 java.rmi 패키지에 들어 있다. 원격 인터페이스 import java.rmi*; public interface MyRemote extends Remote { public String sayHello() throws RemoteException; } 인터페이스가 반드시 java.rmi.Remote를 확장해야 한다. 모든원격 메소드에서RemoteException을 선언해야만 한다. Head First JAVA

  20. 서버용 코드 (2/2) 원격 서비스(인터페이스를 구현한 클래스) import java.rmi*; importjava.rmi.server.*; public classMyRemoteImplextendsUnicastRemoteObjectimplementsMyRemote { public String sayHello() { return“Server says, ‘Hey’”; } // 모든 인터페이스 메소드를 구현 publicMyRemoteImpl() throwsRemoteException { } public static void main (String[] args) { try { Myremote service = new MyRemoteImpl(); Naming.rebind(“Remote Hello”, service); } catch (Exception ex) { ex.printStackTrace(); } } } UnicastRemoteObjet가 java.rmi.server패키지에 들어있음. 원격 인터페이스를 구현해야 한다. 상위클래스 생성자에서 예외를 선언하기 때문에 반드시 생성자를 만들어야 함. 원격 객체를 만들고 Naming.rebind() 정적메소드를 써서 RMI 레지스트리에 결합시킨다. Head First JAVA

  21. 스터브를받는 방법 클라이언트에서 메소드를 호출할 때 스터브 객체에 대해 메소드를 호출하기 때문에 반드시 스터브 객체를 받아야 한다. 클라이언트 힙 서버 힙 3 스터브 스터브 클라이언트 객체 스켈레톤 서비스 객체 2 클라이언트에서 RMI 레지스트리에 대한 룩업 작업을 한다. RMI 레지스트리에서스터브 객체를 리턴한다. 클라이언트에서 실제 서비스에 있는 메소드를 호출하는 것과 같은 방법으로 스터브에 있는 메소드를 호출한다. Remote Hello 1 RMI 레지스트리 (서버에 있음) Head First JAVA

  22. 클라이언트 코드 import java.rmi*; public classMyRemoteClient { public static void main(String [] args) { newMyRemoteClient().go(); } public void go() { try { MyRemote service = (MyRemote) Naming.lookup(“rmi://127.0.0.1/Remote Hello”); String s = service.sayHello(); System.out.println(s); } catch (Exception ex) { ex.printStackTrace(); } } } Naming 클래스가 들어있음 Lookup() 메소드는Object 유형을 리턴하기 때문에 인터페이스 유형으로 캐스트해야 함 클라이언트에서는 항상 원격 인터페이스를 서비스 유형으로 사용 lookup()은 Naming 클래스의 정적메소드 호스트명 또는 IP주소와 서비스를 등록할 때 지정한 이름을 쓴다. Head First JAVA

More Related