주요글: 도커 시작하기
반응형
Akka는 액터에 메시지를 전달하고 응답을 받을 때 자바 인터페이스를 사용할 수 있는 기능을 제공하고 있다. 즉, ActorRef의 sendOneWay()나 sendRequestReply()와 같은 메서드가 아닌 자바 인터페이스에 정의된 메서드를 이용해서 액터에 메시지를 전달하고 응답을 받을 수 있도록 하고 있다. 본 글에서는 Akka가 제공하는 TypedActor를 이용해서 자바 인터페이스를 액터와의 통신 인터페이스로 사용하는 방법을 설명한다.

TypedActor를 이용한 자바 인터페이스 기반 액터 생성

TypedActor 클래스를 사용하면 인터페이스를 구현한 자바 클래스를 액터로 사용할 수 있다. TypedActor를 사용하려면 다음과 같이 인터페이스와 그 인터페이스를 구현한 클래스를 필요로 한다. 이때 인터페이스를 구현한 클래스는 TypedActor 클래스를 상속 받아야 한다.

public interface DataMigrator {
    public void run();
    public int restCount();
}

public class DataMigratorImpl extends TypedActor implements DataMigrator {

    private int count = 0;

    @Override
    public void run() {
        System.out.println("DataMigratorImpl: 작업 시작");
        // 뭔가 작업을 비동기로 처리
    }

    @Override
    public int restCount() {
        return 100 - count;
    }
}

액터와 통신할 때 사용할 인터페이스를 구현하고 TypedActor를 상속받은 클래스를 구현했다면, 다음의 코드를 이용해서 액터를 생성하고 사용할 수 있다.

DataMigrator migrator =
            TypedActor.newInstance(DataMigrator.class, DataMigratorImpl.class);

// migrator는 액터와 통신을 위한 프록시
migrator.run();
int rest = migrator.restCount();
do {
    Thread.sleep(10);
    rest = migrator.restCount();
} while(rest > 0);

TypedActor.stop(migrator); // TypedActor 종료
// Actors.registry().shutdownAll(); 코드도 TypedActor 종료

TypedActor.newInstance()의 첫 번째 파라미터는 액터와 통신할 때 사용할 인터페이스 타입을 지정하며, 두 번째 파라미터는 실제 TypedActor로 사용될 클래스를 지정한다. TypedActor.newInstance() 메서드가 생성한 객체는 액터와 통신을 수행해주는 프록시 객체가 된다. 위 코드에서는 migrator가 프록시 객체가 되는데, 이 프록시 객체의 메서드를 호출하면, 내부적으로 TypedActor 객체에 메시지를 전송하게 되고 TypedActor 객체는 일치하는 메서드를 호출하게 된다.

[참고]
Akka는 TypedActor에 대한 프록시를 객체를 생성하기 위해 AspectWerkz(http://aspectwerkz.codehaus.org/ 참고)를 사용한다.


Fire-And-Forget

메서드의 리턴 타입이 void 이면, 해당 메서드에 대한 메시지는 sendOneWay()와 동일하게 Fire-And-Forget 방식으로 전송된다. 따라서, 메서드를 호출하면 액터가 메시지를 처리 여부에 상관없이 즉시 리턴한다. DataMigrator 인터페이스의 run() 메서드가 이에 해당한다.

DataMigrator migrator = TypedActor.newInstance(DataMigrator.class, DataMigratorImpl.class);
migrator.run(); // 리턴 타입이 void 이므로 Fire-And-Forget 방식


Send-And-Receive-Eventually

메서드가 리턴 타입을 가지면, sendRequestReply()와 동일하게 Send-And-Receive-Eventually 방식으로 메시지가 전송된다. 따라서, 액터로부터 응답이 도착할 때 까지 블럭킹 된다.

DataMigrator migrator = TypedActor.newInstance(DataMigrator.class, DataMigratorImpl.class);
int rest = migrator.restCount(); // Send-and-receive-Eventually 방식

Send-And-Receive-Future

메서드의 리턴 타입이 akka.dispatch.Future이면, Send-And-Receive-Future 방식으로 메서드를 호출한다.

리모트 TypedActor 생성하기

UntypedActor와 마찬가지로 TypedActor도 간단하게 리모트 액터로 제공할 수 있다.

리모트 서버에서 TypedActor 생성하기

리모트 서버에서, 액터를 리모트 액터로 등록하려면 registerTypedActor()를 사용하면 된다.

Actors.remote().start("0.0.0.0", 2553);
DataMigrator migrator = TypedActor.newInstance(DataMigrator.class, DataMigratorImpl.class);
Actors.remote().registerTypedActor("data-migrator", migrator);

클라이언트 코드에서는 Actors.remote().typedActorFor() 메서드를 이용해서 리모트 액터에 대한 프록시 객체를 구한 뒤 알맞은 메서드를 호출하면 된다.

DataMigrator migrator = Actors.remote()
        .typedActorFor(DataMigrator.class, "data-migrator", "172.20.1.2", 2553);

migrator.run();
int rest = migrator.restCount();
do {
    Thread.sleep(1000);
    rest = migrator.restCount();
} while(rest > 0);

Actors.remote().shutdown();

[주의]
클라이언트에서 리모트 액터를 생성할 수도 있으나, 현재 버전에서는 기능이 예상하는 대로 동작하지 않아 본 글에서는 소개하지 않는다.

참고자료
  • http://doc.akka.io/typed-actors-java

+ Recent posts