2009年3月22日星期日

thrift粘合erlang

上篇用thrift尝试了粘合cpp和python,其实我们也可以看出来,所谓的粘合,无非是thrift通过socket的方式产生各种语言的服务器端和客户端的代码,然后可以用任意语言写服务器接口,用任意语言去调用这些服务端的接口。

ok,继续上次hello.thrift,我们先装好thrift-erlang的扩展包,还是去上篇文章里提到的地址down下来安装。然后是生成erlang的代码:
thrift -erl hello.thrift
这样就生成了gen-erl的文件夹。

接着我们用上一篇的python版本的hello跑服务器端,也就是python HelloServer.py
然后我们写个erlang版本的客户端去测试:
hello_client.erl
%% @author author

-module(hello_client).
-include("hello_thrift.hrl").
-export([test/0]).

p(X)->
io:format("~s~n", [X]),
ok.

test()->
Port = 9090,
{ok, Socket} = thrift_client:start_link("localhost",
Port,
hello_thrift),
{ok, Result} = thrift_client:call(Socket, say, ["world"]),
p(Result),
thrift_client:close(Socket),
ok.

写个Makefile:

ERL_THRIFT=/usr/lib/erlang/thrift/

all:
erlc -I ${ERL_THRIFT}/include *.erl
erl +K true -pa ${ERL_THRIFT}/ebin
clean:
rm *.beam
make之,会走到erl的命令行,运行:

erl> hello_client:test()

可以看到输出了

Hello, world
ok

说明这个客户端正常运行了。

都说erlang的高并发能力,不用erlang写服务器端有点可惜,所以来做一个erlang版本的服务器端,继续在gen-erl的文件夹下建立一个hello_server.erl:

%% @author author

-module(hello_server).
-include("hello_thrift.hrl").
-export([start/0, handle_function/2, say/1, stop/1]).

debug(Info)->
io:format("Debug info:~s~n",[Info]).

say(Name)->
Sentence = "Hello," ++ Name,
debug(Sentence),
BinSentence = list_to_binary(Sentence),
BinSentence.

start()->
start(9090).

start(Port)->
Handler = ?MODULE,
thrift_socket_server:start([{handler, Handler},
{service, hello_thrift},
{port, Port},
{name, hello_server}]).

stop(Server)->
thrift_socket_server:stop(Server).


handle_function(Function, Args) when is_atom(Function), is_tuple(Args) ->
case apply(?MODULE, Function, tuple_to_list(Args)) of
ok -> ok;
Reply -> {reply, Reply}
end.
上面的也很简单,和python版本的HelloServer本质是相同的,绑定9090的端口,实现了say的函数;其它的函数,start和stop不用多说,handle_function这个函数比较重要,注意我们erlang版本的客户端的代码调用了thrift_client:call的方法,这个方法传递了函数名和参数的tuple,以让服务器去做函数调用的分发,这一层在python版本的Server中是看不出的,而erlang的这个版本的handle_function就是实现了这个,这个函数是必须的。

第二个需要注意的地方是say函数,这个函数返回一个字符串,我本来使用直接返回Sentence结果,但是当客户端调用时总是出错,后来将这个字符串转成了二进制,也就是使用了list_to_binary的函数,这样才正确运行。我想也是thrift的内部通讯是通过2进制的,这个在cpp和python版的命名中(BinaryProtocol)可以看出来。

ok,试验我们的erlang服务器端,先停掉python版的那个服务器端(因为两个都用了9090的端口),然后Makefile不用变,make之,进入erl的控制台,运行:
erl> hello_server:start()

服务器就启动了。

运行erlang版的客户端/cpp版的客户端/python版的客户端都没有问题~ ^_^

---
Erlang版的就先到此,接下来或许是java版的。

1 条评论:

  1. 写的不错,但是没写thrift erlang库怎么编译

    回复删除