Elixir/Phoenix

Monolith |> microservices

@elixirlang / elixir-lang.org

Erlang

Web

Elixir

Elixir is a dynamic, functional language designed for building scalable and maintainable applications.

Elixir

  • Scalability

  • Fault-tolerance

  • Extensibility and DSLs

  • Tooling

  • Interactive development

  • Erlang compatible

Scalability

current_process = self()

# Spawn an Elixir process (not an operating system one!)
spawn_link(fn ->
  send current_process, {:msg, "hello world"}
end)

# Block until the message is received
receive do
  {:msg, contents} -> IO.puts contents
end

Scalability

  • Due to their lightweight nature, it is not uncommon to have hundreds of thousands of processes running concurrently on the same machine.

  • Isolation allows processes to be garbage collected independently, reducing system-wide pauses, and using all machine resources as efficiently as possible (vertical scaling).

  • Processes are also able to communicate with other processes running on different machines in the same network. This provides the foundation for distribution, allowing developers to coordinate work across multiple nodes (horizontal scaling).

Fault-tolerance

children = [
  TCP.Pool,
  {TCP.Acceptor, port: 4040}
]

Supervisor.start_link(children, strategy: :one_for_one)

The unavoidable truth about software running in production is that things will go wrong.

Supervisor

A supervisor is a process which supervises other processes, which we refer to as child processes. Supervisors are used to building a hierarchical process structure called a supervision tree. Supervision trees provide fault-tolerance and encapsulate how our applications start and shutdown.

Supervisor strategies

  • :one_for_one

  • :one_for_all

  • :rest_for_one

  • :simple_one_for_one

Extensibility and DSLs

Tooling features

Elixir ships with a great set of tools to ease development. Mix is a build tool that allows you to easily create projects, manage tasks, run tests and more

$ mix new my_app
$ cd my_app
$ mix test
.

Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 tests, 0 failures

Tooling features

Interactive development

Tools like IEx (Elixir’s interactive shell) are able to leverage many aspects of the language and platform to provide auto-complete, debugging tools, code reloading, as well as nicely formatted documentation:

$ iex
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex> h String.trim           # Prints the documentation for function
iex> i "Hello, World"        # Prints information about the given data type
iex> break! String.trim/1    # Sets a breakpoint in the String.trim/1 function
iex> recompile               # Recompiles the current project on the fly

Erlang compatible

iex> :crypto.hash(:md5, "Using crypto from Erlang OTP")
<<192, 223, 75, 115, ...>>

Some other cool stuff

# Egar vs Lazy

iex> 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum
7500000000


iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?) |> Enum.sum
7500000000


# Pipe vs no pipe

iex> 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum
7500000000

iex> Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?))
7500000000

Phoenix

How is Phoenix Different

​Phoenix brings back the simplicity and joy in writing modern web applications by mixing tried and true technologies with a fresh breeze of functional ideas.

How is Phoenix Different

  • Phoenix Channel (Web socket)
  • Ecto (Database layer)
  • Context (Code structure)

Umbrella Projects

Monolith or Microservices?

$ mix new myproject_umbrella --umbrella
* creating .gitignore
* creating README.md
* creating mix.exs
* creating apps
* creating config
* creating config/config.exs
$ cd myproject_umbrella/apps
$ mix new myproject_api_server --sup
* creating .gitignore
* creating README.md
* creating mix.exs
* creating apps
* creating config
* creating config/config.exs
* creating test

$ mix new myproject_data_processing --sup
* creating .gitignore
* creating README.md
* creating mix.exs
* creating lib
* creating config
* creating config/config.exs
* creating test
+ myproject_umbrella
  + apps
    + myproject_api_server
    + myproject_data_processing

Deployment

$ mix release.init # As one monolith app


release :myproject do
  set version: "0.1.0"
  set applications: [:myproject_server_api, :myproject_data_processing]
end

Using Distillery

Deployment

$ mix release.init --release-per-app # release each sub app individually


release :myproject_server_api do
  set version: "0.1.0"
  set applications: [:myproject_server_api]
end

release :myproject_data_processing do
  set version: "0.1.0"
  set applications: [:myproject_data_processing]
end

Using Distillery

Monolith

    |> Umbrella

            |> Microservices

The Happy Path

Thank you!

@tian_yi_wang

Elixir/Phoenix

By Tianyi Wang