PREviously on LAMBDA
base data types
processes
message passing (send/receive)
process registry
gen_server
TODAY
Erlang VM (BEAM) ecosystem
Erlang language extensions
OTP
let it crash!
clustering and distributed systems
Erlang VM (BEAM)
SMP and non-SMP BEAM versions
one SMP scheduler per thread per core by default
erl> erlang:system_info (cpu_topology).
processes usually travel across schedulers
BEAM ECOSYSTEM
Erlang -> CoreErlang -> BEAM
<anyLanguage> [ -> CoreErlang ] -> BEAM
where <anyLanguage> can be:
LFE, Elixir, Joxa, Reia, ...
LuvvieScript
IDEA Object Database
Erjang (Erlang on JVM),
multiple BEAM emulators for JS
NIFs, ports, drivers, ...
Erlang language Extensions
In context of modules and data types,
we haven't mentioned yet:
namespaces
pmods
records
maps
behaviors
parse_transform, custom preprocesors, syntax tools
Open Telecom platform (OTP)
...has nothing to do with telco in fact :-)
gen_server reminder (call, cast, info)
gen_fsm (finite state machine)
gen_event (event handling)
applications, supervisors,
automatic failover
PRODUCTIVITY MATTERS
Source: Productivity Gains in Erlang
LET IT CRASH!
don't be defensive
pattern matching, tagged values
"normal" vs system messages
LIVE DEMO
process (node) monitoring
linked processes
monitor (process, node)
linked processes
process flags & trap_exit
supervisors, heartbeat
CRASH EXAMPLES
Fx1 = fun (Pid) -> monitor (process, Pid) end.
Fx2 = fun (Pid) -> link (Pid) end.
Fx3 = fun (Pid) -> link (Pid), process_flag (trap_exit, true) end.
Print = fun (Msg) -> io:format ("Received: ~p~n", [Msg]) end.
Test = fun (Fx) ->
X = spawn (fun () ->
receive _ -> error ('X-crash-boom-bang!') end
end),
Y = spawn (fun () ->
Fx (X),
receive Msg -> Print (Msg) end
end),
X ! hello
end.
[ Test (F) || F <- [Fx1, Fx2, Fx3] ].
RECONSTRUCT PRE-CRASH STATE
shared nothing
processes may eventually die
process restarts with an empty state
so how to get back the state?
solution: ETS, DETS, Mnesia, ...
ETS heir and ownership transfers
state manager server
NODE MONITORING
toolbar, appmon, observer,
os_mon
CLUSTERING
JCL (^G)
epmd
$ erl -sname foo
$ erl -sname boo -remsh foo@gersemi
node/0, nodes/0, get_cookie/0, set_cookie/2,
~/.erlang.cookie
Cluster boot example
LIVE CODE UPGRADES
l (my_module)
code, code_server
weberp:upgrade/0
erlang releases
DEMO TIME: DISTRIBUTED WEBSOCKETS
DWS gen_servers:
dws_ets_table_manager
dws_service_broker
dws_session_server
Cowboy handlers:
dws_session_handler
dws_websocket_handler
Demo WebSocket API:
dws_service_example
DWS: DISTRIBUTED SESSIONS
Mnesia-powered session storage
all the rest is node-specific
(service broker per-API state [metrics or so],
websocket connection state,
etc.)
if the currently connected node dies,
the websocket client just reconnects
(to the same [restarted] or any other node)
DWS: let's CRASH!
unknown message to dws_session_server:
erl> dws_session_server ! foo.
unexpected message to dws_service_broker:
erl> dws_service_broker ! foo.
17:37:21.181 [info] dws_ets_table_manager: received ETS ownership request: {'ETS-TRANSFER',dws_service_broker_state,<0.911.0>,[]}
17:37:21.181 [info] dws_ets_table_manager: received ETS take-over request: {own,<0.20098.2>,dws_service_broker_state}
17:37:21.181 [info] dws_service_broker: received ETS ownership request: {'ETS-TRANSFER',dws_service_broker_state,<0.893.0>,reused}
...well, it crashed, gave the ETS table away, restarted and
got the ETS table back, so the state was preserved!
WHAT IF THE ENTIRE OS PROCESS DIED?
Then we have a heartbeat helper!
Just try to kill the BEAM VM running the DWS...
It will automatically restart in production mode
(not in 'console' mode).
Resources
LET'S GET IN TOUCH!
Lambda Meetup on Erlang/OTP: session #2
By Tomas Morstein
Lambda Meetup on Erlang/OTP: session #2
- 1,840