Combining this with languages like ruby, clojure, and scala seems like a definite win.
Async-by-default doesn't seem like a great model for programming the server-side part of most things that are done over HTTP. Three use cases jump out at me:
2. Threads are scary.
3. You want to make certain actions asynchronous over HTTP (i.e. client says "start", then server maybe says "done" later).
Now consider Clojure:
2. Clojure makes a lot of threaded operations pretty non-scary. Its native data structures are all immutable and it has constructs for concurrent state. These are not any harder to work with than the async/callback model. I find it more natural, but I'm used to Clojure so that could be bias.
3. Async-when-desired is already easy in Clojure. Futures provide a very easy way to do stuff in a thread pool without blocking. Agents provide the same thing for state changes. It really is as easy as (future do-blocking-thing) and (send-off an-agent do-blocking-thing some-args).
What all the JVM Node.js clones are missing and what Node.js sets apart are async libraries. There is no async (MySQL) JDBC driver for starters. If your IO drivers are not async, your async container is not very useful in real life.
Python, Ruby and Perl all have the same cultural tolerance for blocking code. The Node.js community has a complete lack of tolerance for blocking code.
I work with the JVM every day (Clojure) and wish it was different wrt the common use of non-blocking code, but it's going to be a long road to get there on the JVM.
Netty's entire model is asynchronous, and Java 7 now has AsynchronousChannels for IO which, I assume, Netty will make use of.
All in all, the JVM has a much more solid and performant foundation than anything Node can provide. The whole difference will come down to a programming style preference. I am not entirely sure why Vert.x adopted the Node style rather than the proven servlet container, as I'm sure both styles provide comparable performance. I guess each may shine under different loads/usage patterns (my guess is that Vert.x/Node can squeeze more performance from a single thread, but servlets are more scalable).
If you are dealing with something where you don't know what the wire protocol is and you just have a blocking client library to play with (e.g. JDBC - JDBC is, by definition blocking - see the JDBC API), then you can't do much but to wrap the blocking api in an async facade and limit the number of threads that block at any one time.
This is exactly what we do in vert.x. We accept the fact that many libraries in the Java world are blocking (e.g. JDBC) so we allow you to use them by running them on as a worker.
This is one area where we differ from node.js. Node.js makes you run everything on an event loop. This is just silly for some things, e.g. long running computations (remember the Fibonacci number affair?), or calling blocking apis.
With vert.x you run "event-loopy" things on the event loop but you can run "non event-loopy" things on a worker. It's a hybrid.
(notice the Connect method on line 325 of binding.cc)
At some level a client-server database driver isn't all that different from any other network client; you send a request over a socket and wait for a result. There's no reason you have to block while waiting.
Moreover some databases (like Postgres) let you receive asynchronous notifications signaled by transactions on other connections; that's how trigger-based replication systems like Bucardo do their thing.
There are two main things that block in computing:
You better believe that Node blocks on CPU, so what I/O does Node not block on that Twisted does?
You get tons of Java libs to use, a majority of blocking ones and lots of non blocking on one hand, or you restrict yourself to the fewer non-blocking libs of varying quality available for Node.
With Java you can also turn blocking libs to non blocking with a wrapper and threads, whereas with Node.js if it's blocking you're screwing, because the js engine is single-threaded.
It's trivial to offload blocking operations to other processes in node too, it's just not the preferred option.
And ruby has 38237 gems. 99,9% of which are garbage.
Library-count is a terrible metric.
Whatever libraries node has is a drop in the bucket compared to java.
BUT: I assume people will move to backend services with REST and combining REST backend results to a page. This increases IO a lot and will kill your latency and default thread models when you do sync code. You'd need to use async IO, composeable futures to manage latency and thread count. And if you do async backend REST, why not do async JDBC etc. But there are no libraries.
Really? So they reject any kind of library that does anything except call a callback? Because everything else, from calculating 2+2 to creating a template blocks. And it doesn't matter when it happens, when it happens it blocks.
What async containers like Netty (and by proxy, Vert.x) solve is high-latency cases like long polling and file upload/download. Netty for one does have support for zero-copy file transfers: http://docs.jboss.org/netty/3.2/xref/org/jboss/netty/example...
In my experience, these are a small percentage of cases so the majority of the app can use blocking I/O -- even long-polling code, as long as you are using the async framework for the client connection.
"Protocol-agnostic RPC System" does not sound like a node clone at all.
Finagle is about composing async IO calls, e.g. here
This works much better in Scala, as Java is not very good at composing Futures. It needs a lot of boiler plate code as it lacks noise free closures.
Would you call Node.js's MySQL drivers "production quality"?
As far production is concerned, they might as well be the same thing.
>BTW there are hundreds of node apps in production.
Do they use some of Node's MySQL drivers though? For they (or their lack thereof) was the topic of this subthread.
transloadit.com, from the module mantainers, has been using it for an year+. I don't have any magic insight into what modules sites use, but judging from the activity in their repo it's quite popular (~1000 watchers, 100+ forks): https://github.com/felixge/node-mysql
Looking through the docs, the main difference I see is that this is opting for a comparatively heavy-core approach which contrasts with Node's ruthless minimalism + third-party modules.
-file system access is convoluted with HTTP handling: req.response.sendFile()
-pieces of web framework functionality by default, but no full solution (RouteMatcher)
-integrated WebSockets with a novel but unconventional accept/reject API
-heavyweight SockJS integration
It will be interesting how all of his plays out. And I'm definitely interested in hearing evidence for claims such as
> a run-time with real concurrency and unrivalled performance
I haven't looked in to it, but just guessing this is probably so that it can do 0-copy sending of files (e.g. doesn't have to buffer/stream the contents through the JVM).
You can also serve files in the more conventional "node.js-style" way (i.e. pump the buffers manually from file to socket) if you like. It's just slower than getting the kernel to do the work for you.
The whole point of sendfile is to make one system call to send all the data in one stream to another, which in general may block. If you're polling and sending only small chunks at a time (whatever you can write without blocking), is it really that much of an advantage over read/write on the same poll? (If you're not doing that, then you have to block, and you have to dedicate a thread to it.)
It's still an advantage over read/write because you're getting the 0-copy behavior.
This is opposed to Node, which must run at least one VM for each CPU in order to utilize all of the cores in a system, unless your only use of threads is ThreadPoolExecutor-style pools, then you can use the horrible hack that is threads-a-gogo
> InfoQ: What about running a real-time app on the JVM vs. on Node.js, with respect to debugging, monitoring and operations?
> Answer: I'd say monitoring and operations are really the concern of the environment in which you deploy vert.x than vert.x itself. e.g. if you deployed vert.x in a cloud, the cloud provider would probably provide monitoring for you.
Plus a whole framework based around MongoDB:
Are you sure you're not looking at the github tags, rather than the downloads?
I know Fibers/Green threads are all the rage right now, and it is certainly something to keep an eye on, but I am not entirely convinced that roll your own threading is going to be any more performant than what the kernel can do.
If we can find a way of implementing fibers efficiently, that supports millions of fibers on a single JVM instance, I would be interested.
req.response.sendFile('webroot/' + file);
I'll have file='../../secret.txt' thanks
Also, the servlet API is crazy, partly because of all its baggage. There seems to be a lot of exploration around what the right API is right now, but its pretty clear the world wants something new.
No. Servlet containers use a thread pool (that grows and shrinks dynamically).
The point is that a given request in a servlet container is handled in it's own thread. That thread will probably come from a pool and be reused to handle another request of course, but that's sort of immaterial.