|
| 1 | +# Elli - Overview |
| 2 | + |
| 3 | +Copyright (c) 2012-2016 Knut Nesheim, 2016-2018 elli-lib team |
| 4 | + |
| 5 | +__Version:__ 3.3.0 |
| 6 | + |
| 7 | +__Authors:__ Knut Nesheim, elli-lib team. |
| 8 | + |
| 9 | +Erlang web server for HTTP APIs |
| 10 | + |
| 11 | +## Features |
| 12 | + |
| 13 | +Here's the features Elli _does_ have: |
| 14 | + |
| 15 | +* [Rack][]-style request-response. Your handler function gets a |
| 16 | + complete request and returns a complete response. There's no |
| 17 | + messaging, no receiving data directly from the socket, no writing |
| 18 | + responses directly to the socket. It's a very simple and |
| 19 | + straightforward API. Have a look at [`elli_example_callback`](elli_example_callback.html) |
| 20 | +for examples. |
| 21 | + |
| 22 | +* Middlewares allow you to add useful features like compression, |
| 23 | +encoding, stats, but only have it used when needed. No features you |
| 24 | +don't use on the critical path. |
| 25 | + |
| 26 | +* Short-circuiting of responses using exceptions, allows you to use |
| 27 | + "assertions" that return for example 403 permission |
| 28 | + denied. `is_allowed(Req) orelse throw({403, [], <<"Permission |
| 29 | + denied">>})`. |
| 30 | + |
| 31 | +* Every client connection gets its own process, isolating the failure |
| 32 | +of a request from another. For the duration of the connection, only |
| 33 | +one process is involved, resulting in very robust and efficient |
| 34 | +code. |
| 35 | + |
| 36 | +* Binaries everywhere for strings. |
| 37 | + |
| 38 | +* Instrumentation inside the core of the webserver, triggering user |
| 39 | + callbacks. For example when a request completes, the user callback |
| 40 | + gets the `request_complete` event which contains timings of all the |
| 41 | +different parts of handling a request. There's also events for |
| 42 | +clients unexpectedly closing a connection, crashes in the user |
| 43 | +callback, etc. |
| 44 | + |
| 45 | +* Keep alive, using one Erlang process per connection only active |
| 46 | +when there is a request from the client. Number of connections is |
| 47 | +only limited by RAM and CPU. |
| 48 | + |
| 49 | +* Chunked transfer in responses for real-time push to clients |
| 50 | + |
| 51 | +* Basic pipelining. HTTP verbs that does not have side-effects(`GET` |
| 52 | + and `HEAD`) can be pipelined, ie. a client supporting pipelining |
| 53 | +can send multiple requests down the line and expect the responses |
| 54 | +to appear in the same order as requests. Elli processes the |
| 55 | +requests one at a time in order, future work could make it possible |
| 56 | +to process them in parallel. |
| 57 | + |
| 58 | +* SSL using built-in Erlang/OTP ssl, nice for low volume admin |
| 59 | +interfaces, etc. For high volume, you should probably go with |
| 60 | +nginx, stunnel or ELB if you're on AWS. |
| 61 | + |
| 62 | +* Implement your own connection handling, for WebSockets, streaming |
| 63 | + uploads, etc. See [`elli_example_callback_handover`](elli_example_callback_handover.html). |
| 64 | + |
| 65 | +## Extensions |
| 66 | + |
| 67 | +Here's some ready-to-use extensions for Elli. |
| 68 | + |
| 69 | +* [elli_access_log](https://github.com/elli-lib/elli_access_log): |
| 70 | +Access log |
| 71 | +* [elli_basicauth](https://github.com/elli-lib/elli_basicauth): |
| 72 | +Basic auth |
| 73 | +* [elli_chatterbox](https://github.com/elli-lib/elli_chatterbox): |
| 74 | +HTTP/2 support |
| 75 | +* [elli_cloudfront](https://github.com/elli-lib/elli_cloudfront): |
| 76 | +CloudFront signed URLs |
| 77 | +* [elli_cookie](https://github.com/elli-lib/elli_cookie): |
| 78 | +Cookies |
| 79 | +* [elli_date](https://github.com/elli-lib/elli_date): |
| 80 | +"Date" header |
| 81 | +* [elli_fileserve](https://github.com/elli-lib/elli_fileserve): |
| 82 | +Static content |
| 83 | +* [elli_prometheus](https://github.com/elli-lib/elli_prometheus): |
| 84 | +Prometheus |
| 85 | +* [elli_stats](https://github.com/elli-lib/elli_stats): |
| 86 | +Real-time statistics dashboard |
| 87 | +* [elli_websockets](https://github.com/elli-lib/elli_websocket): |
| 88 | +WebSockets |
| 89 | +* [elli_xpblfe](https://github.com/elli-lib/elli_xpblfe): |
| 90 | +X-Powered-By LFE |
| 91 | + |
| 92 | +You can also find a more complete list at <https://github.com/elli-lib>. |
| 93 | + |
| 94 | +## About |
| 95 | + |
| 96 | +From operating and debugging high-volume, low-latency apps we have |
| 97 | +gained some valuable insight into what we want from a webserver. We |
| 98 | +want simplicity, robustness, performance, ease of debugging, |
| 99 | +visibility into strange client behaviour, really good instrumentation |
| 100 | +and good tests. We are willing to sacrifice almost everything, even |
| 101 | +basic features to achieve this. |
| 102 | + |
| 103 | +With this in mind we looked at the big names in the Erlang |
| 104 | +community: [Yaws][], [Mochiweb][], [Misultin][] and [Cowboy][]. We |
| 105 | +found [Mochiweb][] to be the best match. However, we also wanted to |
| 106 | +see if we could take the architecture of [Mochiweb][] and improve on |
| 107 | +it. Elli takes the acceptor-turns-into-request-handler idea found |
| 108 | +in [Mochiweb][], the binaries-only idea from [Cowboy][] and the |
| 109 | +request-response idea from [WSGI][]/[Rack][] (with chunked transfer |
| 110 | +being an exception). |
| 111 | + |
| 112 | +On top of this we built a handler that allows us to write HTTP |
| 113 | +middleware modules to add practical features, like compression of |
| 114 | +responses, HTTP access log with timings, a real-time statistics |
| 115 | +dashboard and chaining multiple request handlers. |
| 116 | + |
| 117 | +## Aren't there enough webservers in the Erlang community already? |
| 118 | + |
| 119 | +There are a few very mature and robust projects with steady |
| 120 | +development, one recently ceased development and one new kid on the |
| 121 | +block with lots of interest. As Elli is not a general purpose |
| 122 | +webserver, but more of a specialized tool, we believe it has a very |
| 123 | +different target audience and would not attract effort or users away |
| 124 | +from the big names. |
| 125 | + |
| 126 | +## Why another webserver? Isn't this just the NIH syndrome? |
| 127 | + |
| 128 | +[Yaws][], [Mochiweb][], [Misultin][], and [Cowboy][] are great |
| 129 | +projects, hardened over time and full of very useful features for web |
| 130 | +development. If you value developer productivity, [Yaws][] is an |
| 131 | +excellent choice. If you want a fast and lightweight |
| 132 | +server, [Mochiweb][] and [Cowboy][] are excellent choices. |
| 133 | + |
| 134 | +Having used and studied all of these projects, we believed that if we |
| 135 | +merged some of the existing ideas and added some ideas from other |
| 136 | +communities, we could create a core that was better for our use cases. |
| 137 | + |
| 138 | +It started out as an experiment to see if it is at all possible to |
| 139 | +significantly improve and it turns out that for our particular use |
| 140 | +cases, there is enough improvement to warrant a new project. |
| 141 | + |
| 142 | +## What makes Elli different? |
| 143 | + |
| 144 | +Elli has a very simple architecture. It avoids using more processes |
| 145 | +and messages than absolutely necessary. It uses binaries for |
| 146 | +strings. The request-response programming model allows middlewares to |
| 147 | +do much heavy lifting, so the core can stay very simple. It has been |
| 148 | +instrumented so as a user you can understand where time is spent. When |
| 149 | +things go wrong, like the client closed the connection before you |
| 150 | +could send a response, you are notified about these things so you can |
| 151 | +better understand your client behaviour. |
| 152 | + |
| 153 | +## Performance |
| 154 | + |
| 155 | +"Hello World!" micro-benchmarks are really useful when measuring the |
| 156 | +performance of the webserver itself, but the numbers usually do more |
| 157 | +harm than good when released. I encourage you to run your own |
| 158 | +benchmarks, on your own hardware. Mark Nottingham has some |
| 159 | +[very good pointers](http://www.mnot.net/blog/2011/05/18/http_benchmark_rules) |
| 160 | +about benchmarking HTTP servers. |
| 161 | + |
| 162 | +[Yaws]: https://github.com/klacke/yaws |
| 163 | +[Mochiweb]: https://github.com/mochi/mochiweb |
| 164 | +[Misultin]: https://github.com/ostinelli/misultin |
| 165 | +[Cowboy]: https://github.com/ninenines/cowboy |
| 166 | +[WSGI]: https://www.python.org/dev/peps/pep-3333/ |
| 167 | +[Rack]: https://github.com/rack/rack |
0 commit comments