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
Elixir/Phoenix
- 1,064