2013년 4월 18일 목요일

Apache Avro IDL protocol 을 비동기 방식으로 통신하기

연속해서 Avro 에 대해 글을 쓰게 되네요. 이번 프로젝트에 Avro를 사용할 것이고, 팀원들이 쉽게 쓰게 하기 위해서 이 글을 씁니다. ㅋ

Netty 덕분에 Avro 의 통신이 믿을만하고, 속도도 빠르다고 확신합니다만, 개발자 분들도 비동기 방식을 사용하여 더 효과적인 통신이 되도록 하면 좋을 것입니다.

CalculatorServer.java ( 이전 글의 예제를 비동기 방식도 가능하도록 수정)

package example.avro.rpc;
import lombok.extern.slf4j.Slf4j;
import org.apache.avro.AvroRemoteException;
import org.apache.avro.ipc.*;
import org.apache.avro.ipc.specific.SpecificRequestor;
import org.apache.avro.ipc.specific.SpecificResponder;
import java.io.IOException;
import java.net.InetSocketAddress;
/**
* Avro Async Callback 을 활용한 RPC 통신
*
* @author sunghyouk.bae@gmail.com
* @since 13. 4. 17. 오후 9:16
*/
@Slf4j
public class CalculatorServer {
public static class CalculatorImpl implements Calculator {
@Override
public double add(double x, double y) throws AvroRemoteException {
return x + y;
}
@Override
public double subtract(double x, double y) throws AvroRemoteException {
return x - y;
}
}
private static Server calcServer;
private static final int CALC_SERVER_PORT = 65123;
private static void startServer() throws IOException {
calcServer = new NettyServer(new SpecificResponder(Calculator.class, new CalculatorImpl()),
new InetSocketAddress(CALC_SERVER_PORT));
}
public static void main(String[] args) throws Exception {
System.out.println("Starting server...");
startServer();
System.out.println("Server started");
NettyTransceiver calcClient = new NettyTransceiver(new InetSocketAddress(CALC_SERVER_PORT));
Calculator.Callback proxy = (Calculator.Callback) SpecificRequestor.getClient(Calculator.Callback.class, calcClient);
System.out.println("Client built, get proxy");
proxy.add(2, 3, new Callback<Double>() {
@Override
public void handleResult(Double result) {
System.out.println("Callback... add(2, 3)=" + result);
}
@Override
public void handleError(Throwable error) {
System.out.println("예외가 발생했습니다. error=" + error.getMessage());
}
});
CallFuture<Double> asyncResult = new CallFuture<Double>();
proxy.add(2, 3, asyncResult);
Thread.sleep(10);
if (asyncResult.isDone())
System.out.println("CallFuture... add(2,3)=" + asyncResult.get());
System.out.println("add(2, 3)=" + proxy.add(2, 3));
System.out.println("subtract(5, 1)=" + proxy.subtract(5, 1));
calcClient.close();
calcServer.close();
}
}
입니다. 이전 코드에서 변경된 부분은 다음과 같습니다.

변경된 부분만!!!

NettyTransceiver calcClient = new NettyTransceiver(new InetSocketAddress(CALC_SERVER_PORT));
Calculator.Callback proxy = (Calculator.Callback) SpecificRequestor.getClient(Calculator.Callback.class, calcClient);
System.out.println("Client built, get proxy");
proxy.add(2, 3, new Callback<Double>() {
@Override
public void handleResult(Double result) {
System.out.println("Callback... add(2, 3)=" + result);
}
@Override
public void handleError(Throwable error) {
System.out.println("예외가 발생했습니다. error=" + error.getMessage());
}
});
CallFuture<Double> asyncResult = new CallFuture<Double>();
proxy.add(2, 3, asyncResult);
Thread.sleep(10);
if (asyncResult.isDone())
System.out.println("CallFuture... add(2,3)=" + asyncResult.get());

비동기 방식 통신을 위해서는 Client 를 얻을 때 Calculator.class 를 쓰지 않고, Calculator.Callback.class 를 사용합니다.  이 interface 는 이미 Avro에 의해 생성된 코드입니다.

이를 바탕으로 Callback을 직접 정의해도 되고,  CallFuture 를 사용해도 됩니다. 

댓글 없음: