SF Scala Notes (2/2)

Erlang

Introduction

Erlang is a highly available fault tolerant framework that came
out of Ericson to support Telephony things. People like their phones to
work basically all of the time, so it's not surprising that the language
reflects these decisions.

Erlang Highlights

Declarative

  • An example of using Factorials
module(ex1).  
-export([factorial/1]).

factorial(1) ->  
1;  
factorial(N) when N >= 1 ->  
N * factorial(N-1).  

High Level Constructs make things like quicksort very simple operations on lists componetnts.

Has a bit level syntax which supports making bit level operations very easy to write.

Concurrent

Erlang processes are the erlang version of threads, and are incredibly low weight, each process takes only a few bytes.

The basic way to use concurrency is to use the spawn process.

Pid = spawn(ex3, activity, [report])  

Processes communicate by asynchronous message passing:
The sender will send a message

Pid ! {data, 12, 13}  

and a receiver will catch a process.

receive  
  {start} -> ....
  {stop} -> ....
  {data, X, Y} -> ....
end  

Acknowledgement has to be built explicitly into the protocol. Even
if the actor doesn't actually exist, it won't throw an error, so you
have to build a response/acknowledgement into the code explicitly.

Robust

Simple and consistent error recovery through Supervision hierarchies leads to very high availability. Most of these constructs come from the telephony mindset around availability/uptime paranoia and are reflected in the main standard library, the OTP framework.

Cooperating processes may be linked together explicitly, and when one quits, it may propagate the crashing to other depdent actors. However, exit signals can also be trapped, and then processing/code can be used to figure out the correct way to respond to the error.

These primitives can be combined into combinations of supervisors and workers. The actors are layered into trees.

Distributed

Explicit or transparent distribution. There's also a network aware runtime system, where message that need to be sent to nodes across the network, they can be transparently handled by the runtime, converted into a serialized network form, and then processed on
the other end.

Hot Code Loading

Suppose you have some module which has a piece of code that's currently running. Then a new verison of that module can be brough into the same runtime system, and then as soon as a new process is created, the new code will run on the new system.

There's also grabage collection of modules. After the new code is out, the old code will be eventually removed.

Multicore support

SMP provides "Linear scalability" out of the box that to it's no shared memory approach to conurrency. The approach to erlang concurrency gives us this basically for free.

One of the big distinctions with multicore erlang, each process has it's own garbage collector. If you have a bunch of processes, where each one is dealing with a little data, then you don't end up with stop the world garbage collection.

OTP

The Open Telecom Platform is really the full erlang distribution.

Design principles are implemented as code: gen_server, FSMs, supervisors, applications, etc. are included in the OTP. It's also fully documented with reference docs and user guides.

Tools: Mnesia, Dialyzer, Observer, Eunit, EDoc, etc.

Fully Documented: reference docs, user guides etc.

The Mtyh's of Erlang

I Wrote my Erlang System in 4 weeks!

  • Is it Documented
  • Is the developer supporting it.
  • SNMP
  • Live Tracing etc.

Upgrades during runtime are easy!

Actually easy for

  • It's easy for simple patches
  • adding functionality without changing the state.

Non backwards compatible changes need time.

  • Database schema changes
  • State changes in your process
  • Upgrades in distributed environments

Testing is really quite difficult.

Nine 9's is standard

5 9's is achievable though, at a fraction of the effort of Java/C+

Erlang Best practices

Follow OTP

There's 20 years of the absolute best development and incorporation of solid design.

Let it Crash

Your code will crash anyway; why not plan for it?

Isolate crashing components, let them reset to a known state,
log the errors and debug at your own pace, and watch out for thrashing.

Synchronization in a distributed system is hard

#include "EveryDistributedSystemsTalkHere"

Dynamic Scalability

  • If your system is bsuy, it'll need to grow.
  • If the system is consistently idle, you may want to contract
    • New systems have empty caches.
    • Old systems receiving new data also means cache-misses.

(Riak is one type of tool that can help. You can also use riak for doing dynamic scalability of things that aren't databases. )

Use Processes Freely

  • One role == One Process
  • One loop of process is ina single module.

Monitoring is key

It's very important to monitor many things so that you can understand
your steady state. It's important to see things at VM/hosts/network.

Book suggestions

Programming Erlang - Second Edition

Erlang Programming

Erlang and OTP in action