2012년 9월 28일 금요일

erlang web server experience


결과적으로 일반적인 웹 작성(text/html)에는 mochiweb을 쓰고,
json/application을 위해서는 cowboy를 쓰고 있다.

webmachine을 처음에 쓰다가, 성능 테스트 후 실망하고, mochiweb의 예전 버젼에 dependency가 있음으로 인해서, 버그가 수정안 된 것을 알고, cowboy로 급히 전환했었다.
cowboy는 binary기반으로 mochiweb은 list기반으로 처리하기 때문에, 많은 코드를 수정해야 했다.

erlang web쪽의 발전이 가히 눈씻고 봐야 할 정도라고 봐야 한다.
아직, 뚜렷한 1인자는 없다.
mochiweb,cowboy가 경쟁할 듯 보이고, 다소 무거워 보이는 ChicagoBoss는 어찌 될지 모르겠다. 다른 웹 서버들도 생겨나고 있다...
아직은 erlang web 서버 시장의 1인자를 위해서 경쟁을 시작할 가치는 있어보인다.
아직 erlang을 잘 다루는 프로그래머가 별로 많지 않기 때문에,
철저한 테스트를 통한 경험을 기반으로 한 솔루션이 3년내에 나올 것이라 본다.

그런데, 앞으로, erlang을 기반으로 한 서버 솔루션이 대세가 될 것으로 내다본다.
왜냐하면, 실제로 해보면, php만큼 쉽다. 결코 어렵지 않다. 게다가 경험자가 손봐주면, 놀라울 정도의 성능과 확장성을 확보할 수 있기 때문이고, 이와 연동하는 DB들도 성숙할 것이기 때문이다.

haskell쪽도 기대를 내심 하고 있는데... haskell의 wai를 지켜봐야 한다.
haskell로 서버/클라이언트 모두 하나의 코드로 만들 수 있는 시대가 올 것으로 기대한다.




2012년 9월 3일 월요일

2i in riak leveldb

qrtest_driver_riakclient_leveldb.erl
다음과 같이 index를 줘서 put을 하고,

run(put2, KeyGen, ValueGen, State) ->
    DeviceQRBin = list_to_binary(get_random_string(2,"0123456789ABCDEF")),
    BucketBin = << <<"qr_log">>/binary , DeviceQRBin/binary >>,
    NowKey=term_to_binary(now()), %% for distionction

    ProviderID = random:uniform(10),
    ActionBin = list_to_binary(get_random_string(2,"ABCDEF")),
    ResultBin = list_to_binary(get_random_string(2,"123456")),

    T = util_time:epoch(), %% time in second
    It=#qr_log{ device_qr = DeviceQRBin , provider_id = ProviderID, action= ActionBin, result=ResultBin , time=T },

    MetaData = dict:store(<<"index">>, [ {"time_int", T}, {"action_bin", ActionBin} ], dict:new()),
    Robj = riak_object:new(BucketBin,NowKey, term_to_binary(It),MetaData),      

    case (State#state.client):put(Robj, State#state.replies) of
        ok ->
            io:format("."),
            {ok, State};
        {error, Reason} ->
            %%io:format("?~p~n",[Reason]),
            io:format("?"),
            {error, Reason, State};
        _ ->
            io:format("-")
    end;

다음과 같이 get을 하면 된다.






  
    qrtest_driver_riakclient_leveldb.erl
    
  
  
    
run(get_index1, KeyGen, _ValueGen, State) ->
    DeviceQRBin = list_to_binary(get_random_string(2,"0123456789ABCDEF")),
    BucketBin = << <<"qr_log">>/binary , DeviceQRBin/binary >>,
    ActionBin = list_to_binary(get_random_string(2,"ABCDEF")),
    Query = { eq , <<"action_bin">> , ActionBin  }, %%=> not to crash

    case (State#state.client):get_index(BucketBin, Query , 10000) of %% 10000 is timeout value
        {ok, R} ->
            io:format("!~p",[R]),
            {ok, State};
        {error, notfound} ->
            io:format("_"),
            {ok, State};
        {error, Reason} ->
            {error, Reason, State};
        {error, timeout , _ } ->
            io:format("T"),
            {ok, State};
        _ ->
            io:format("="),
            {ok, State}     
    end;

best way to install erlang and riak in macosx

maxosx에서 여러가지 시도를 해보았는데, 가장 쉽고 좋은 방법은,...

이전 erlang과 riak을 모두 지우고,

https://github.com/spawngrid/kerl
에서 다운받아 설치하고,

kerl로 설치하는 것.

$ kerl list releases


$ kerl build R15B01 r15b01


$ kerl install r15b01 /usr/local/erlang


riak install page에서 나오듯이 binary로 설치하는 것.

http://wiki.basho.com/Installing-on-Mac-OS-X.html


curl -O http://downloads.basho.com.s3-website-us-east-1.amazonaws.com/riak/CURRENT/osx/10.4/riak-1.2.0-osx-x86_64.tar.gz
tar xzvf riak-1.2.0-osx-x86_64.tar.gz


linux server 환경에서도 마찬가지이다.

2012년 9월 2일 일요일

riak performance in KT ucloud

debian squeeze 64bit
Riak 1.2.0
4Core 16GB
Bitcask backend default setting
basho_bench 10 concurrent workers, get:put:delete=1:1:1

일 때,

처리량은 4000~5000 tps 정도를 기록하고,
latency는 95%가 5ms 이하로 나온다.

만족스럽긴 하지만, cloud환경에서는 machine setting이 불가능 하니,
bitcask setting이나 os setting등을 통해서 향상이 가능할 듯 하다.
KT측과 disk 성능에 대해서 상의해 보아야 할 듯 하다.

riak_pb(protocol buffers) client를 사용하면 10~20% 성능 저하를 가져온다.
riak_raw_http client를 사용하면 50%  정도 성능 저하가 생긴다.

자세한 사항이 궁금하다면, 문의하세요~


2012년 8월 30일 목요일

upgrading riak 1.2.0 in centos

riak rolling upgrade 테스트를 위해서,
riak 1.1.4가 설치되어 있는 centos에서
riak 1.2.0 rpm으로 설치하고자 했는데...

다음과 같은 메시지가 떨어진다.



Loading ....

dependency 를 맞춰서 설치해줘야 하는데... 매우 귀찮아지는 듯...
ubuntu로 바꿔서 설치하는 것을 시도해 볼까 한다.


2012년 8월 28일 화요일

embed riak native client in erlang release

code:add_path를 통해서 riak_kv, riak_core ebin 디렉토리를 지정하고,
riak:client_connect를 하기 전에, 다음 코드를 실행해 놓도록 하면 된다.

Loading ....

2012년 8월 23일 목요일

rebar vs sinan


erlang project로 package를 만들어, release를 하고, deploy하고, 서비스를 하고, upgrade version을 running time에 live hot code swap을 하려면....

이 일련의 과정이 매우 쉽고 자연스럽게 된다면....

rebar와 sinan이 그 문제를 해결하려고 했는데...
여전히 쉽게 풀리지 않은 상태이다.
http://www.metabrew.com/article/erlangotp-releases-rebar-release_handler-appup-etc
이 블로그에서도 마지막에 위의 요구사항이 되었으면 하면서 끝맺음을 한다.

rebar를 쓰다가 sinan을 써보니, sinan은 release에는 잘 되어 있지만, dependency 관리가 어려운 편이다. rebar는 dependency관리는 잘 되는데, release 하기가 까다롭다.

숙련된 개발자는 물론 어찌되었든 잘 관리하고 있을텐데, 그 방법이 궁금하다.

일단 rebar를 잘 써보기로 했다. 보조 스크립트들을 잘 구성화면 요구사항을 만족할 수 있을 듯.

upgrade를 하는 기능이 새로 나왔었구나! 써보자!
https://github.com/basho/rebar/wiki/Upgrades
비디오 영상도 있다!
http://vimeo.com/8311407

--
rebar로 설치본을 만드는 것을 다시 해봤는데, 성공을 했지만, 매우 귀찮은 과정을 거쳐야 했다. 있어야 할 beam file을 copy하지 않아서 수동으로 copy해야 했다. 뭔가 잘못된 것 같은데...
sinan으로 다시 dependency 관리를 해봐야겠다. 아마도 app2에 dependency library source를 놓으면 될 듯 하다.

아래 링크를 꼭 확인하자. 제일 편하게 만들어 놓았다!
http://blog.pqsdk.org/from-zero-to-deployment-with-cowboy-in-5-minu
이걸 수정하여, 다시 이렇게 만들었다.
https://github.com/wdshin/myappt

=>
rebar와 reltool에 완전히 익숙해졌다. 다음 프로젝트의 구성을 참고하면 된다.
https://github.com/wdshin/bigwig


2012년 8월 22일 수요일

mongoDB to mysql


mongoDB에서 mySQL로 이전을 성공적으로 마쳤다. riak으로 바꾸고 싶었지만, 아직 검증되지 않은 이유로 적용할 수 없었다.

mongoDB는 이제 안 쓰게 될 것이다.

mongoDB가 global lock문제를 해결하길 바란다.


mochiweb bug with webmachine


webmachine은 mochiweb의 현재 버전이 아닌 예전 버젼에 dependency를 갖고 있는데,
과도한 스트레스를 주거나, 잘못된 인자를 주면, no match clause error를 낸다.

이때, mochiweb의 src에 있는 mochiweb_http 를 다음 파일로 바꿔주기만 하면, 더 이상 그 에러를 내지 않는다.
https://github.com/mochi/mochiweb/blob/master/src/mochiweb_http.erl

webmachine이 mochiweb 최신 버젼에 맞춰서 업데이트 되길 바란다.

덕분에 cowboy와, ChicagoBoss로 관심을 돌리게 되었다.
같은 어플리케이션을 요 두가지 framework으로 구현해보고 스트레스 테스트 해봐야겠다.




2012년 8월 21일 화요일

logging for future use in hbase and rhive


logging으로 그냥 쓰던 db에 넣으려고 했는데,
hbase와 rhive를 알아버렸다.

erlang 과 hbase를 연결해서, log들을 넣고,
나중에 rhive로 분석해서 뭔가 의미 있는 것을 추출할 수 있으리라 기대하면서,
일단은 hbase를 설정해 놓으려고 한다. ㅎ

설치는 아래처럼 하면 될 듯.
http://kungfooguru.wordpress.com/2009/08/31/erlang-thrift-and-hbase/

아쉽게도 erlang으로 되어 있지 않아서, thrift로 통신해야 하지만, 별 문제는 없을 듯.

다만, 궁금한 것은 hbase의 안정성과 성능이다.
hbase가 zookeeper로 구현해서 node추가/삭제/관리는 잘 할 듯 보이고, 안정성은 돌려봐야 한다. cassandra에 비해서 안정성이 떨어진다는 이야기가 있다. -.-;
rhive에서 어떤 DB도 연결해서 쓸 수 있을 것 같은데... hbase가 딱히 답은 아닐 수도 있다.
실전에서 rhive를 사용하는 입장에서, logging DB를 유지 관리하는 입장에서의 답이 매우 궁금하다.

R 언어를 배우는 것도 흥미롭다. 벡터 기반언어의 재미를 느낄 수 있다. rCuda도 있다고 하니... 미래가 흥미롭기도 하다.

현재의 state-of-the-art는 실시간은 아닌데, 실시간 분석이 되려면 어찌 되야 하는지 연구 대상이다.
서비스 중에 각종 얼러트를 서비스 책임자에게 날려줄 수 있다면, 얼마나 좋겠는가?

2012년 7월 5일 목요일

using rebar


Richard Jones 님이 정리한, rebar 사용법.
http://www.metabrew.com/article/erlang-rebar-tutorial-generating-releases-upgrades

이건 2010년도에 Belo Horizonte님이 정리한 사용법
http://alancastro.org/2010/05/01/erlang-application-management-with-rebar.html

그런데, outdated된 내용도 있고, 그대로 딱 되지는 않는다.

당장 필요한 것만 정리하면 다음과 같다.

1. rebar를 다운로드 받는다.
https://github.com/basho/rebar

2. 프로젝트 루트 디렉토리를 만든다. 그리고 rebar를 copy한다.
#> mkdir proj_home
#> cd proj_home

3.  proj_home/apps/mysample/src 로 프로젝트를 만든다.
디렉토리 구조는, https://github.com/RJ/erlang_rebar_example_project/tree/v1 이것을 참조하면 된다.

src 폴더에서,
#> rebar create-app appid=mysample
로 소스를 생성한다.

mysample_app.erl 을 mysample.erl로 mv하고, start/0 함수를 추가한다.

다음을 rebar.config에 추가한다.


{sub_dirs, [
            "apps/mysample",
            "rel"
           ]}.


그리고, 추가 소스를 넣고, 동작이 되게 하고, 컴파일한다.
#> ./rebar compile

4. release버젼을 만들어 본다.

#> mkdir rel
#> cd rel
#> ../rebar create-node nodeid=mysample

=> rel.config를 수정한다.
https://github.com/RJ/erlang_rebar_example_project/blob/v1/rel/reltool.config
{lib_dirs, ["../apps"]},

{rel, "dummy", "1",
        [
         kernel,
         stdlib,
         sasl,
         dummy_app
        ]},

이 부분을 수정하면 된다.

#> cd ..
#> ./rebar generate

5. 확인한다.
#> bin/mysample 치면 console,start,stop,attach,ping 등을 해 볼 수 있다.





2012년 7월 2일 월요일

distributed read/write cache for type value store


riak을 ram(memory) backend로 설정도 해보고,
redis/memcached도 고려해 보고,
couchBase도 고려해보고,
RabbitMQ를 이용한 방식도 생각해봤다.
scalaris도 설치해봤다.

riak은 내부적으로 erlang의 ets를 사용하는데, stress test시 garbage collection을 제대로 처리 못해서, swap memory를 사용한다. 그래서, 갑자기 퍼포먼스가 떨어진다.

redis/memcached는 memory flush out에 callback을 붙이는 것이 단기간에는 쉽지 않았다.

couchBase는 license비용 때문에, 엄두가 나질 않았다.

scalaris는 설정하다가 실패. 아직 찾아볼 자료도 별로 없다. 소스 리뷰는 도움이 된다.

결국, cache에 대해서는, mnesia를 사용해서 자체적인 분산처리 agent를 만들기로 결정했다.

결론적으로, 현재의 best practice는 memory cache 를 read only로 redis를 사용하고,(그것이 싫다면 자체제작) persistence에 대해서는 riak의 bitcask를 사용하는 것인 듯.

mongoDB와 riak은 근본적으로 분산처리 알고리즘이 다르다.
어떻게 다른지, 잘 알고 써야 한다. mongoDB는 controller를 통해서, hash key를 통제하는 방식이고, riak은 vnode를 사용하여, peer끼리 gossip하며 balance시키며 교환하는 방식이다. mongoDB는 자체적으로 memory cache를 갖고 있기 때문에, 성능이 더 좋다. 하지만, 잘 쓰기 나름이다. 개인적으로 riak이 더 마음에 든다.
Riak의로 AP를 확보하고, Memory Cache로 C(Consistency)와 성능을 확보하면 완벽할 듯.



mongoDB value size


type-value store를 넘어서 document store라고 알려져 있는데...
실제로는 그렇지 않다.
최대 value size를 10k 이하로 유지할 것.
그러기 위해서 key를 잘 선정하고, 잘 쪼갤 것.

그리고, nested 구조를 쓰지 말 것.


그렇다고, couchDB(couchBase)는 잘 될까?


2012년 6월 28일 목요일

erlang node


riak에서 riak-admin join을 하다가
unreachable이 나와서, 알아보다가 실수를 하였다. -.-;

node().
를 쉘에서 넣으면, 현재 node의 이름이 나온다.
erlang:get_cookie()
를 넣으면, 현재 세팅된 cookie가 나온다.
net_adm:ping('some@remote.ip').
하면, 리모트 노드와 연결 가능한 상태인지 알 수 있다.
이때  cookie가 다르면, pang이 뜬다.
command shell에서 ping이 되더라도,
cookie값이 다른지 스펠링부터 확인하자.


2012년 6월 27일 수요일

list_to_atom and apply


외부에서 callback 으로 설정할 모듈:함수 이름을 전달했다고 치자.

M=list_to_atom(ConfigModuleName).
F=list_to_atom(ConfigFuncName).
Args=[1,2,3].
apply(M,F,Args).

이렇게 하면, 원하는 함수를 실행시킬 수 있다.
다만, DoS를 피하려면, list_to_existing_atom 을 쓰면 안전하다.



mongoDB to riak + postgres


http://vimeo.com/42744689

mongoDB로 고생하다가
riak + postgres로 바꾼 스토리다.

덤덤하게 이야기하지만, 많이 고생했을 것 같다.


2012년 6월 15일 금요일

using riakpool_client in erlang

https://github.com/dweldon/riakpool

riakpool_client는 riak pb client에 connection pooling 기능을 넣어서 쓸 수 있게 해준다.
간단하게 쓸 수 있다. 하지만, 실전에 쓰기에는 아직 부족함이 많다.
riak http client ( https://github.com/basho/riak-erlang-http-client )을 쓰는 것이 맞을지도 모르겠다. 어떤 것을 쓰는게 빠를지 테스트 해 볼 예정이다.

riak은 key-value store다. value에 attribute들을 여러개 넣으려면,  record를 저장해야 할텐데, binary로 변환해서 저장한다. 즉, record를 꽉 채워서 넣어야 한다. 일부 field만 저장하는 것은 지원하지 않는다. 그렇게 하려면, record를 읽어와서, 바뀐 field만 다시 record에 넣고, put해야 한다. 이 부분은, 좀 아쉽다! 근데, 다른 key-value store도 내부적으로 그렇게 할 듯 하다. 확인이 필요한 부분이다. 현재까지 내가 확인 한 것은 그렇다. -.-;;
다음은 간단히 record를 put하는 예제를 구현해 봤다.

1> rd(item, {id,name} ).
item
2> It=#item{ id= <<"aaa">> , name = <<"bbb">> }.
#item{id = <<"aaa">>,name = <<"bbb">>}

3> riakpool_client:put( <<"aaa">> , <<"bbb">> , term_to_binary(It) ).
ok
4> { ok , R } =  riakpool_client:get( <<"aaa">> , <<"bbb">> ).

5> binary_to_term(R).
#item{id = <<"aaa">>,name = <<"bbb">>}
6> R2 = binary_to_term(R).
#item{id = <<"aaa">>,name = <<"bbb">>}
7> R2#item.id.
<<"aaa">>


2012년 6월 14일 목요일

erlang in production leads to haskell


Erlang으로 프로젝트를 시작한지 3주.
아주 만족스럽다.
deployment와 management,scale 이슈만 커버하면 거의 다 마스터 될 듯.

Erlang을 입문하는데, 어려움을 겪고 있다면,
webmachine,mochiweb을 써서 간단한 것이라도 만들어 보길 권한다.
금새 익숙해 질 것이다. ^^

최근에 다시 haskell을 보기 시작했는데,
Erlang에 익숙해지니, 전에 어렵게 느껴지던 haskell도 훨씬 쉬워 보인다.

Haskell에 OTP의 기능들이 들어오면 좋을텐데...
Haskell/OTP 프로젝트 없을까? ^^

DB는 mnesia와 riak을 프로젝트에 쓸 것이다.
두개의 성능 테스트의 결과가 흥미진진하다.


2012년 6월 10일 일요일

10 year project


* Erlang/Haskell으로 web/game을 위한 서버사이드의 모든 미들웨어와 서비스를 구현
-> 2~3년내에 가능

* GPGPU를 활용하는 언어 디자인
그에 따른 게임엔진 구현
그에 따른 게임 구현

10년을 투자할만하지 않을까? ^^


erlang in production

erlang으로 드디어 실제 서비스에 들어갈 작업을 한다.
2주 정도만에, 프로토타입을 완성했다.

mochiweb,webmachine,mnesia을 이용하여, 서버를 구현하고,
html/javascript/jquery로 웹 클라이언트,
iOS에선 Obj-c로 앱 클라이언트를 구현했다.

이곳저곳에서 웹서핑을 하며, 예제를 구하고, 테스트 하고, 코딩하면서
즐겁게 코딩했다.

erlang의 위대함을 느낄 수 있었다.

데이터베이스는 mnesia를 쓰고 있지만,
riak이나 couchBase등을 쓸 계획도 있다. 물론 모두 테스트 해서 어플리케이션에 맞는 DB를 고를 것이다.

erlang으로 작업하고 있자니, 내버려둔 haskell이 생각나서, haskell도 다시 보려고 한다.
haskell로 production에 써야 할텐데...

앱 클라이언트로는 native하게 obj-c로 쓰긴 했지만,
cross platform용으로 mosync를 쓸 생각이다.


2012년 4월 17일 화요일

150 spells


5개 대륙,
25개의 영웅,
100개 남짓의 유닛,
150여개의 아이템.

스마트폰 게임에서 이 정도 스케일의 작품이 있었나?

덕분에 용량은 200메가를 육박한다.
압축하자;;;

2~3개월안에 출시 꼭 한다.
세상을 놀라게 하는거다.

2012년 1월 24일 화요일

playframework for google app engine


play!framework 홈페이지에 오랜만에 들어가봤다.
그들은 2.0을 만들고 있었다.

요즘은 웹프레임워크가 모두 Cloud환경에 맞춰서 개발한다.
그에 맞게 대대적인 공사중인 듯 하다.

실망스럽지만, google app engine을 사용하고, smart phone game에서 쉽게 가져다가 쓸 수 있는 framework는 아직 없는 듯 하다.
play!framework를 일단 쓰기로 했다.
google app engine을 data store로 사용하면 전세계 배포에 문제가 없기 때문이다.


pain on me :(


몸도 마음도 한달째 좋지 않다. 원인을 찾고 있다.
부정적인 임팩트에 쉽게 지쳐버리는 체질이 된 것 아닐까 의심하고 있다.
더 강해져야 한다.
기도하자.

no pain, no gain. T_T

2012년 1월 20일 금요일

Time to package


출시 3~4개월을 앞두고 있다.

기본적인 게임의 완성도 이외에도 챙겨야 할 일들이 많다.
지금 일단 생각하고 있는 것들은 다음과 같다.

1순위 : 게임의 재미 확보, 안정성
2순위 : UI 완성도 , 튜토리얼(학습곡선)
3순위 : 컨텐츠 량 ( 캐릭터,아이템,스테이지 )
4순위 : 그래픽 퀄러티
5순위 : 사운드 퀄러티
6순위 : 아웃게임 및 게임센터 ( Achievement ), 아이템샵
7순위 : 소셜 ( 랭킹, 페이스북, 트위터 )
8순위 : 패키징 퀄러티 ( 소개글, 스샷, 용량 , 로고, 이름 )
9순위 : 멀티플랫폼 테스트 ( 안드로이드, 아이폰, 아이패드, 태블릿 )
10순위 : 가격정책, 유료화 ( 포인트샵, 광고 )
11순위 : 반복적인 재미를 위한 스테이지, 업데이트 확장성
12순위 : PvP, Online (옵션;;;)
13순위 : 홍보, 마케팅 ( 웹페이지 , 포지셔닝 키워드 , 앱스토어 등록 )


2012년 1월 10일 화요일