5 ms·
Why anybody wants to run node.js instead of Java. Java is much better suitable for the server side than node.
by solomatov 11y ago
Why anybody wants to run node.js instead of Java. Java is much better suitable for the server side than node.
- nothrabannosir 11y agoNobody has commented yet. I can only guess this is because all agree: it goes without saying that this sweeping generalisation is patently untrue. Still, allow me to humor you and give just one (of the many) reason(s) why: async I/O. Yes, it's possible in Java. Yes, Java has futures that make it not just possible, but also a reality in this universe. Unfortunately, Java has made the inconvenient decision to retain backwards compatibility and keep all its synchronous I/O operations available. Perhaps not a complete folly. For all of the good that decision has brought, there is one downside: any code (any lib) can still lock up an entire OS thread. Result: all libs actually do this. No matter how Future-istic your codebase; use any lib and you're back to sync I/O.[1] This is absolutely killing for high concurrency, I/O bound servers, who now lock up not just an FD or two per conn, but also an entire OS thread. Javascript's threading model, on the other hand, is so shit that it came out the other side. By being inherently single threaded, all blocking I/O must be done through callbacks. Result: you can't block an OS level thread in javascript! So all libraries are inherently async (from the OS level). There are, of course, many more reasons why Java is not "much better suitable for the server side than node", but this is just one of them (libraries, existing knowledge in your org, community, ...). In reality, both have their uses. Node has proven itself by now. Disclaimer: I actually hate Javascript. And Java. Including Java 8 (for all the shit it, wisely, keeps around). [1] E.g. Amazon's official AWS SDK, which is sync IO. Want async IO for S3 (or anything there)? Write it yourself. Which you won't. Because there's already a lib. "But it's not async!" // TODO.
- EvanPlaice 11y agoEasy on the 'rage' Javascript's threading model, on the other hand, is so shit that it came out the other side. By being inherently single threaded, all blocking I/O must be done through callbacks. Result: you can't block an OS level thread in javascript! So all libraries are inherently async (from the OS level). This statement is patently false. I/O requests are fired off asynchronously in the main context but fetch data via background threads. In addition, in a multi-core/processor system you can use the 'cluster' module to fire off multiple instances (ideally 1 per core) of the HTTPD. As for libraries. Node doesn't provide much in terms of 'batteries included' but the NPM registry has eclipsed the library ecosystem of every other language. If anything, the issue is too much choice as there are usually 3-5 alternatives for everything you can imagine. The minimalist nature of the Node core is a 'double edge sword'. The downside is, it requires a lot more cognitive load and research to choose the libraries to use in a dev stack. The upside is, since most of the functionality is developed independent of Node the core devs can focus the entirety of their effort improving the platform/language/packaging. The effort of building all additional functionality is the responsibility of the community. I have used Java some and C# a lot so I can understand why devs love the ecosystem and tooling. The tooling for JS is getting better over time but there's something to be said for IDEs that come prepackaged with all the tools necesssary to be productive. Personally, I shifted over time embracing the flexibility of dynamic languages and shifted to a mindset that favors composition over structure.
- solomatov 11y ago>I actually hate Javascript. And Java. Including Java 8 (for all the shit it, wisely, keeps around). Could you give me an example of any technology which you don't hate?
- nothrabannosir 11y agoYes, but let's keep that talk for over a drink some time :) I put that in to clarify that Im not coming at this from fanboyism. It wasnt about me, but to contextualize the comment.
- carterehsmith 11y agoI hope we can agree that, whether Netty or Node can accept 100M connections per millisecond or not -- is irrelevant if the rest of your stack cannot keep up. In most applications, eventually you need to hit the database to process the request... and the database does not care if your original http request was asynchronous or not... it will still take its sweet time in milliseconds (or seconds for complex queries) to respond. And the best way to prevent that is caching. And that is where Node is at disadvantage. In Java (and C, and C#, and a bunch of others), if your server has 16 cores, you will be running a single process on 16 cores and probably 32 concurrent threads, and they can all access some shared data (notably, database cache) with low intra-process latency, using some simple sharing primitives. Now, Node... if a Node process is single-threaded, then one would need to spawn 16(32) Node processes to fully utilize the server, and they will be using inter-process communication to talk to each other -- much slower than Java's intra-process.
- EvanPlaice 11y agoIn Java (and C, and C#, and a bunch of others), if your server has 16 cores, you will be running a single process on 16 cores and probably 32 concurrent threads, and they can all access some shared data (notably, database cache) with low intra-process latency, using some simple sharing primitives. You're right but there are downsides to this approach. First, you're creating a single point of failure. If any part of the application crashes for whatever reason it brings everything down with it. If you intend to have fault tolerance, maintain uptime during updates and/or provide A/B testing capabilities, you'll still require at least a redundant server and a load balancer to funnel incoming requests between the two. Second, sharing memory across cores comes at a cost. A simple mutex/lock strategy will work but will be inefficient as it blocks on both reads and writes to shared data. You could choose to use a CAS (Compare and Swap) strategy to avoid locks altogether. As long as you can ensure your models as well as all of the internal data structures they use are immutable and thread safe. Considering the nested nature of OOP inheritance as well as language level access restrictions on classes/methods/members, it can be difficult/impossible to ensure immutability without hand-rolling your own data structures. Third, sharing state across contexts comes with hidden costs that need to be taken into consideration. For instance, if the shared state for all threads is updated (ie a cached value is added/updated) it will invalidate the L1, L2, and L3 caches on the processor. The overhead of cache invalidation increases in proportion to the number of cores/processors involved. Source: http://www.drdobbs.com/architecture-and-design/sharing-is-the-root-of-all-contention/214100002?pgno=1 http://www.drdobbs.com/architecture-and-design/sharing-is-th... I assume you have experience with multi-threaded programming. I won't touch on the transient nature and inherent difficulty in replicating bugs introduced in multi-threaded programming. Other than to say, I've done enough of it in the past to develop a very healthy fear. ----------------------- What about Node... You're right to assume that Node instances will run as a cluster. Ideally one instance per core, to reduce context switching and prevent cache invalidations between the foreground and background workers internal to a Node instance. As for a cache layer between the DB and Node instances. Since communication between Node instances will happen at the OS level via IPC, there's no benefit to implementing a global cache internal to the Node application. Instead, it would be better to offload the responsibility to a separate service that is specialized for caching (ex redis). This reduces the complexity of the application, surface area for bugs, and development time. Load balancing will be required anyway, so it makes sense to use Nginx. Nginx is much more fault tolerant, providing sane limits for incoming requests, as well as the ability to define routes that short-circuit requests to static files. What's interesting about deploying a Node cluster is its 'redundant by default' nature including auto-respawning of cluster instances https://www.npmjs.com/package/express-cluster https://www.npmjs.com/package/express-cluster. If you desire a more granular control over cluster management you could use https://github.com/Unitech/pm2 https://github.com/Unitech/pm2. To make this work the servers themselves will need to be stateless. Which means, handling session management requires additional work-arounds. ----------------------- Java is likely 'faster' when deployed in a strictly vertically scaled setup. Node.js is more geared to horizontal scaling by default. Just like Java now includes good support for async request handling, I have no doubt the community will design tools that also favor scaling out. Either way, I don't think raw performance is going to be the deciding factor. Choice of platform is a business decision that depends on the resources and skills and/or preference of the team responsible for development.
- campers 11y agoRecently I've been doing a bit of research on what tech stack to choose for my next project. I'm a long time Java dev and been doing JS/TypeScript dev the last year. I'd been deciding with a newer Java/JVM stack or node.js/TS. There's a library that fixes the sync I/O issue in Java call Quasar which implements lightweight threads called Fibers. I remember seeing it a while ago and thought it was pretty interesting and it seems reasonably mature now. One of the nicest things about it is you can get async IO with a sync programming model. So no callbacks and chaining of promises. I'll probably start with Java 8 but the other JVM language I quite like it Kotlin, which has a similar style to TypeScript in some ways, and is designed for Java interop. Kotlin + Quasar fibers seems like a pretty nice combo on the JVM. http://blog.paralleluniverse.co/2015/06/04/quasar-kotlin/ http://blog.paralleluniverse.co/2015/06/04/quasar-kotlin/ http://blog.paralleluniverse.co/2015/08/28/quasar-0.7.3-comsat-0.5.0/ http://blog.paralleluniverse.co/2015/08/28/quasar-0.7.3-coms...
- nothrabannosir 11y agoThe problem is not the lack of async IO, but the existence of sync IO. As long as sync IO is a possibility, it will spread through your program like a cancer. Even without using it yourself, all your libs will. Does Quasar address this? Edit: just to clarify: it's not as bad as I make it sound. Java may still be the best tool for your project. It's definitely got a great VM and good libs. If it makes sense, use it.
- campers 11y agoSync I/O API's are still an issue, the main one being JDBC. The approach with Quasar is to have a dedicate thread pool for the JDBC calls, which in that case isn't necessarily too bad as you don't want to overload your database. Comsat is the companion project which provides the quasar fiber integration to common libraries/services (http, servlet, db etc) which gives you the nice synchronous programming model (via bytecode instrumentation) with the async/light thread scalability. So your incoming servlet request would use the async servlet API integration to move the execution to a fiber. Then calls to an external http service, out-of-process cache, files, NoSQL db etc would all happen within the fibers. Its mainly the JDBC that requires a pool of normal threads. I've only just decided this is what I want to use next, so I'll be able to tell from experience over the coming months!
- deleted 11y ago[deleted]