Embed presentation
Downloaded 57 times





![This Talk
Our Application: A Sequence Server
Erlang service that returns a sequence of numbers.
1 sequence(N) ->
2 List1 = lists:seq(1, N),
3 List2 = [list_to_binary(integer_to_list(X)) || X <- List1],
4 {ok, List2};
5
6 %% sequence(2).
7 {ok, [<<"1">>, <<"2">>]}.
8
9 %% sequence(5).
10 {ok, [<<"1">>, <<"2">>, <<"3">>, <<"4">>, <<"5">>]}.
11
12 %% sequence(50000).
13 {ok, [<<"1">>, <<"2">>, <<"3">>, <<"4">>, ...]}.
6 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-6-2048.jpg)





![BERT-RPC - Overview
BERT-RPC
Developed by GitHub (Tom Preston-Werner)
BERT = Binary Erlang Term
• Encoding mimics native Erlang serialization
http://bert-rpc.org
https://github.com/mojombo/ernie
1 % Request
2 {call, ernie_sequence, sequence, [3]}
3
4 % Response
5 {response, {ok, [<<"1">>, <<"2">>, <<"3">>]}}
12 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-12-2048.jpg)


![REST / JSON - Request & Response
Request
GET /sequence/3 HTTP/1.1
User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4
OpenSSL/0.9.8r zlib/1.2.5
Host: localhost:8001
Accept: */*
Response
HTTP/1.1 200 OK
Server: MochiWeb/1.1 WebMachine/1.9.0 (someone had painted it blue)
Date: Wed, 23 Nov 2011 22:09:13 GMT
Content-Type: application/json
Content-Length: 21
["1","2","3"]
15 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-15-2048.jpg)

![Protocol Buffers - RPC
Request
1 rpc_demo_pb:encode({sequencerequest, 3}).
2 <<8,3>>
Response
1 rpc_demo_pb:encode({sequenceresponse, [<<"1">>, <<"2">>, <<"3">>]}).
2 <<10,1,49,10,1,50,10,1,51>>
17 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-17-2048.jpg)
![BERT-RPC - Encoding
1 term_to_binary([<<"1">>,<<"2">>,<<"3">>]).
2 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
3
4
5 bert:encode([<<"1">>,<<"2">>,<<"3">>]).
6 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
18 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-18-2048.jpg)
![BERT-RPC - Encoding
1 term_to_binary([<<"1">>,<<"2">>,<<"3">>]).
2 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
3
4
5 bert:encode([<<"1">>,<<"2">>,<<"3">>]).
6 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
7 | | | | | |
8 | | | | | + Ascii value for '1'
9 | | | | + Length of string (1)
10 | | | + Next term is a string
11 | | + Length of list (3)
12 | + Next term is a list
13 + Start of Erlang term
19 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-19-2048.jpg)
![BERT-RPC - RPC
Request
1 bert:encode({call, ernie_sequence, sequence, [5]}).
3 <<131,104,4,100,0,4,99,97,108,108,100,0,14,101,114,110,
4 105,101,95,115,101,113,117,101,110,99,101,100,0,8,115,
5 101,113,117,101,110,99,101,107,0,1,5>>
Response
1 bert:encode({reply,{ok,[<<"1">>,<<"2">>,<<"3">>,<<"4">>,<<"5">>]}}).
2
3 <<131,104,2,100,0,5,114,101,112,108,121,104,2,100,0,2,111,
4 107,108,0,0,0,5,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,
5 1,51,109,0,0,0,1,52,109,0,0,0,1,53,106>>
20 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-20-2048.jpg)





![REST / JSON - Server
Spooky Server
1 -module(spooky_sequence).
2 -behaviour(spooky).
3 -export([init/1, get/2]).
4
5 init([])->
6 [{port, 8002}].
7
8 get(_Req, ["sequence", Num])->
9 case sequence:sequence(Num) of
10 {ok, List} ->
11 {200, mochijson2:encode(List)};
12 {error, Error} ->
13 {500, io_lib:format("~w", [Error])}
14 end;
15 get(_Req, _)->
16 {400, "Usage: /sequence/:Num:"}.
26 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-26-2048.jpg)
![REST / JSON - Server
Webmachine Server
1 -module(webmachine_sequence).
2 -export([init/1, content_types_provided/2, to_json/2]).
3 -include_lib("webmachine/include/webmachine.hrl").
4
5 -record(ctx, { list }).
6
7 init([]) ->
8 {ok, #ctx {}}.
9
10 content_types_provided(RD, Ctx) ->
11 Types = [{"application/json", to_json}],
12 {Types, RD, Ctx}.
13
14 to_json(RD, Ctx) ->
15 {ok, List} = sequence:sequence(N),
16 Body = mochijson2:encode(List),
17 {Body, RD, Ctx}.
27 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-27-2048.jpg)
![Protocol Buffers - Server
Erlang Server
1 %% Erlang RPC Demo
57 handle_info({tcp, _Sock, _Data}, State) ->
2 %% Copyright (c) 2011 Rusty Klophaus (@rustyio)
58 %% req =/= undefined: received a new request while another was in
3 %% See MIT-LICENSE for licensing information.
59 %% progress -> Error
4
60 lager:error("Received a new PB socket request"
5 -module(protobuff_server).
61 " while another was in progress"),
6 -behaviour(gen_server).
62 {stop, normal, State};
7
63
8 -export([
64 handle_info(_, State) -> % Ignore any late replies from gen_servers/messages from fsms
9 start_link/0,
65 {noreply, State}.
10 set_socket/2,
66
11 init/1,
67 terminate(_Reason, _State) ->
12 handle_call/3,
68 ok.
13 handle_cast/2,
69
14 handle_info/2,
70 code_change(_OldVsn, State, _Extra) -> {ok, State}.
15 terminate/2,
71
16 code_change/3,
72 %% ===================================================================
17 encode/1,
73 %% Handle PB Messages
18 decode/1]).
74 %% ===================================================================
19
75
20 -record(state, { sock }).
76 process_message(#sequencerequest { n = N }, State) ->
21
77 case sequence:sequence(N) of
22 -include("rpc_demo_pb.hrl").
78 {ok, List} ->
23
79 Resp = #sequenceresponse { sequence = List },
24 %% ===================================================================
80 send_msg(Resp, State);
25 %% Public API
81 {error, Reason} ->
26 %% ===================================================================
82 Msg = io_lib:format("~w", [Reason]),
27
83 Resp = #sequenceerror { message=Msg },
28 start_link() ->
84 send_msg(Resp, State)
29 gen_server:start_link(?MODULE, [], []).
85 end.
30
86
31 set_socket(Pid, Socket) ->
87 %% Send a message to the client
32 gen_server:call(Pid, {set_socket, Socket}).
88 send_msg(Msg, State) ->
33
89 Pkt = encode(Msg),
34 init([]) ->
90 gen_tcp:send(State#state.sock, Pkt),
35 {ok, #state{}}.
91 State.
36
92
37 handle_call({set_socket, Socket}, _From, State) ->
93 encode(Msg) ->
38 inet:setopts(Socket, [{active, once}, {packet, 4}, {header, 1}]),
94 MsgType = element(1, Msg),
39 {reply, ok, State#state{sock = Socket}}.
95 [msg_code(Msg) | rpc_demo_pb:iolist(MsgType, Msg)].
40
96
41 handle_cast(_Msg, State) ->
97 decode([MsgCode|MsgData]) ->
42 {noreply, State}.
98 MsgType = msg_type(MsgCode),
43
99 rpc_demo_pb:decode(MsgType, MsgData).
44 handle_info({tcp_closed, Socket}, State=#state{sock=Socket}) ->
100
45 {stop, normal, State};
101 msg_code(#sequencerequest {}) -> 1;
46 handle_info({tcp_error, Socket, _Reason}, State=#state{sock=Socket}) ->
102 msg_code(#sequenceresponse {}) -> 2;
47 {stop, normal, State};
103 msg_code(#sequenceerror {}) -> 3;
48 handle_info({tcp, _Sock, MsgData}, State=#state{sock=Socket}) ->
104 msg_code(Other) ->
49 Msg = decode(MsgData),
105 throw({unknown_pb_type, Other}).
50 case process_message(Msg, State) of
106
51 {pause, NewState} ->
107 msg_type(1) -> sequencerequest;
52 ok;
108 msg_type(2) -> sequenceresponse;
53 NewState ->
109 msg_type(3) -> sequenceerror;
54 inet:setopts(Socket, [{active, once}])
110 msg_type(Other) ->
55 end,
111 throw({unknown_pb_code, Other}).
56 {noreply, NewState};
28 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-28-2048.jpg)
![BERT-RPC - Server
Ernie Server - Erlang BERT-RPC Server
1 %% FILE: ernie.config
2 [
3 {module, ernie_sequence},
4 {type, native},
5 {codepaths, []}
6 ].
1 -module(ernie_sequence).
2 -export([sequence/1]).
3
4 sequence(N) ->
5 sequence:sequence(N).
29 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-29-2048.jpg)





























The document discusses cross-language remote procedure calls (RPC) using Erlang, highlighting various serialization formats including REST/JSON, Protocol Buffers, and BERT-RPC. It presents the advantages and disadvantages of each method, along with code examples for implementing a sequence server in Erlang. Additionally, it covers encoding speed benchmarks and the performance of different serialization methods in various programming environments.





![This Talk
Our Application: A Sequence Server
Erlang service that returns a sequence of numbers.
1 sequence(N) ->
2 List1 = lists:seq(1, N),
3 List2 = [list_to_binary(integer_to_list(X)) || X <- List1],
4 {ok, List2};
5
6 %% sequence(2).
7 {ok, [<<"1">>, <<"2">>]}.
8
9 %% sequence(5).
10 {ok, [<<"1">>, <<"2">>, <<"3">>, <<"4">>, <<"5">>]}.
11
12 %% sequence(50000).
13 {ok, [<<"1">>, <<"2">>, <<"3">>, <<"4">>, ...]}.
6 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-6-2048.jpg)





![BERT-RPC - Overview
BERT-RPC
Developed by GitHub (Tom Preston-Werner)
BERT = Binary Erlang Term
• Encoding mimics native Erlang serialization
http://bert-rpc.org
https://github.com/mojombo/ernie
1 % Request
2 {call, ernie_sequence, sequence, [3]}
3
4 % Response
5 {response, {ok, [<<"1">>, <<"2">>, <<"3">>]}}
12 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-12-2048.jpg)


![REST / JSON - Request & Response
Request
GET /sequence/3 HTTP/1.1
User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4
OpenSSL/0.9.8r zlib/1.2.5
Host: localhost:8001
Accept: */*
Response
HTTP/1.1 200 OK
Server: MochiWeb/1.1 WebMachine/1.9.0 (someone had painted it blue)
Date: Wed, 23 Nov 2011 22:09:13 GMT
Content-Type: application/json
Content-Length: 21
["1","2","3"]
15 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-15-2048.jpg)

![Protocol Buffers - RPC
Request
1 rpc_demo_pb:encode({sequencerequest, 3}).
2 <<8,3>>
Response
1 rpc_demo_pb:encode({sequenceresponse, [<<"1">>, <<"2">>, <<"3">>]}).
2 <<10,1,49,10,1,50,10,1,51>>
17 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-17-2048.jpg)
![BERT-RPC - Encoding
1 term_to_binary([<<"1">>,<<"2">>,<<"3">>]).
2 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
3
4
5 bert:encode([<<"1">>,<<"2">>,<<"3">>]).
6 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
18 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-18-2048.jpg)
![BERT-RPC - Encoding
1 term_to_binary([<<"1">>,<<"2">>,<<"3">>]).
2 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
3
4
5 bert:encode([<<"1">>,<<"2">>,<<"3">>]).
6 <<131,108,0,0,0,3,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,1,51,106>>
7 | | | | | |
8 | | | | | + Ascii value for '1'
9 | | | | + Length of string (1)
10 | | | + Next term is a string
11 | | + Length of list (3)
12 | + Next term is a list
13 + Start of Erlang term
19 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-19-2048.jpg)
![BERT-RPC - RPC
Request
1 bert:encode({call, ernie_sequence, sequence, [5]}).
3 <<131,104,4,100,0,4,99,97,108,108,100,0,14,101,114,110,
4 105,101,95,115,101,113,117,101,110,99,101,100,0,8,115,
5 101,113,117,101,110,99,101,107,0,1,5>>
Response
1 bert:encode({reply,{ok,[<<"1">>,<<"2">>,<<"3">>,<<"4">>,<<"5">>]}}).
2
3 <<131,104,2,100,0,5,114,101,112,108,121,104,2,100,0,2,111,
4 107,108,0,0,0,5,109,0,0,0,1,49,109,0,0,0,1,50,109,0,0,0,
5 1,51,109,0,0,0,1,52,109,0,0,0,1,53,106>>
20 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-20-2048.jpg)





![REST / JSON - Server
Spooky Server
1 -module(spooky_sequence).
2 -behaviour(spooky).
3 -export([init/1, get/2]).
4
5 init([])->
6 [{port, 8002}].
7
8 get(_Req, ["sequence", Num])->
9 case sequence:sequence(Num) of
10 {ok, List} ->
11 {200, mochijson2:encode(List)};
12 {error, Error} ->
13 {500, io_lib:format("~w", [Error])}
14 end;
15 get(_Req, _)->
16 {400, "Usage: /sequence/:Num:"}.
26 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-26-2048.jpg)
![REST / JSON - Server
Webmachine Server
1 -module(webmachine_sequence).
2 -export([init/1, content_types_provided/2, to_json/2]).
3 -include_lib("webmachine/include/webmachine.hrl").
4
5 -record(ctx, { list }).
6
7 init([]) ->
8 {ok, #ctx {}}.
9
10 content_types_provided(RD, Ctx) ->
11 Types = [{"application/json", to_json}],
12 {Types, RD, Ctx}.
13
14 to_json(RD, Ctx) ->
15 {ok, List} = sequence:sequence(N),
16 Body = mochijson2:encode(List),
17 {Body, RD, Ctx}.
27 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-27-2048.jpg)
![Protocol Buffers - Server
Erlang Server
1 %% Erlang RPC Demo
57 handle_info({tcp, _Sock, _Data}, State) ->
2 %% Copyright (c) 2011 Rusty Klophaus (@rustyio)
58 %% req =/= undefined: received a new request while another was in
3 %% See MIT-LICENSE for licensing information.
59 %% progress -> Error
4
60 lager:error("Received a new PB socket request"
5 -module(protobuff_server).
61 " while another was in progress"),
6 -behaviour(gen_server).
62 {stop, normal, State};
7
63
8 -export([
64 handle_info(_, State) -> % Ignore any late replies from gen_servers/messages from fsms
9 start_link/0,
65 {noreply, State}.
10 set_socket/2,
66
11 init/1,
67 terminate(_Reason, _State) ->
12 handle_call/3,
68 ok.
13 handle_cast/2,
69
14 handle_info/2,
70 code_change(_OldVsn, State, _Extra) -> {ok, State}.
15 terminate/2,
71
16 code_change/3,
72 %% ===================================================================
17 encode/1,
73 %% Handle PB Messages
18 decode/1]).
74 %% ===================================================================
19
75
20 -record(state, { sock }).
76 process_message(#sequencerequest { n = N }, State) ->
21
77 case sequence:sequence(N) of
22 -include("rpc_demo_pb.hrl").
78 {ok, List} ->
23
79 Resp = #sequenceresponse { sequence = List },
24 %% ===================================================================
80 send_msg(Resp, State);
25 %% Public API
81 {error, Reason} ->
26 %% ===================================================================
82 Msg = io_lib:format("~w", [Reason]),
27
83 Resp = #sequenceerror { message=Msg },
28 start_link() ->
84 send_msg(Resp, State)
29 gen_server:start_link(?MODULE, [], []).
85 end.
30
86
31 set_socket(Pid, Socket) ->
87 %% Send a message to the client
32 gen_server:call(Pid, {set_socket, Socket}).
88 send_msg(Msg, State) ->
33
89 Pkt = encode(Msg),
34 init([]) ->
90 gen_tcp:send(State#state.sock, Pkt),
35 {ok, #state{}}.
91 State.
36
92
37 handle_call({set_socket, Socket}, _From, State) ->
93 encode(Msg) ->
38 inet:setopts(Socket, [{active, once}, {packet, 4}, {header, 1}]),
94 MsgType = element(1, Msg),
39 {reply, ok, State#state{sock = Socket}}.
95 [msg_code(Msg) | rpc_demo_pb:iolist(MsgType, Msg)].
40
96
41 handle_cast(_Msg, State) ->
97 decode([MsgCode|MsgData]) ->
42 {noreply, State}.
98 MsgType = msg_type(MsgCode),
43
99 rpc_demo_pb:decode(MsgType, MsgData).
44 handle_info({tcp_closed, Socket}, State=#state{sock=Socket}) ->
100
45 {stop, normal, State};
101 msg_code(#sequencerequest {}) -> 1;
46 handle_info({tcp_error, Socket, _Reason}, State=#state{sock=Socket}) ->
102 msg_code(#sequenceresponse {}) -> 2;
47 {stop, normal, State};
103 msg_code(#sequenceerror {}) -> 3;
48 handle_info({tcp, _Sock, MsgData}, State=#state{sock=Socket}) ->
104 msg_code(Other) ->
49 Msg = decode(MsgData),
105 throw({unknown_pb_type, Other}).
50 case process_message(Msg, State) of
106
51 {pause, NewState} ->
107 msg_type(1) -> sequencerequest;
52 ok;
108 msg_type(2) -> sequenceresponse;
53 NewState ->
109 msg_type(3) -> sequenceerror;
54 inet:setopts(Socket, [{active, once}])
110 msg_type(Other) ->
55 end,
111 throw({unknown_pb_code, Other}).
56 {noreply, NewState};
28 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-28-2048.jpg)
![BERT-RPC - Server
Ernie Server - Erlang BERT-RPC Server
1 %% FILE: ernie.config
2 [
3 {module, ernie_sequence},
4 {type, native},
5 {codepaths, []}
6 ].
1 -module(ernie_sequence).
2 -export([sequence/1]).
3
4 sequence(N) ->
5 sequence:sequence(N).
29 @rustyio](https://image.slidesharecdn.com/2011-erlangdc-rustyklophaus-111203213117-phpapp01/75/Everybody-Polyglot-Cross-Language-RPC-with-Erlang-29-2048.jpg)



























