12

After reading two books, Programming Erlang (Joe Armstrong) and Programming Elixir (Dave Thomas), I have a few question about Erlang/Elixir in real world.

Q1: unifying backend development

I saw a table in a tech talk (I made a screenshot, but I forgot the source. If you know, please leave a comment):

+ ---------------------- + ------------------------- + --------- +
| Technical requirement  | Server A                  | Server B  |
+ ---------------------- + ------------------------- + --------- +
| HTTP Server            | Nginx & Phusion           | Elixir    |
| Request Processing     | Ruby on Rails             | Elixir    |
| Long Running Requests  | Go                        | Elixir    |
| Server-Side State      | Redis                     | Elixir    |
| Persistable Data       | Redis & Mongo             | Elixir    |
| Background Jobs        | Cron, Bash Scripts & Ruby | Elixir    |
| Service Crash Recovery | Upstart                   | Elixir    |
+ ---------------------- + ------------------------- + --------- +

Is that true? Is Erlang/Elixir so mature that it can handle all backend works?

If true, will this Erlang/Elixir code base be monolithic?

Q2: soft real-time

From Designing for Scalability with Erlang/OTP (Francesco Cesarini & Steve Vinoski):

If your system throughput is a million messages per second and a million simultaneous requests happen to be processed, it should take 1 second to process and deliver a request to its recipient. But if during a spike, two million requests are sent, there should be no degradation in the throughput; not some, but all of the requests should be handled within 2 seconds.

Can Erlang/Elixir really do that?

If my Erlang server (only on machine) can only handle 1M messages/sec and the request spike is 5M requests/sec, will almost all of the requests be handled within 5 seconds? How does Erlang work without a distributed environment? Why can't other backend tech do that (e.g. node.js)?

Q3: real-time scalability

Is there any available tech/tool/library/service or real case to scale up by adding Erlang nodes automatically when detecting request spikes, and scale down as soon as usage drops?

What are the tools suitable to manage deployment/monitoring/operation for Erlang/Elixir?

Q4: optimization

I know WhatsApp use Erlang to support their services. They did a lot of optimization on Erlang. Any info about this? If we need to optimize our Erlang services, how can we start it?

Xaree Lee
  • 3,188
  • 3
  • 34
  • 55
  • Can you format the table given in Q1 please. I don't understand Q1 as given. – Steve Pallen Apr 30 '17 at 18:12
  • 2
    I guess your questions are too broad and not very suitable for Q&A format. –  Apr 30 '17 at 18:21
  • To answer your questions, someone would need to write another book. – webdeb Apr 30 '17 at 18:26
  • FYI: The [table](https://twitter.com/sheharyarn/status/690675755525742592) is from @SasaJuric's [Elixir in Action](https://www.manning.com/books/elixir-in-action). – Sheharyar Nov 26 '18 at 03:52
  • Also, I actually did [ask him about the table](https://twitter.com/sasajuric/status/690677600864309250) a few years back. It's [based on a true story](https://twitter.com/sasajuric/status/690680184459124736) and also what inspired me to write the package [`que`](https://github.com/sheharyarn/que). – Sheharyar Nov 26 '18 at 03:59

1 Answers1

18

Answer to Q2.

Elixir and Erlang can handle the spikes because their web servers typically spawn a new Erlang process for each request. This is achievable because Erlang processes are much lighter than OS processes and threads. Many other languages use OS threads for concurrency and use polls to manage the limited resources on the host machine.

Most very modest servers can handle more than a million simultaneous processes. Since each request is a processes, each request is complete when it has been provided the required cpu resources to accomplish the request.

Process scheduling is Erlang is cooperative, not preemptive, allowing context switches to occur much faster than those in the OS. Finally, Elixir and Erlang use all cores on a CPU by default.

As long as the server is configured with enough memory and the number of processes startup variable is set appropriately, its very doable.

The Erlang VM was design for telecommunications systems to support concurrency for many phones. It was also design in the early days when memory and CPU was very limited compared to today.

Answer to Q1

TL;DR Yes, Elixir is mature enough

Elixir is build on the Erlang VM, which is very mature. It is the foundation for telecom switches that must support Many Nines Reliability. Since Elixir runs on the Erlang VM, if specific functionality is missing Elixir or an Elixir dependency, you can use Erlang directly from Elixir. As well, you can mix and match Elixir and Erlang packages in an Elixir Project. The same does when working with Erlang project.

The following points should address your table.

  • Elixir web apps work very well behind a Nginx or Apache reverse proxy
  • Elixir makes it very easy to write concurrent code making it suitable for Long running requests, using a load balancer to direct requests to either server A or B
  • Elixir supports Redis, Mongo, and many other backends. I've personally shared the same database tables between an app that was partially written in Rails and partially in Elixir's Phoenix Framework. I even shared the session data between both.
  • Elixir can be written in files for compiling (.ex extension) as well as for scripts (.exs) which makes it suitable for scripting. Elixir's concurrency model makes it very easy to program scheduled jobs without the need to use an external command line cron. Finally, Elixir has many build in libraries for File management and OS specific functionality.

An Elixir app, whether its a Web app, or a pure backend app, can be easily build stateful. Its built into the echo system and does not require any 3rd party APIs. Furthermore, a Phoenix web app, it first and foremost a stateful Elixir app with some additional components to assist in developing web apps. So, you get the ability to do things like periodically scheduling.

Just to be clear, when I say stateful, I mean that you can design your app to manage state. Variables in Elixir and Erlang are immutable. State needs to be managed through very controlled abstractions that are designed for concurrency. For example, you may choose to manage some central state with a GenServer. The only way to access/minulate that state is by passing an immutable message to the GenServer. And since receive messages to a particular process are serialized, the data access is concurrency safe.

Community
  • 1
  • 1
Steve Pallen
  • 4,417
  • 16
  • 33
  • 2
    Horizontal scaling is a much larger answer to the rather lengthy one I've already provided. I think you should google this. You many want to start with `distributed erlang` and work from there. Multi-Node mainly a function of the EVM. Elixir provides the support to work with local and remote processes. – Steve Pallen Apr 30 '17 at 19:08
  • About Q2, if a machine can only handle 1M requests/sec, what will Erlang server does when the spike is 2M~5M requests/sec? Will not the Erlang server drop those requests which it currently can't handle? – Xaree Lee May 01 '17 at 02:41
  • 1
    If the throughput is CPU bound, then incoming requests will will queue up in the server's inbox. Provided the server is configured to handle enough processes and memory, the EVM will handle the load. However, it the maximum number of processes is reached, incoming requests will be dropped. If the VM runs out of memory, the VM will crash. – Steve Pallen May 01 '17 at 02:51