Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Concurrency, Robustness and Elixir
SoCraTes 2015
Erlang About Erlang
What is Erlang?
Erlang is ...
●
A programming language (Concurrent, Functional)
●
A virtual machine (l...
Elixir The Elixir project
What is Elixir?
Elixir is a functional, concurrent, general-purpose programming language built a...
Erlang Computing challenges of the 21st century
4004
8080
186
286
i386
i486
P5 Pentium
P6
P7
Core
Nehalem
Ivy Bridge
Haswe...
Concurrent
programming
in Elixir
Elixir The Actor model
Process
Mailbox
Msg 1
Msg 2
Msg 3
defmodule ListenerServer do
use GenServer
def init(args) do
Proce...
Elixir The Actor model
Process
Spawn
Send/
Receive
Mailbox
Msg 1
Msg 2
Msg 3
defmodule ListenerServer do
use GenServer
def...
Elixir Actors in Elixir
Erlang / Elixirs key feature: Packing code into small chunks that can be run
independently and con...
Elixir OOP versus COP
Object oriented programming Concurrent oriented programming
Class Actor
Instance Process
Instantiati...
pid = spawn function # Start a new process, return its PID
send pid, message # Send message to process with pid
receive do...
defmodule Listener do
def listen do
receive do
:quit -> exit(nil)
message -> IO.puts "Got the message '#{message}'"
end
li...
defmodule Listener do
def listen do
receive do
:quit -> exit(nil)
{message, from} -> IO.puts "Got the message '#{message}'...
defmodule Listener do
def start do
Process.register self, :listener
listen
end
def listen do
receive do
:quit -> exit(nil)...
Elixir Process behaviours
Task Asynchronous calculation
Agent State-carrying process
GenServer Generic OTP Server
Supervis...
Elixir Tasks and Agents
# Start an independent task
task = Task.async(fn -> do_some_work() end)
# Collect the result
resul...
line = "Freude schöner Götterfunken"
task = Task.async(fn -> String.upcase(line) end)
IO.puts Task.await(task)
task = Task...
Elixir Generic Server Callbacks
defmodule MyServer do
use GenServer
# Initialize server
def init(args), do: {:ok, state}
#...
defmodule ListenerServer do
use GenServer
# Public API
def start_link, do: GenServer.start_link ListenerServer, []
# Callb...
defmodule ListenerServer.Supervisor do
import Supervisor.Spec
def start do
children = [ worker(ListenerServer, [], restart...
defmodule FirstEventHandler do
use GenEvent
def handle_event(message, state) do
IO.puts "The first event handler was notif...
defmodule FiniteStateMachine do
@behaviour :gen_fsm
def start_link(_opts) do
:gen_fsm.start_link({:local, FSM}, __MODULE__...
Elixir OTP
Super-Supervisor
Supervisor Supervisor
Supervisor
Worker Worker Worker
Worker
Worker Worker WorkerHelper Helper...
defmodule ExampleApp do
use Application
def start(_type, _args) do
MainSupervisor.start
end
end
Elixir Elixir application ...
# Starts the BEAM Erlang Virtual Machine
# and the EPMD Erlang Port Mapper Daemon (default port 4369)
cluster01> elixir --...
Nächste SlideShare
Wird geladen in …5
×

Concurrency, Robustness & Elixir SoCraTes 2015

638 Aufrufe

Veröffentlicht am

Slides from the session "Concurrency, Robustness & Elixir" at SoCraTes 2015, Soltau

Veröffentlicht in: Software
  • Als Erste(r) kommentieren

Concurrency, Robustness & Elixir SoCraTes 2015

  1. 1. Concurrency, Robustness and Elixir SoCraTes 2015
  2. 2. Erlang About Erlang What is Erlang? Erlang is ... ● A programming language (Concurrent, Functional) ● A virtual machine (lightweight, massively concurrent, asynchronous) ● An ecosystem (OTP, design patterns and libraries for building robust systems) ● Developed since 1986, Joe Armstrong et al (Ericsson) ● Open Source since 1998 ● Initially used for telephone switches ● Now for many other applications requiring High Availability & distributed concurrency: ➔ ejabberd ➔ CouchDB ➔ GitHub
  3. 3. Elixir The Elixir project What is Elixir? Elixir is a functional, concurrent, general-purpose programming language built atop the Erlang Virtual Machine. ● Full compatibility with the Erlang universe, compiles to Erlang bytecode ● Refurbished syntax (Ruby inspired) ● Aims for enhanced productivity (better build tools, less boilerplate) ● Extensibility (Structs, Protocols, DSLs -> Clojure inspired) Quite young -> First commit Jan 9, 2011 Current version 1.0.5 http://elixir-lang.org/
  4. 4. Erlang Computing challenges of the 21st century 4004 8080 186 286 i386 i486 P5 Pentium P6 P7 Core Nehalem Ivy Bridge Haswell 0.1 1 10 100 1000 10000 MHz Clock speed limit Multicore Clustering & Cloud High availability
  5. 5. Concurrent programming in Elixir
  6. 6. Elixir The Actor model Process Mailbox Msg 1 Msg 2 Msg 3 defmodule ListenerServer do use GenServer def init(args) do Process.register self, :listener {:ok, []} end def handle_cast(:quit, state) do {:stop, :normal, state} end def handle_cast(message, state) do IO.puts "Got the message '#{message}'" {:noreply, state} end end Behaviour { state }
  7. 7. Elixir The Actor model Process Spawn Send/ Receive Mailbox Msg 1 Msg 2 Msg 3 defmodule ListenerServer do use GenServer def init(args) do Process.register self, :listener {:ok, []} end def handle_cast(:quit, state) do {:stop, :normal, state} end def handle_cast(message, state) do IO.puts "Got the message'" {:noreply, state} end end Behaviour {state}
  8. 8. Elixir Actors in Elixir Erlang / Elixirs key feature: Packing code into small chunks that can be run independently and concurrently. Actor Model: ● Independent asynchronous processes ● Share nothing with other processes ● Communication only via messages ● Messages are stored in the process mailbox until consumed ● A process can create new processes ● Processes have an inner state Elixir processes ... ● Aren't system threads or processes. ● Managed by the Erlang Virtual Machine ● Extremely light-weight, nearly no overhead to create one. ● Even a modest computer can run > 100000 Elixir processes. ● Can be changed at run-time (hot-code swapping)
  9. 9. Elixir OOP versus COP Object oriented programming Concurrent oriented programming Class Actor Instance Process Instantiation Spawn Constructor Initializer Prototype Behaviour Setter/Getter Message Interface Protocol Attribute State Singleton Registered process
  10. 10. pid = spawn function # Start a new process, return its PID send pid, message # Send message to process with pid receive do # Try to match messages in process mailbox match1 -> result1 match2 -> result2 ... after timeout -> result # Result when no message arrived in timeout end self # Process ID of current process Process.list # List all running processes flush # (iex) Flush mailbox, print all messages :pman.start # Start Erlang process manager Elixir Concurrent programming
  11. 11. defmodule Listener do def listen do receive do :quit -> exit(nil) message -> IO.puts "Got the message '#{message}'" end listen end end listener = spawn fn -> Listener.listen end send listener, "Hello World" send listener, :quit Elixir Process programming
  12. 12. defmodule Listener do def listen do receive do :quit -> exit(nil) {message, from} -> IO.puts "Got the message '#{message}'" send from, "Thank you for the message!" end listen end end listener = spawn fn -> Listener.listen end send listener, {"Hello World", self} flush send listener, :quit flush Elixir Process programming
  13. 13. defmodule Listener do def start do Process.register self, :listener listen end def listen do receive do :quit -> exit(nil) message -> IO.puts "Got the message '#{message}'" end listen end end spawn fn -> Listener.start end send :listener, "Hello World" send :listener, :quit Elixir Process registering
  14. 14. Elixir Process behaviours Task Asynchronous calculation Agent State-carrying process GenServer Generic OTP Server Supervisor OTP Supervisor Application OTP Application GenEvent Generic Event Handler :gen_fsm Generic Finite State Machine
  15. 15. Elixir Tasks and Agents # Start an independent task task = Task.async(fn -> do_some_work() end) # Collect the result result = Task.await(task) Tasks: Independent asynchronous calculations # Start a new agent {:ok, agent} = Agent.start(fn -> initial_state end) # Update the agent state Agent.update(agent, fn old_state -> new_state end) # Get the current agent state Agent.get(agent, fn state -> value end) # Terminate the agent Agent.stop(agent) Agents: Wrappers around state
  16. 16. line = "Freude schöner Götterfunken" task = Task.async(fn -> String.upcase(line) end) IO.puts Task.await(task) task = Task.async(fn -> :timer.sleep(3000); String.upcase(line) end) IO.puts "Waiting for the task to complete..." IO.puts Task.await(task) Elixir Task and Agent example {:ok, agent} = Agent.start(fn -> 0 end, [name: :counter]) IO.puts Agent.get(:counter, fn value -> value end) Agent.update(:counter, fn value -> value+1 end) IO.puts Agent.get(:counter, fn value -> value end) Agent.stop(:counter)
  17. 17. Elixir Generic Server Callbacks defmodule MyServer do use GenServer # Initialize server def init(args), do: {:ok, state} # Terminate server def terminate(reason, state), do: {reason, state} # Call with reply def handle_call(msg, from, state), do: {:reply, reply, new_state} # Casts without reply def handle_cast( msg, state ), do: {:noreply, new_state} # All other messages def handle_info( msg, state ), do: {:noreply, new_state} # Hot code swap def code_change( vsn, state, extra ), do: {:ok, new_state} end
  18. 18. defmodule ListenerServer do use GenServer # Public API def start_link, do: GenServer.start_link ListenerServer, [] # Callback functions def init(args) do Process.register self, :listener {:ok, []} end def handle_cast(:quit, state) do {:stop, :normal, state} end def handle_cast(message, state) do IO.puts "Got the message '#{message}'" {:noreply, state} end end {:ok, pid} = ListenerServer.start_link GenServer.cast :listener, "Hello" GenServer.cast :listener, :quit Elixir Generic Server
  19. 19. defmodule ListenerServer.Supervisor do import Supervisor.Spec def start do children = [ worker(ListenerServer, [], restart: :transient) ] Supervisor.start_link(children, strategy: :one_for_one) end end ListenerServer.Supervisor.start GenServer.cast :listener, "Hello" GenServer.cast :listener, {1,2,3} # Crashes the listener server GenServer.cast :listener, "Hello World" GenServer.cast :listener, :quit Elixir Supervision
  20. 20. defmodule FirstEventHandler do use GenEvent def handle_event(message, state) do IO.puts "The first event handler was notified: '#{message}'" {:ok, state} end end defmodule SecondEventHandler do use GenEvent def handle_event(message, state) do IO.puts "The second event handler was notified: '#{message}'" {:ok, state} end end GenEvent.start_link(name: :eventmanager) GenEvent.add_handler(:eventmanager, FirstEventHandler, nil) GenEvent.add_handler(:eventmanager, SecondEventHandler, nil) GenEvent.notify(:eventmanager, "Hi there!") Elixir Event Handler
  21. 21. defmodule FiniteStateMachine do @behaviour :gen_fsm def start_link(_opts) do :gen_fsm.start_link({:local, FSM}, __MODULE__, [], []) end def next_state() do :gen_fsm.send_event(FSM, :round) end def init(_), do: IO.puts "FSM started"; { :ok, :ping, [] } def ping(:round, state), do: IO.puts "Ping!"; {:next_state, :pong, state} def pong(:round, state), do: IO.puts "Pong!"; {:next_state, :ping, state} end FiniteStateMachine.start_link [] # "FSM started" FiniteStateMachine.next_state # "Ping!" FiniteStateMachine.next_state # "Pong!" FiniteStateMachine.next_state # "Ping!" FiniteStateMachine.next_state # "Pong!" Elixir Finite state machine
  22. 22. Elixir OTP Super-Supervisor Supervisor Supervisor Supervisor Worker Worker Worker Worker Worker Worker WorkerHelper Helper Application
  23. 23. defmodule ExampleApp do use Application def start(_type, _args) do MainSupervisor.start end end Elixir Elixir application project Build tool mix: > mix new exampleapp mix.exs # Mix project definition file /config/config.exs # Project specific configuration /lib/ # Source code /test/ # Tests suites
  24. 24. # Starts the BEAM Erlang Virtual Machine # and the EPMD Erlang Port Mapper Daemon (default port 4369) cluster01> elixir --sname node --no-halt --cookie secret_cookie Elixir Distributed computing: Nodes # Elixir master node (on same subnet as cluster nodes) master> iex --sname masternode --cookie secret_cookie Node.connect :"node@cluster01" # Establish node connection pid = Node.spawn :"node@cluster01", func # Spawn a process Node.self # Name of current node Node.list # List all connected nodes

×