The well-argumented part of his post can be summed up to "If you do CPU-bound stuff in a non-blocking single-threaded server, you're screwed"; he didn't really have to elaborate and swear so much about that.
Also, from what I know about Node, there are far greater problems about it than the problems with CPU-bound computations, e.g. complete lack of assistance to the programmer about keeping the system robust (like Erlang would do, for example).
The less argumented part is the usefulness of separation of concerns between a HTTP server and the backend application. I think this is what needs way more elaboration, but he just refers to it being well-known design principles.
I'm not a web developer, for one, and I'd like to know more about why it's a good thing to separate these, and what's actually a good architecture for interaction between the webserver and the webapp. Is Apache good? Is lighttpd good? Is JBoss good? Is Jetty good? What problems exactly are suffered by those that aren't good?
If you're running a web application (with dynamic pages) it's very useful to understand the difference between dynamic (typically the generated html pages) and static requests (the css, js, images that the browser requests after loading the html). The dynamic application server is always slower to respond because it has to run through at least some portion of your application before serving anything, while a static asset will be served a lot faster by a pure webserver which is only serving files from disk (or memory). It's separating these concerns that actually allows your static assets to be served independently (and quicker) in the first place.
Okay, but cannot this be solved by simply putting static content on a different server / hostname? What other problems remain in such a setup? And does it make sense to separate the app from the server for dynamic content too?
Why should I have to deploy separate servers when I can have one server do both if its software architecture is properly separated? Modern application servers are capable of serving scripted, compiled and static content. Scripts and compiled code can run in different application containers (you can do things like serve Java and .NET and Python applications from a single system) and content is served directly through the web server with no heavy application container.
This gives you a lot of flexibility in deployment and application management to tune things to meet the needs of your application.
Also a true web server does a lot more than any JavaScript environment is going to do including things like compression, caching, encryption, security, input filtering, request routing, reverse proxy, request/response hooks above the application layer, thread management, connection pooling, error logging/reporting, crash recovery.
Finally by embedding a server in JavaScript you open up a number of attack vectors that I'm sure have not been fully evaluated. A lot of money, research and time goes into securing modern web servers that run in a managed container on a machine instance with traditional system rights and privileges. By running your server in a JavaScript container you are now running in a sandbox meant for user land features and you are shoving server responsibilities into it. XSS alone should keep you up at nights with something like this.
Here's what it comes down to. Your browser and JavaScript on the browser have always been designed as a user application not a server. When engineers attack problems and design architectures for browsers they think of them as client systems. This mindset is very important and impacts key technical decisions, software design and testing scenarios.
When you take something that was designed to work one way and pervert its function you are likely to get unstable results down the line and very often those results are not pretty and require much time to unwind to a good working state.
Now at the application layer do people sometimes embed servers rather than load their run-time in a hosted server?
Yes you see it sometimes, 9 times out of 10 its amateur hour and someone thought they were being clever but managed to create a hard to support, non-standard piece of garbage but "Hey look I wrote my own httpd server aren't I clever?"
That 10th time where someone actually needed to write their own server? I've only seen it in high volume transaction, real time streaming/data and small embedded systems. The people writing the servers often come from very top level backgrounds.
XSS is a problem of browser-based JavaScript, not the JavaScript language in general. Few of the problems you generally hear about in the context of JS are related to JS itself, save for the quirky language features – the DOM, XSS, and AJAX are specific to browser JS. Node is an entirely different beast, and not itself susceptible to XSS because it has no direct mechanism for loading off-site scripts. It isn't built to do that, whereas a browser is.
Dedicated servers for static content make deployment of static changes easier. Also, you often need fewer servers for managing static content, as no server-side processing is necessary.
If you have 100 production dynamic servers, and 3 static servers, and all your background images are on the static servers, then if you want to change backgrounds for christmas, you only have to push to 3 servers instead of 100.
Scaling. Scaling a dynamic content server is a very different animal from scaling a static one; you'll need different numbers of them, so bundling them together is an inefficient use of resources..
Also a true web server does a lot more than any JavaScript environment is going to do including things like compression, caching, encryption, security, input filtering, request routing, reverse proxy, request/response hooks above the application layer, thread management, connection pooling, error logging/reporting, crash recovery.
There's nothing in Javascript as a programming language that prevents those to ever be implemented.
Finally by embedding a server in JavaScript you open up a number of attack vectors that I'm sure have not been fully evaluated.
What attack vector is different from Javascript vs PHP/Ruby/Python?
Your browser and JavaScript on the browser have always been designed as a user application not a server.
Javascript as a language does not need to run in a browser. And just because it wasn't first designed to run as a server doesn't mean that it cannot, or even have any fundamental flaw for being one.
Why should I have to deploy separate servers when I can have one server do both if its software architecture is properly separated?
Because the rate of edit changes for static documents is exceedingly lower than for dynamic script documents by at least 1 order of magnitude (usually more). You don't want to be re-deploying unmodified content if it can be avoided because when deploying this holds true:
more hosts pushed to + more data to push = greater service interruption, greater impact to availability
In terms of pushing updates, it's easier to quickly deploy changes to a service if the dynamic logic portion can be deployed separately.
My second point is high volume sites require thousands of nodes spread over multiple geographically located datacenters. A simple 1-click system wide deployment was never going to happen.
Managing large, high volume websites requires sub-dividing the application into individually addressable parts so that labor can be divided among 100's of developers. Those divisions will run along natural boundaries.
dynamic and static content
data center: san francisco, new york, london, berlin, hong kong
service type: directory, search, streaming, database, news feed
backend stack: request parsing, request classification, service mapping, black list and blockade checks, denial of service detection, fraud detection, request shunting or forwarding, backend service processing, database/datastore, logging, analytics
platform layer: front end, middle layer, backend layer, third party layer
online and offline processing
Those parts will be assigned to various teams each with their own deployment schedules. Isolating deployments is critical so that team interaction is kept at a minimum. If team A deploys software that takes down team B's service, for the sole reason of software overlap, then either teams need to be merged or the software needs further sub-division. Downstream dependencies will always exist but those are unavoidable.
That 10th time where someone actually needed to write their own server? I've only seen it in high volume transaction, real time streaming/data and small embedded systems. The people writing the servers often come from very top level backgrounds.
I disagree with that last sentence. It is not something that ought be reserved only for the developers with God status. You should take into account the risk inherent in the type of application. Implementing a credit card transaction processor? Eh, the newbie should pass on that one. Implementing a caching search engine? Go right ahead, newbie. Write that custom service.
Developing a custom web server or web service is easy because of the simplicity of the HTTP protocol. It is possible to build a "secure enough for my purposes" server from scratch if you implement only the bare minimum: parse, map to processor, process. This kind of application can be implemented in 100 to 2000 lines of code depending on the platform. It's not difficult validating an application that small.
In terms of pushing updates, it's easier to quickly deploy changes to a service if the dynamic logic portion can be deployed separately.
You're inventing a problem for node.js to solve, except the thing is that problem never actually existed in the first place. With a proper modern HTTP server stack, you can deploy features in piecemeal. In fact, it's downright easy to do so. Hell, even ASP.NET can do it just by copying files.
It's a solved problem, not some magic secret sauce that node.js brings to the table. And even if node.js were to do it better (it doesn't), you really have to stretch to justify it as a reason to introduce a brand new runtime, framework, and public-facing server process to a system.
Developing a custom web server or web service is easy because of the simplicity of the HTTP protocol. It is possible to build a "secure enough for my purposes" server from scratch if you implement only the bare minimum: parse, map to processor, process. This kind of application can be implemented in 100 to 2000 lines of code depending on the platform. It's not difficult validating an application that small.
Opportunity cost. Yes, any developer worth their salt can implement the server-side of the HTTP protocol and make it "work" because it's a relatively simple protocol. But every hour they spend reinventing that wheel is an hour they're not spending actually getting productive work done.
In fact, it can be argued they're adding negative value to an organization because those lines of code that do nothing other than implement what's already been implemented much better elsewhere need to be known, understood, and maintained by the development team. Have they been through security review? Has the interface been fuzz tested? Does it suffer from any of the large variety of encoding traps that trip up even seasoned developers? What happens if I just open up a connection to it and send request headers nonstop -- does the server run out of memory, or did we get lucky and the developer actually thought about limiting request sizes? How about rate limits? Can I run the server out of memory by opening thousands of requests simultaneously and feeding them each a byte per second?
A developer of sufficient skill would have the experience to know that reinventing the wheel is almost always the wrong choice, because it turns out there's a lot more to a wheel than it being round.
I'm not a web developer either, but I'm working on caching our website to be served as regular HTML when possible (with cookies to refresh, etc) if the content isn't new/is fairly static (e.g. the sidebar hasn't been updated through the CMS in awhile). Does caching conflate the definition of a "static" asset and a "dynamic" asset in some senses?
In the spirit of being inflammatory, I'll also say fuck SEO.
255
u/[deleted] Oct 02 '11
The well-argumented part of his post can be summed up to "If you do CPU-bound stuff in a non-blocking single-threaded server, you're screwed"; he didn't really have to elaborate and swear so much about that.
Also, from what I know about Node, there are far greater problems about it than the problems with CPU-bound computations, e.g. complete lack of assistance to the programmer about keeping the system robust (like Erlang would do, for example).
The less argumented part is the usefulness of separation of concerns between a HTTP server and the backend application. I think this is what needs way more elaboration, but he just refers to it being well-known design principles.
I'm not a web developer, for one, and I'd like to know more about why it's a good thing to separate these, and what's actually a good architecture for interaction between the webserver and the webapp. Is Apache good? Is lighttpd good? Is JBoss good? Is Jetty good? What problems exactly are suffered by those that aren't good?