2013년 4월 18일 목요일

Apache Avro IDL 을 이용한 RPC 구현

어제는 JSON 포맷의 Avro Protocol 파일을 정의하여, RPC 를 구현해 봤습니만 (Avro Protocol 방식),
오늘은 IDL을 이용하여 구현해 보도록 하겠습니다. IDL 이 json 포맷보다 훨씬 가독성이 좋아서, 저는 앞으로는 IDL로 구현해야겠네요.

오늘은 어제보다 좀 더 복잡한 코드를 만들어 보겠습니다. Avro IDL 관련 설명을 읽고 10분만에 구현했으니, 이 글을 보시는 분들도 단박에 이해 되실겁니다.

구현한 예제는 검색 서비스를 흉내낸 것인데,  데이터의 저장, 검색 함수를 지원합니다.

searchService.avdl (Avro IDL 포맷의 확장자는 avdl 입니다)


SearchService 에는 Entity, SearchResult 라는 자료구조 (java에서는 class) 를 정의하고, 아래에는 rpc 메소드들을 정의했습니다.
JSON 포맷보다 훨씬 보기 좋죠?

이전 글에 설명되었듯이 idl-protocol 에 대해 source-generation 을 수행하고, 아래 코드를 작성하면, Search Service 를 제작할 수 있습니다.

SearchServer.java

Client, Server 구현은 이전글의 예제와 거의 유사합니다.
아주 초간단하게 작성했지만 될 건 다 됩니다^^

이제 Avro 의 좀 더 깊은 영역을 살펴봐야겠습니다.

2013년 4월 17일 수요일

apache avro 의 rpc 예제 by java

검색 서비스 제작 중에 외부 서비스를 위한 RESTful 말고, 내부적으로 사용할 고속의 통신 방식을 제공하는 방법을 찾아봤습니다. 일차적으로 유명한 Apache Thrift 를 사용하려다가, Avro 가 맘에 들어, 공부 삼아 예제를 테스트 해 봤습니다.

흠 뭐랄까? 개발하는 입장에서는 Thrift 라 크게 다를 게 없는데... 규격을 정의하는 코드는 차라리 Thrift 가 눈에 더 익어 보이네요^^
다만, Avro 측에서 주장하는 Dynamic 함과 Schema 를 가지고 있다는 것이 향후 확장이라던가, 유연성 측면에서 좋을 것 같더군요...

개인적으로 이거 저거 상세하게 따지지 않고, 맘에 가는 걸 선택합니다... 
향후에 둘 다 지원하면 되니까요^^ 

어쨌든 오늘은 avro 의 serialize/deserialize 예제 말고, 서버와의 통신 (RPC) 예제를 만들어 볼까합니다. (제가 서비스에 사용하기 위해 미리 연습삼아 제작한 것입니다)

예제는 클라이언트가 서버에게 계산을 요청하면, 값을 계산해서 반환하는 계산 서비스를 구현할 것입니다.

우선 준비 사항으로 avro 라이브러리가 필요합니다.

1. maven dependency 에 아래의 avro 관련 라이브러리를 추가합니다.

        avro 1.7.4 와 avro-ipc 1.7.4 를 사용했습니다.   

최신 버전이 1.7.4 더군요. avro-ipc 가 client/server 통신을 하기 위한 라이브러리 입니다.
내부적으로 Netty 를 사용하네요. Netty를 사용한다는 것은 속도면에서 보증받는 거라 보시면 됩니다. ㅋ

2. 다음으로 avro 파일을 java 코드로 생성해주는 avro-maven-plugin 을 정의해 줍니다.




avro-maven-plugin 버전도 1.7.4 더군요^^ 위의 sourceDirectory, outputDirectory 를 보시면, 표준 maven directory로 설정했습니다. 이부분은 각자 변경하시면 됩니다. 
avro 파일들을 찾아 java 클래스로 생성하여 outputDirectory 밑에 생성합니다.

자 이제 본격적으로 Calculator 를 제작해 봅시다.

calculator 를 먼저 정의합니다. avro 파일은 *.avro 가 표준입니다. 
하지만 protocol 인 경우는 *.avpr 을 써야 합니다.

3. calculator.avpr

{
    "namespace": "example.avro.rpc",
    "protocol": "Calculator",

    "types": [],

    "messages": {
        "add": {
                "request":[ { "name": "x", "type": "double"},
                            { "name": "y", "type": "double"} ],
                "response":"double"
            },

          "subtract": {
                "request":[ { "name": "x", "type": "double"},
                            { "name": "y", "type": "double"} ],
                "response":"double"
          }
    }
}

우선 namespace  를 정의하고, protocol 을 정의합니다. 이를 통해 rpc 통신을 한다는 것을 지정했습니다. types 는 사용자 정의 수형을 정의하는 영역입니다. 계산 서비스에서는 double 형만 쓰기 때문에 작업할 것이 없습니다.
다음으로 add, subtract 메소드를 정의했습니다. 
request 는 input parameter 이고, response 는 output parameter 입니다. output parameter 는 이름이 필요 없기 때문에 형식이 생략되었습니다.

이제 maven 에서 generate-sources 를 통해 java 코드를 생성합니다.

4. 생성된 Calculator.java




소스를 보시면 원하는대로 add, subtract 메소드가 정의되었음을 확인할 수 있습니다.
다음으로 실제 서버에서 서비스를 하고, client 에서 호출하여 결과를 볼 수 있는 예제를 제작해 봅시다.

5. CalculatorServer.java





아주 쉽죠^^

저도 처음에 avro가 rpc 를 위해 자체적인 서버가 없는 줄 알았습니다. netty 를 사용한다는 것을 알고는 thrift 보다 avro가 우선순위에 올라오게 되었지요^^

앞으로 내부 서버간의 통신 등에는 avro 를 적극적으로 활용해야겠습니다.

2013년 4월 7일 일요일

hibernate-redis 제작 (hibernate4 2nd cache using Redis) - part 1


hibernate-redis 제작 - part 1
hibernate-redis 제작 - part 2


작년부터 만들어보겠다고 맘만 먹고 있던 hibernate 4 2nd cache using Redis 를 제작해봤습니다.
hibernate 4, spring-data-redis 1.0.3, jedis 2.1 을 이용하여 작업했습니다.

Repository : https://github.com/debop/hibernate-redis

현재까지 테스트 시에는 제대로 작동하고, 성능 또한 만족스럽습니다.

한가지 마음에 걸리는 것은 spring-data-redis 의 RedisTemplate 를 사용하므로서, Spring 라이브러리에 의존하게 된다는 것이네요.

앞으로는 jedis 만 사용하도록 Upgrade 할 예정입니다.

흠... 그리고 검토한 것 중에 캐시 데이터 저장 시 압축을 지원하려고 했는데, Redis 는 기본적으로 제공한다고 하니, 굳이 할 필요가 없겠더라구요...
혹시 나중에 필요하면 옵션으로 넣어볼까 합니다.

NHibernate 2.x 에서는 2nd Cache Provider 제작이 엄청 쉬웠는데 ㅎㅎ...
hibernate 4 는 처음에는 분석하는데 좀 힘들었습니다...
hibernate-ehcache 소스를 보고 분석해보니 별거 아니더군요 ㅋ...