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.
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.
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!".
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.
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.
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!
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.
> 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?
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.
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.
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.
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.
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.
Looks promising. But didn't see anywhere in the docs how does this work.
* What's the underlying server?
* Does it transpile to Node.js?
* How does the third party module system work?
* Which are other readymade libraries that can be used with this?
It runs directly on the Dart VM, which has its own HTTP server implementation. That's the interesting thing about the Dart VM - it's a C++ executable with no ties to JS. Third party modules may be provided by through Dart's package manager, https://pub.dartlang.org.
It's command-line tool runs the application, but there isn't much from stopping you from just using the `dart` command line tool and a Dart script to start it.
edit: Basically, you can run this on any machine that can install Dart.
So Dart has a few different compilation targets: JavaScript for building front-end web apps and the Dart VM [1]. There's also some work being done for other compilation targets, specifically for faster development cycles when doing front-end web stuff.
The interesting thing about the Dart VM is there's no JavaScript at all. You can even link to C and C++ code from Dart.
I love flutter/dart, and have some little experience with Java + servers/microservices... So my question is how is GC trashing handled? e.g. if it becomes > some percentage of the running time are isolates "killed/restarted" (if that makes senses, or the whole process)?
When running `wrk` to do performance testing and monitoring in Observatory [1] and with anything we have in production, I haven't seen an Isolate or the process ever die. This may be a question better suited for the Dart VM team, I'll see if I can't ping someone.
And yeah, as a native iOS developer for many years, I finally sat down and built something in Flutter this weekend and really liked it.
33 comments
[ 634 ms ] story [ 356 ms ] threadThe 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.
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.
"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!".
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.
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.
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
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
Where did you get that info? I haven't seen it in the changelog. Is message passing using structured cloning?
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=#...
Related question: Is multi-threading accomplished via these Isolates, or is there a threading model within each Isolate too?
Thanks!
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.
How much extra memory usage is there per isolate?
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.
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
It's command-line tool runs the application, but there isn't much from stopping you from just using the `dart` command line tool and a Dart script to start it.
edit: Basically, you can run this on any machine that can install Dart.
The interesting thing about the Dart VM is there's no JavaScript at all. You can even link to C and C++ code from Dart.
1: Here's a discussion on how the Dart VM is implemented: https://groups.google.com/a/dartlang.org/forum/#!topic/misc/...)
And yeah, as a native iOS developer for many years, I finally sat down and built something in Flutter this weekend and really liked it.
1: https://dart-lang.github.io/observatory/
An HTTP request for /files/xyz.jpg returns the something_else/xyz.jpg.
If the HTTP path is a directory, then index.html is automatically appended to it. This is a brief overview of the referenced documentation above.
Never mind, I was readding wrong.