Skip to content

Comment on Show HN: Aqueduct – Dart on the Server

Comments

jcstkOP

Aqueduct is a server-side framework for building and deploying REST applications. It is written in Dart. Its goal is to provide an integrated, consistently styled API.

The framework contains behavior for routing and authorizing HTTP requests, persisting data in PostgreSQL, testing, and more.

One thing that makes Aqueduct really interesting is that it runs the application on a few isolated-memory threads. This is a concept interpreted from the Erlang/Elixir that leverages Dart 'Isolate's. (Here's some documentation on that: https://aqueduct.io/docs/http/structure/)

The aqueduct command-line tool serves applications, manages database schemas and OAuth 2.0 clients, and generates OpenAPI specifications.

The project seems really interesting but I'm struggling to understand what the key benefits would be over other frameworks (Rails, Node, etc.)

Related question: Is multi-threading accomplished via these Isolates, or is there a threading model within each Isolate too?

Thanks!

jcstkOP

Good questions, thank you. Aqueduct initially started as a proof of concept - as a mobile shop, Dart was just so familiar to the languages we often used and it ran on the server. We tried building a few things and everyone was able to pick it up so quickly, and it took off internally from there. The value to us as mobile developers is that there was less context switching than when jumping into Ruby or JS (and all the other reasons we aren't quite fans of JS.)

Yes, multi-threading is accomplished through isolates. The application is run as a replica on a number of isolates, configurable by a command line option.

Each isolate has its own database connection, etc., but operate exactly the same. This behavior doesn't require any additional effort by the developer. (edit: The initialization code sets up a reactive channel for requests, each isolate instantiates that channel, and Dart's VM manages delivering an HTTP request to the most appropriate isolate.)

So, it's not quite like Erlang/Elixir where each connection gets its own process, rather the default number of isolates is 3. Isolates have their own heap, so memory isn't shared across them, but there is a message hub that isolates can send values across. This is useful when say you have websockets connected to different isolates and you want to broadcast a message to all of them.

You can spawn additional isolates from a 'web server isolate' to move computation to another thread.

Can an isolate handle multiple requests at once? (For example, suppose there are lots of cheap requests, so it's I/O bound, not CPU bound.)

How much extra memory usage is there per isolate?

An isolate is really just like a separate runtime, running in a separate thread. It's a language provided convenience (with some inter-isolate communication facilities but no shared memory). Think of it as running multiple node or python interpreter instances but with less hassle.

Yep, I was asking how Aqueduct is using them.

jcstkOP

For a bit more detail:

The main isolate creates an Application instance that has N number of supervisors, one for each isolate. The isolates are launched and go thru their initialization steps, reporting back to their supervisor. The application completes its launch once all supervisors have reported back. It fails its launch if an isolate throws an error during initialization or does not hear back in a configurable timeout. Any inter-isolate messages sent during startup are queued until all isolates have completed startup.

Once the isolates are up and running, the main isolate doesn't do anything other than facilitate the inter-isolate message hub. Requests are delivered directly to the isolates running the web server.

When running automated tests, the default behavior is to run everything on the main isolate, since tests are run against a temporary database schema that only exists for the lifetime of the connection.

jcstkOP

Yup! Each isolate has its own event loop... and I'll do a terrible job explaining that as its late in the day, so I included a reference link [1].

The memory consumption of an isolate depends on the size of the application code. Each isolate actually has its own copy of the application code that gets tuned by the VM over time. Even stuff like static variables are per-isolate. I just pulled up an OK sized Aqueduct project, and it looks like about 30-40MB per isolate. Most of that is probably Aqueduct itself. A worker isolate is likely an order of magnitude smaller.

1: https://webdev.dartlang.org/articles/performance/event-loop

jcstkOP

(And we'd also really love to hear any critical feedback.)

Whats your perspective of the activity around the Dart VM? Is Google actively maintaining it? As a JS dev I always wrote it off as being a non-starter, but your project has intrigued me to taking a second look at the VM. Thanks!

The Dart VM team is super active. If you are a VM geek this group[1] is a good way to follow what is going on.

Dart now targets the Web (two compilers - one for development, one for "production" - both transpiling to JS), the server (Dart server VM - fast native JIT VM), Mobile via flutter (support for AOT on iOS), and Fuchsia.

[1] https://groups.google.com/a/dartlang.org/forum/?fromgroups=#...

jcstkOP

Good question - yeah, the VM is actively maintained. All of the tooling for the Dart ecosystem runs on the VM, Flutter is a Dart VM project, too.

The changelog [1] always has a few entries for the Dart VM with each version, but it's quite clear from using it daily that much more is happening. Some notable recent improvements have been asynchronous breakpoints that are integrated in IntelliJ's debugger and some optimizations for sending messages across isolates.

1: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md

notable recent improvements have been asynchronous breakpoints that are integrated in IntelliJ's debugger and some optimizations for sending messages across isolates.

Where did you get that info? I haven't seen it in the changelog. Is message passing using structured cloning?

jcstkOP

Just through observation. Breakpoints just started to work and a pesky race condition between isolates became reproducible.

Since this is targeted a developers, it's worth looking at the intro pages of similar tools - flask and spark come to mind but there are others in the same vein. The slideshow with vague verbiage which is often not obviously related to the code being shown just doesn't make any sense.

"Compose modular maintainable code" or "Achieve the productivity of a cohesive framework" doesn't really say anything at all - you can replace that whole thing with a random code snippet and a big title that says "Aqueduct - now, more than ever!".

jcstkOP

Thanks for the great feedback. I wondered about that as well - as you can probably tell, I'm neither a good marketer or a good web developer.

The 'cohesive framework' one made sense in my head - the ORM and the HTTP stuff work together so that errors thrown by the ORM are translated into the appropriate status codes without having to catch the exception. I can see how just reading that may make no sense.

I'll check out the webpages for both Flask and Spark and adjust accordingly. The real info for developers is at https://aqueduct.io/docs anyhow.

I have a general question about Dart and would appreciate any thoughts.

How have you found Dart as a server-side language? What's the performance like and the ease of development?

First impressions of Dart are positive. However, the server-side (interpreted) language landscape is dominated by Python, Ruby, PHP etc. Any thoughts on choosing Dart for server-side programming over these other common languages and what you think the advantages are? Many thanks.

jcstkOP

Sure thing. As a server-side language, love it. I also do all my command-line scripting with it, too.

Async/await is implemented really well (Google hired Erik Meijer to help them build it), their threading model is excellent, and there are built-in keywords in the language for stream handling that are seriously productive [1]. Anyone that knows Java/Swift/Kotlin/ObjC is going to be productive in Dart very, very quickly.

Performance has been great, but someone else may be better qualified to answer that question. Much of the lower level socket stuff is just C/C++. I don't want to speak on something I don't fully understand, so I included an article about the Dart VM below [2].

To me, Dart differentiated itself by being more similar to compiled, C-like languages. Obviously, Django, Laravel, Rails, etc. are much more mature. Aqueduct is tested well [3], but nothing beats years of regression tests.

1: https://www.dartlang.org/articles/language/beyond-async 2: https://www.dartlang.org/articles/dart-vm/why-not-bytecode 3: https://github.com/stablekernel/aqueduct

Thank you for sharing your project.

I am unable to read the examples on the homepage as they scroll by too fast. Could you please do both of: increase the time each example stays on screen; and disable the automatic scrolling if the user makes an effort to select a particular example either by clicking the side arrows or the selector tabs on the bottom.

jcstkOP

Thanks, good idea and will definitely do that.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.