티스토리 뷰

728x90
반응형
728x170

 포스팅은 RMI 기본 구성 및 작성 가이드입니다.


1. RMI

1.1 구조

Stub/Skeleton 계층

Proxy와 같은 역할을 하며, 데이터를 바이트 스트림으로 변환하는 마샬링과 언마샬링을 한다

 

Stub

원격 객체가 있는 원격지의 가상 머신과 연결, 매개 변수를 원격 가상 머신에게 마샬링, 메소드를 호출한 결과를 기다리고 그 결과로 얻어진 반환 값을 언마샬링, 변환 값을 클라이언트에게 전달한다.

 

Skeleton(JDK1.3이후Tie)

원격 객체의 메소드의 매개 변수들을 언마샬링, 원격 메소드가 구현된 실제 클래스를 호출하고 그 결과를 호출자에게 마샬링한다.

 

Remote Reference 계층

RMI 커넥션에서 호출과 연결에 관련된 작업을 처리한다.

 

Transport 계층

OSI 7계층의 TCP/IP에 대응되는 계층으로, 가상 머신 간에 스트림 기반의 네트워크 커넥션을 생성하고 설정하고 관리하는 역할을 한다.

 

RMI Call 순서

원격 객체의 메소드를 호출하는 클라이언트 -> Stub -> Remote Reference -> TCP -> IP -> 네트워크 인터페이스 -> IP -> TCP -> Remote Reference -> Skeleton -> 서버의 원격 객체

 

1.2 원격 객체의 위치 검색

위치 검색 방법 (API 소개)

클라이언트는 RMI 서버의 호스트명과 포트 번호를 가지고, 네이밍 서비스 디렉토리 서비스에 접속한다.

RMI에서는 원격 객체를 저장하기 위한 네이밍 서비스로 RMI 레지스트리를 사용한다.

rmi 호스트 위치 설정 : rmi://<host_name>[:name_service_port]/<service_name>

 

만약에 RMI 프로토콜에서 로컬 호스트로 rmi 호스트를 포트 번호로 기본 포트인 1099번을 그냥 사용한다면, URL을 다음과 같이 사용해도 된다

/<service_name>

 

1.3 RMI 전송 방식

네트웍에서의 전송 방법

Peer to Peer : 일반적인 데이터를 주고 받는 방법은 서버와 클라이언트 환경이 있다. 일반적으로 웹이나 ftp 또는 웹하드 같은 특정서버가 있어서 해당 서버에 연결을 하여 데이터를 주고 받는 것을 말한다. 하지만 peer to peer 의 경우 특정한 서버가 있는 것이 아닌 동등한 입장의 클라이언트와 클라이언트가 서로 데이터를 주고 받는 것을 의미한다. (다대다의 연결)

point to point : 일대일의 연결. 네이트온과 같이 일대일로 파일을 전달 받는 것을 의미한다. (일대일의 연결)

 

rmi에서는 UnicastRemoteObject 클래스를 이용하여 TCP 스트림을 기반으로 point-to-point 방식으로 서버와 통신하는 방법을 제공한다.

 

1.4 RMI 작성 가이드 및 구동 방법

RMI 레지스트리를 이용하여 애플리케이션을 개발하려면 다음과 같은 단계를 밟는다.

 

1. 원격 인터페이스 작성하기

import java.rmi.Remote;

import java.rmi.RemoteException;

 

public interface LoggingTime extends Remote {

        public String log(String name) throws RemoteException;

}

원격 인터페이스는 공통 인터페이스라고도 하며, 서버가 클라이언트에게 서비스하는 메소드를 정의하는 인터페이스이다. 클라이언트는 서버가 제공하는 메소드에 대한 실제 구현 내용을 알 필요 없이, 메소드의 이름과 매개 변수, 반환 값에 대한 정보만을 가지고 메소드를 호출한다.

 

(작성 규칙)

a. 원격 인터페이스는 반드시 public으로 선언한다.

b. 원격 인터페이스는 반드시 java.rmi.Remote 인터페이스를 상속받는다. Remote 인터페이스에는 특별한 메소드가 존재하지 않는다. 다만, 작성하는 인터페이스가 원격 인터페이스임을 알려주기 위한 용도이다.

c. 각각의 메소드는 반드시 java.rmi.RemoteException 처리를 해야 한다.

d. 원격 메소드가 매개 변수나 반환 값으로 원격 객체를 가지고 있으며, 원격 객체는 반드시 구현 클래스의 타입이 아닌 인터페이스 타입이어햐 한다.

e. 원격 메소드의 매개 변수나 반환 값으로 사용하는 데이터는 자료형이 기본 자료형이거나 직렬화된 타입이어야 한다.

 

2. 원격 인터페이스 구현 클래스 작성하기

import java.io.*;

import java.rmi.*;

import java.rmi.server.*;                                                               //remote interface api

import java.util.Date;

 

public class LoggingTimeImpl extends UnicastRemoteObject implements LoggingTime {       //remote interface extends UnicastRemoteObject implements LoggingTime

        public LoggingTimeImpl() throws RemoteException {}

 

        public String log(String name) throws RemoteException {                         //remote interface implements method

                return "Hello" + name + "this is:" + new Date() + "now";

        }

}

원격 인터페이스를 구현하는 클래스는 원격 인터페이스에 정의된 메소드를 실제로 구현하는 클래스이며, 원격 객체로 사용할 수 있도록

java.rmi.server.RemoteServer 클래스를 상속받아야 한다.

java.rmi.server.RemoteServer의 최상위(super) 클래스인

java.rmi.server.RemoteObject java.lang.Object equals(), hashcode(), toString() 메소드를 RMI 서비스에 맞게 재정의(overriding)하고 있다. RemoteServer에는 원격 서버 구현에 필요한 내용이 있으며, 원격 객체로서의 역할을 하게 된다.

 

(작성 규칙)

a. public 클래스로 선언하고 UnicastRemoteObject Activatable 클래스를 상속받는다.

b. 원격 인터페이스를 구현해야 한다.

c. RemoteException을 처리하는 디폴트 생성자(Default Construct)를 가져야 한다.

 

3. 원격 객체를 등록하는 서버 프로그램 구현하기

import java.rmi.*;

 

public class LoggingTimeServer {

        public static void main(String[] args) {

                try {

                        LoggingTimeImpl impl = new LoggingTimeImpl();                           //making Objectinterface

                        Naming.rebind("/log", impl);

                        System.out.println("LoggingTimeServer bind for registry");

                } catch (Exception ex) {

                    ex.printStackTrace();

                }

        }

}

위에서 생성된 원격 구현 클래스의 인스턴스인 원격 객체를 네이밍 서비스에 등록하는 클래스를 작성하도록 한다. 먼저 원격 객체의 인스턴스를 생성한 다음, Naming 클래스의 bind() 또는 rebind() 메소드를 사용하여 등록한다.

 

4. 원격 객체를 이용하는 클라이언트 프로그램 구현하기

import java.rmi.*;

 

public class LoggingTimeClient {

        public static void main (String[] args) {

                try {

                        LoggingTime logTime = (LoggingTime)Naming.lookup("/log");

                        String message = logTime.log("nrson");

                        System.out.println(message);

                } catch (Exception ex) {

                  ex.printStackTrace();

                }

        }

}

클라이언트는 RMI 호스트의 RMI 레지스트리에서 원격 객체를 검색한 후에, 그 결과로 원격 객체에 대한 레퍼런스를 얻는다. 원격 객체에 대한 레퍼런스는 java.rmi.Remote 타입이기 때문에, 이를 원격 서버가 서비스하는 원격 인터페이스로 캐스팅을 해야만 원격 객체의 메소드를 사용할 수 있다. Naming 클래스의 lookup() 메소드를 사용하여 네이밍 서비스에 등록된 원격 객체를 검색하고 원격 객체의 레퍼런스 값을 반환받는다.

 

5. RMI 예제를 컴파일하고 실행하기

a. 먼저 앞에서 작성한 파일을 컴파일 한다.

(컴파일 )

[narason@infrasvr rmi_test]$ ls -la

합계 24

drwxrwxr-x  2 narason pinfra 4096 4 11 17:59 .

drwx------ 23 narason pinfra 4096 4 11 17:39 ..

-rw-rw-r--  1 narason pinfra  162 4 10 17:26 LoggingTime.java

-rw-rw-r--  1 narason pinfra  434 4 10 17:32 LoggingTimeClient.java

-rw-rw-r--  1 narason pinfra  600 4 10 17:23 LoggingTimeImpl.java

-rw-rw-r--  1 narason pinfra  494 4 10 17:32 LoggingTimeServer.java

[narason@infrasvr rmi_test]$

 

(컴파일 )

[narason@infrasvr rmi_test]$ javac *.java

[narason@infrasvr rmi_test]$ ls -la

합계 40

drwxrwxr-x  2 narason pinfra 4096 4 11 17:59 .

drwx------ 23 narason pinfra 4096 4 11 17:39 ..

-rw-rw-r--  1 narason pinfra  234 4 11 17:59 LoggingTime.class

-rw-rw-r--  1 narason pinfra  162 4 10 17:26 LoggingTime.java

-rw-rw-r--  1 narason pinfra  703 4 11 17:59 LoggingTimeClient.class

-rw-rw-r--  1 narason pinfra  434 4 10 17:32 LoggingTimeClient.java

-rw-rw-r--  1 narason pinfra  692 4 11 17:59 LoggingTimeImpl.class

-rw-rw-r--  1 narason pinfra  600 4 10 17:23 LoggingTimeImpl.java

-rw-rw-r--  1 narason pinfra  683 4 11 17:59 LoggingTimeServer.class

-rw-rw-r--  1 narason pinfra  494 4 10 17:32 LoggingTimeServer.java

[narason@infrasvr rmi_test]$

 

b. 클라이언트와 서버의 프록시 역할을 하는 Stub Skeleton을 생성하기 위해 RMI 컴파일을 하도록 한다.

(rmic 명령어를 이용하여 생성 ex - rmic -v1.1 LoggingTimeImpl)

[narason@infrasvr rmi_test]$ rmic -v1.1 LoggingTimeImpl

[narason@infrasvr rmi_test]$ ls -la

합계 48

drwxrwxr-x  2 narason pinfra 4096 4 11 18:00 .

drwx------ 23 narason pinfra 4096 4 11 17:39 ..

-rw-rw-r--  1 narason pinfra  234 4 11 17:59 LoggingTime.class

-rw-rw-r--  1 narason pinfra  162 4 10 17:26 LoggingTime.java

-rw-rw-r--  1 narason pinfra  703 4 11 17:59 LoggingTimeClient.class

-rw-rw-r--  1 narason pinfra  434 4 10 17:32 LoggingTimeClient.java

-rw-rw-r--  1 narason pinfra  692 4 11 17:59 LoggingTimeImpl.class

-rw-rw-r--  1 narason pinfra  600 4 10 17:23 LoggingTimeImpl.java

-rw-rw-r--  1 narason pinfra 1688 4 11 18:00 LoggingTimeImpl_Skel.class

-rw-rw-r--  1 narason pinfra 1871 4 11 18:00 LoggingTimeImpl_Stub.class

-rw-rw-r--  1 narason pinfra  683 4 11 17:59 LoggingTimeServer.class

-rw-rw-r--  1 narason pinfra  494 4 10 17:32 LoggingTimeServer.java

[narason@infrasvr rmi_test]$

 

c. Stub, Skeleton 생성 여부확인 이후 RMI 레지스트리를 작동하고 서버 프로그램을 실행한다.

(rmiregistry 구동 1099 해당 포트)

- [narason@infrasvr rmi_test]$ rmiregistry 1099

 

(rmi server 구동)

- [narason@infrasvr rmi_test]$ java LoggingTimeServer

LoggingTimeServer bind for registry

 

(rmi client 호출 결과)

-[narason@infrasvr rmi_test]$ java LoggingTimeClient

Hellonrsonthis is:Thu Oct 11 18:03:51 KST 2012now

[narason@infrasvr rmi_test]$

 

고맙습니다.

728x90
반응형
그리드형

'③ 미들웨어 > ⓙ JEUS' 카테고리의 다른 글

[JEUS7] 이중화 테스트 가이드  (0) 2018.08.04
[JEUS6] XML 사용 가이드  (0) 2018.08.02
[JEUS7] 운영자 모니터링  (0) 2018.07.31
[JEUS6] JMX Guide  (0) 2018.07.23
[JEUS7] 운영자 모니터링  (0) 2018.07.20