Performance Zone is brought to you in partnership with:

Ant is a freelance Java architect and developer. He has been writing a blog and white papers since 2004 and writes about anything he finds interesting, related to Java or software. Most recently he has been working on enterprise systems involving Eclipse RCP, Google GWT, Hibernate, Spring and J2ME. He believes very strongly in being involved in all parts of the software life cycle. Ant is a DZone MVB and is not an employee of DZone and has posted 27 posts at DZone. You can read more from them at their website. View Full User Profile

Java Non-blocking Servers, and What I Expect node.js to do if it is to Become Mature

05.23.2011
| 18447 views |
  • submit to reddit

node.js is getting a lot of attention at the moment. It's goal is to provide an easy way to build scalable network programs, e.g. build web servers. It's different, in two ways. First of all, it brings Javacript to the server. But more importantly, it's event based, rather than thread based, so relies on the OS to send it events when say a connection to the server is made, so that it can handle that request.

The argument goes, that a typical web server "handles each request using a thread, which is relatively inefficient and very difficult to use." As an example they state that "Node will show much better memory efficiency under high loads than systems which allocate 2MB thread stacks for each connection."

They go on to state that "users of Node are free from worries of dead-locking the process — there are no locks. Almost no function in Node directly performs I/O, so the process never blocks. Because nothing blocks, less-than-expert programmers are able to develop fast systems".

Well, reading those statements makes me think that I have problems in my world which need addressing! But then I look at my world, and realise that I don't have problems. How can that be? Well first of all, because we don't have a thread per request, rather we use a thread pool, reducing the memory overhead, and queuing incoming requests if we can't run them in a thread instantly, until a thread becomes free in the pool.

The second reason I don't have threading problems is because I work with Java EE. I write business software which is written as components which get deployed to an app server. That app server is what does all the hard work with threads. All I have to do is follow some simple and common sense rules to avoid threading issues, like ensuring that shared resources like a Map(dictionary) are instantiated using the thread safe API which Java offers. In more extreme cases, I use the synchronized keyword to protect methods or objects being shared.

All this means that we Java programmers have become very efficient at writing software to solve business problems, rather than writing software to solve technical problems like concurrency, scalability, security, transactions, resources, object and resource pooling, etc., etc.

So when do I need to solve those problems which lots of threads introduce, namely memory problems? Any server which needs to maintain an open connection to the client, in order to say stream video or Voice over IP (VOIP), or handle instant messaging, is a server where I'm going to have problems with memory if I have a thread per connection.

Now, the Java EE specifications tend to focus on multithreaded servers. And to my knowledge, there is no Java EE specification which tells vendors how to make a server which lets people deploy software components to it, which are handled in a non-blocking manner. Sure, you could write a Servlet compliant server like Tomcat with a non-blocking engine under the hood, but Java EE doesn't talk about streaming. And probably 99% of websites out there don't do the kind of streaming which is going to cause memory issues.

So there certainly are times when something like node.js will be useful. Or at least the idea of a non-blocking server. But looking into the details, node.js isn't something that I would seriously use if I needed such a server. The main problems are that:

  1. you deploy Javascript to the server
  2. it doesn't seem to specify a standardised way of writing components so that I can concentrate on writing business software rather than solving technical issues
  3. while it is rumoured to be fast, studies such as this suggest it's half as slow as Java
  4. compared to Java, the node.js API and Javascript libraries available today are immature - think about things like sending email, ORM, etc.
  5. node.js has political problems because it relies on Google. If Google don't want to support Javascript on the server (their V8 engine is designed for Chrome, client side), and node.js needs a patch or development on V8 to handle a serverside issue, they might never get it. OK, like I have a chance to get a Java bug patched by Oracle ;-)
It started for me, with this code snippet, taken from the node.js site:
    var net = require('net');

    var server = net.createServer(function (socket) {
      socket.write("Echo server\r\n");
      socket.pipe(socket);
    });

    server.listen(1337, "127.0.0.1");

Well, if the point of node.js is to make it really easy to create a server, and pass it a function for handling requests, I can do that in Java too:
TCPProtocol protocol = new TCPProtocol(){

    public void handleRequest(ServerRequest request, 
                              ServerResponse response) {

        //echo what we just received
        try {
            response.write(request.getData());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
};

Configuration config = new Configuration(1337, protocol);
ServerFactory.createServer(config).listen();

OK, it's a tiny bit more complicated. But the reason is, I decided to write a non-blocking server which can be configured to handle any kind of request. The configuration takes a port number for the server to run on, and a protocol object. The protocol object is a subclass of an abstract protocol, and its job is to look at the data coming in from the wire and decide how to handle it. A TCPProtocol as shown above is simplest protocol, in that it does nothing. You need to tell it what to do, by overriding the handleRequest() method (analagous to supplying a function in Javascript), for example as shown above, by returning to the client what it sent to the server.

But I wanted to do something more useful, so I extended what I wrote to handle voice over IP, or at least a client streaming an MP3 to a different client, to simulate a phone call between the two of them.

The first step was to design the protocol. At the byte level, the first byte in a packet sent to the server contains the command, or action, the second byte contains the length of the payload, if any, and the subsequent bytes contain the payload.

The protocol then lets a caller login (returning a session ID), start a call (returning an OK/NOK), send data for the call, end a call, and quit (logout).

After a few hours I had my laptop playing my favourite MP3s, streamed to my laptop from a different PC. But it looked clunky. I had a think, and took inspiration from the Servlet and EJB specifications in Java EE. Namely, I wanted to have deployable components whose sole job was to handle a business requirement.

In .NET and Java you can define a web service or web page (Servlet) by annotating the class. In the annotation, you provide a URL path, which the server uses to determine when to call your servlet or web service. This is similar to a "command" or "action" as I had in my VOIP protocol.

So I wrote a little container, which sits inside the non-blocking server. The server takes the incoming request and once it has handled the low level non-blocking stuff, it passes the request over to the configured protocol. The VOIP protocol then extracts the command (first byte) from the incoming request. It then uses a "context" object, which it gets injected into it from the container, to send the incoming request to a Handler. The handler is a class which has an annotation to state which command it can handle. The handler is then analagous to a web service or servlet. It is a piece of busienss code which handles an incoming request, based on the command (path) which the client is requesting.

Put together, it looks as follows. The first bit is the protocol's handler method which determines the command and sends it to a handler:
    public void handleRequest(ServerRequest request,
	                          ServerResponse response) {

        String criterion = String.valueOf(request.getData()[0]);
        try{
            //call through to the context for help - it
            //will call the handler for us.
            getContext().handleRequest(criterion, request, response);
        } catch (UnknownHandlerException e) {
            //send NOK to client because of unknown command
            response.write(new Packet(UNKNOWN_COMMAND).marshal());
        }
    }

A Packet object in the above code is simply an encapsulation of the data sent over the wire, but knows that the first byte is the command, the second is the length and subsequent bytes are the payload. In an HTTP request, this Packet object would be something which knew about the HTTP header's attributes and the HTTP payload, rather than the ServerRequest and ServerResponse objects which only know about byte arrays and sockets/channels.

The second part of the solution are then the handlers. These are contained in the configuration, either created programatically as shown in the TCP example above, or created using XML which the server reads upon startup. The container then locates, instantiates and calls these handlers on behalf of the protocol, when the protocol object calls getContext().handleRequest(criterion, request, response) in the above snippet. A typical handler looks like this:
@Handler(selector=VoipProtocol.LOGIN)
public class VoipLoginHandler extends VoipHandler {

    public void service(VoipRequest request,
                        VoipResponse response)
                        throws IOException {
		
        String name = request.getPacket().getPayloadAsString();
        Participant p = new Participant(
                        name, response.getSocketChannel());
        getProtocol().getModel().addParticipant(p);
        request.getKey().attach(p);
		
        //ACK
        String sessId = p.getSessId().getBytes(VoipProtocol.CHARSET);
        Packet packet = new Packet(sessId, VoipProtocol.LOGIN)
        response.write(packet);
	}

}

So, the service method is the only one in a handler, and is in charge of doing business stuff. There is no techy stuff here. The code works out who is logging in, creates an instance of them (the Participant object) in the model. The model is contained in the protocol object, which exists just once in the server. Compared to a servlet, the call to get the model is analagous to putting data into the application scope. The code then attaches the participant object to the client connection using the attach(Object) method (see Java NIO Package) so that we can always get straight to the relevant part of the data model from the connection object, when subsequent requests arrive. Finally, the code responds to the client with the session ID as an aknowledgement. Note that here, I haven't bothered to authenticate the password - the payload only contains the username. But if I were writing a complete app, I would have more data in my payload, perhaps even something like XML or JSON, and I would authenticate the username and password.

The @Handler annotation at the top of the handler class is analagous to the @WebServlet annotation applied to Java EE Servlets. It has a "selector" attribute which the container uses to compare to the criterion which the protocol extracts from the request. This is analagous to the URL patterns attribute in @WebServlet which tells a Java EE web container to which path the servlet should be mapped. There is a little bit of hidden magic too - the service method in the handler already knows VoipRequest and VoipResponse, rather than ServerRequest and ServerResponse. The superclass does this magic, by implementing the standard service method and calling the specialised abstract service method, implemented in subclasses.

So, being creative, I added a further attribute to the @Handler annotation. It is called runAsync and defaults to false. But, if it is set to true, then the container sends the handler to a thread pool for execution sometime in the future. I don't actually use this in the VOIP example, but I did this, to show that it is perfectly feasible, that an app server can do such things. The developer doesn't need to worry about threads or anything - they simple configure the annotation and the container handles the hard parts. This is typical of Java EE! And it becomes extremely useful in cases where a request needs a little more time to execute. In a non-blocking single threaded process, while connections are concurrently connected to the server, they are serviced sequentially, meaning that they MUST return fast, if you don't want those in the queue to wait too long. This is something which node.js CANNOT do, because it has no way of starting threads. Their solution is to send an async request to a different process. But to do that, the developer is spending time working on technical issues, rather than getting on and trusing the container to do it for them, so that they can spend more time writing cost effective business code. One of the main reasons to use Java EE is that the developer can spend more time writing business software and less time handling techie problems. There is no reason why a handler couldn't also have other annotations:
@Handler(selector=VoipProtocol.QUIT)
@RolesAllowed({"someRole", "someOtherRole"})
@TransactionManagement(TransactionManagementType.CONTAINER)
public class VoipQuitHandler extends VoipHandler {

    @PersistenceContext(unitName="persistenceUnitName")
    private EntityManager em;
    .
    .
    .
}

The @RolesAllowed@TransactionManagement annotation means that transactions will be handled by the container rather than by the programmer. When the handler is executed, the @PersistenceContext annotation causes the container to inject a JPA entity manager so that the business code has access to a database. This is exactly the same way that a Servlet or EJB gets resources from the container. Those resources are created based on the app server configuration, in a standardised way and are managed by the container too (pooling, reconnecting, etc.), again, relieving the programmer from that burden.

So what do we have now? Instead of a low level API like node.js provides, we have a high level container for running software components within a non-blocking server. What we don't have, is Javascript running on the server, because it seemed like the ideal language for handling callbacks in a non-blocking environment, because it has an event queue and function pointers.

Could this little exercise be the basis of a JSR? Well, is it really useful? Only really in cases where you have clients which need to keep connections open to the server for a long time, and you have thousands of clients. There won't be many people needing to do this, and there are more important JSRs awaiting acceptance and implementation. But who knows what the future will bring.

To summarise, node.js makes me uneasy, because I don't like the idea of Javascript and its immature stack of libraries being deployed on a production server. Whenever I develop with Javascript I spend a lot more time with the debugger than I would like to, because the language is not entirely checkable using static analysis because it is duck typed. But the idea of building a non-blocking server using Java - now that's interesting (to me at least). But like I said, I'm just not sure how often will it be useful.

It seems to me, that the revolution that node.js is starting isn't really about Javascript on the server. It is more about using a non-blocking server. But the problem is, probably 99% of our needs are already satisfied with standard multithreaded servers. And we can already write scalable websites, without all those problems which node.js claims we have. So let's not rebuild the world based on non-blocking I/O, just because node.js has arrived. Let's build/rebuild just those very special cases, where non-blocking I/O will really help us.

Does node.js deserve the hype it is getting? I don't think that it deserves hype because you can run Javascript on the server - that's a bad thing. Douglas Crockford (senior JavaScript architect at Yahoo!) even hints this, when he says:

"The big surprise for me in this is we're about to take maybe the most important step we've ever taken in terms of the technology of the web, and JavaScript is leading the way."

He seems to be saying that Javascript is leading the way in the most important step we are ever taking, and not that Javascript IS the most important step we are taking. That is, non-blocking servers are the most important step, and having an event loop on the server is the way forward. The way I understand it, he is saying that non-blocking is the revolution. The problem I have in joining in on this revolution is that non-blocking servers are not ncessarily the best thing ever. They only really help, when you have thousands of clients needing to keep their connections to the server open. HTTP (99% of the web) doesn't need non-blocking I/O to become the technology leader of the web - it already is. So instead of joining in this revolution and all the hype that node.js is stirring up, I will ignore it and continue building software the way I have been.

The code for the examples given above are in two Eclipse projects, which you can download here. The first project is the framework itself, including the non-blocking server, container and relevant classes and interfaces. The second project is an example of how to use the framework to build (business) apps. It contains the TCPServerRunner class for running a TCP echo server. It also contains the VoipServerRunner which starts the VOIP Server. To run the streaming example, first run the ListeningClient, followed by the SendingClient. Change line 74 of the SendingClient to use your favourite MP3, and you should hear it stream the first 20 seconds. The VOIP server itself isn't 100% reliable - especially once clients have disconnected. But I guess node.js wasn't that stable after only a small number of hours of development. Good luck!

PS. Performance: streaming at 192 kilobits a second, the server told me it was running around half a percent load (i.e. the event loop was idle 99.5% of the time). GSM, rather than high quality MP3 uses around 30 Kbps, so for a real VOIP server, you could probably get away with 1200 simultaneous calls. That doesn't seem that many, but I have no idea really. I guess I have 2 CPU cores which I could use so that I could use a load balancer to spread the load among two processes, which is the node.js way of using all the cores. But the load balancer wouldn't be doing much less work than my server does, so might not be able to handle any extra load itself. Or I could stick my handlers in a thread pool, using the runAsync attribute of my @Handler annotation. So a low cost commodity server could handle nearly 2500 simultaneous calls. Still not many? Again, I really don't know. But I should say that I didn't try optimising the server. My packet sizes are based on sending one packet of sound data every 12 milliseconds. Perhaps I could get away with sending them less frequently which might improve throughput and still have good call quality with low latency. Who knows - anyone wanting to optimise it, let me know the results! One thing for sure is that a server using one thread per connection with 2500 simultaneous connections, will struggle. While my previous blog article showed it is possible to have many thousand threads open, the context switching is likely to become the bottle neck. A non-blocking server is certainly the way forward for this use case.

Download the code here.

From http://blog.maxant.co.uk/pebble/2011/05/22/1306092969466.html

Published at DZone with permission of Ant Kutschera, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Jose Maria Arranz replied on Mon, 2011/05/23 - 2:46am

Regarding to threading and non-blocking programming  I'm sure you will get surprised.

Martijn Verburg replied on Mon, 2011/05/23 - 4:29am

Great in depth article! It's always good to have more options, but leading web servers (namely Tomcat 7) have already pretty efficient Java workarounds in place. The future also looks bright with NIO.2 asynchronous socket/channel and file APIs coming into Java 7. I expect to see Java based web servers taking advantage of that pretty quickly. Cheers, Martijn (@karianna)

Subbu Allamaraju replied on Mon, 2011/05/23 - 10:43am

Where did the author get his facts?

"it doesn't seem to specify a standardised way of writing components so that I can concentrate on writing business software rather than solving technical issues"

 Huh?  

 "node.js has political problems because it relies on Google."

 What political problems?

This article is competing with the article that IBM pulled out a few weeks ago - http://www.ibm.com/developerworks/opensource/library/os-nodejs/index.html (see http://webcache.googleusercontent.com/search?q=cache:t5iEsHYKPXoJ:www.ibm.com/developerworks/library/os-nodejs/+ibm+nodejs&cd=3&hl=en&ct=clnk&gl=us&client=firefox-a&source=www.google.com for a cached copy).
 

Abhishek Chavan replied on Mon, 2011/05/23 - 12:33pm

Great Article. I just started reading NodeJs and trying it out. It looked quite nice but I was a little worried about extensibility and scalability while using NodeJS. With so many new languages coming in the Sphere right now, I am waiting for the next big language. Let's see what it is.

Appreciate the article. Would love your inputs on What will be the next big Language. Which language should one learn next.

Abhi

Ant Kutschera replied on Mon, 2011/05/23 - 1:26pm

Hi Jose Maria,

I agree with most of the points.

Breaking tasks into little steps has a trendy name: eteration.  Like you say, to do that, is to simulate what threads do, and to do it means you have to do the programming of how to break tasks up instead of letting the VM and OS do it for you.  While it might mean you can use just one thread, it's ugly from the developers point of view.  I guess it's a tradeoff.

Instead of saying one should use threads, or one shouldn't, I created the runAsync attribute in my @Handler annotation, so that the developer can choose.  Sometimes you will need it, and sometimes you won't.  But what is clear here, is that it won't ever be "one thread PER request".  Just a thread pool, to enable longer running tasks to not block the event queue.  If there are no available threads, the tasks get queued.  A huge number of threads won't help, because you only have a limited number of other cores which can process those threads.  You don't want thousands, because the context switching will kill you.  You might as well just let tasks build up in the queue which the thread pool works on.

Let me be explicit here: the programmer doesn't need to know anything about threads, except that their model might be accessed by multiple threads.  The programmer should use thread safe data structures in the model, which they can get using the Collections class (Java API).  That is really easy and does NOT mean they are handling the horrible parts of threading.

And for all those people who say "don't worry, use processes rather than threads", take a look here: http://amix.dk/blog/post/19577#Is-node-js-best-for-Comet

The problem there, is that they want to put the expensive write calls into a thread, away from the event queue thread which handles the reads.  But you can't put the writes into a different process, because two processes cannot share one connection.  (Although there is talk about passing file handles between processes, perhaps then one process can read from a connection while the other writes to it?  I have no idea - way to low level for me...)  What I suggested with runAsync on Handlers would let the programmer do exactly what they needed to do, namely put the writing onto a different thread.

For me, the thought process of people should be like this:

1) Will I have short lived requests (i.e. the client will open and close connections quickly, like with normal HTTP)?

If Yes (99% of people), then use a multithreaded server, because it is a waste of time building a new server.  Use a Java EE app server to take the burden of threading away from you :-)  You won't have scalability issues, because you can build a server farm.  Memory and context switching won't be that bad, because you only have a limited number of threads in a pool - you don't have a thread per request.

2) Will there by many thousand long lived connections? 

If No, then configure your server with enough threads to handle all the open connections.  Use a Java EE app server to take the burden of threading away from you :-)  Or if you need your own protocol rather than HTTP(S) or RMI, use the something like the server I developed above!  It also relieves you of threading issues.

If Yes, then you have to support many thousands of clients who need to keep their connections to the server open, so use a non-blocking server. 

3) Will my non-blocking server have to handle request which will take more than ten to a hundred microseconds to service?

If yes, use a non-blocking server that has a thread pool, like I have created above.  Make sure you have a container which does the hard threading stuff for you, so that you can concentrate on writing useful business code.

If you follow that thought process, most people would never think of using node.js.  Sadly if you look in the internet, you find people with thought processes more like this: I want to develop some app which I think will be the next big Facebook/Twitter.  I'm going to build for scale now, not when it gets big.  I'll jump right in and use node.js coz I heard its fast.  Oh and its trendy.  I'll get good press too!  Oh, and I got no experience of what it takes to make a production server and I want to live in maintenance hell.

Cheers,
Ant

PS. There seems to be much discussion about whether multithreaded is good, or whether NIO is good, but in terms of node.js, let's make the point that Javascript with it's duck typing is bad for developing quality software!  I could tolerate node.js a lot more, if it used Java or a C# :-)

Ant Kutschera replied on Mon, 2011/05/23 - 1:47pm in response to: Subbu Allamaraju

I got my facts from the linked sites.  But I didn't search the web exhaustively, because, well, I would never have finished.

IBM has taken the page down...  And it's author is a freelance programmer, so it's not exactly an IBM article.  And not everything IBM does or writes about is the best...  But I will read the article!

node.js examples are about writing servers, not about writing business solutions.  Their home page advertises how easy it is to write a low level web server.  It doesn't mention how I can deploy a website to it, without having to write lots and lots of code to do things like check security and manage sessions send the requested path to the code which handles that path. 

You don't understand my statement "it doesn't seem to specify a standardised way of writing components so that I can concentrate on writing business software rather than solving technical issues" - can you point me to the documentation page which tells me how to write a single peice of business code, without having to write an entire webserver to handle sessions, security, server management, resource management, pooling, etc?  If you have written an EJB or servlet, you will know what I mean here.

The political problems I referred to were those here: http://www.olympum.com/future/nodejs-to-v8-or-not-to-v8/.  I am sure if you search the internet, you will find articles which also say that there are no political problems.

Ant Kutschera replied on Mon, 2011/05/23 - 1:50pm in response to: Abhishek Chavan

Hi Abhi,

Is it not clear?  Java, forever!

:-)

Jose Maria Arranz replied on Mon, 2011/05/23 - 2:37pm

Ant, I agree with most of you are saying including the duck typing concern (for me it is very very important).

Some points:

1) Will I have short lived requests ?

 All decent Java web servers use some kind of "adaptative" thread pool (new threads can be created when necessary). 

2) Will there by many thousand long lived connections?

I must recognize in this case a non-blocking approach may be useful but EVER MIXED with a thread pool, otherwise you can ruin your server as you can easily find in Node.js when you do some time consuming task.

The only problem of one thread per request is memory, is not context switching, as you can see in my article you can run thousands of extreme concurrent threads with almost NO penalty, if most of your threads are stalled (usual in a Comet application) you can scale to many many thousands of alive threads (only the memory is the problem), in my article an example shows how the cost of context switching of thousands of stopped threads is zero.

In summary: I can see non-blocking in very extreme cases of very extreme concurrency, for instance a Comet application serving to many many thousands of users and many user events per second (and ever using a thread pool for non-IO tasks), and in my opinion in this case the server will be extremely slow with any approach.

 

Ant Kutschera replied on Mon, 2011/05/23 - 3:04pm in response to: Subbu Allamaraju

Hi Subbu,

Michael's article is interesting.  But wrong.

He claims: "Instead of spawning a new OS thread for each connection(...), each connection creates a process..."

Fail!  It's a single threaded process. See http://stackoverflow.com/questions/6101979/node-js-single-process-or-multiprocess/6101997#6101997.

In Michael's section "What Node definitely isn't", he says what I am saying.  And what I introduce, is my vision of a non-blocking server needs to go to become mature and compete with things like Apache, Tomcat, and other servers (not in terms of handling HTTP, but in terms of being market leaders).  Sadly, just by using Javascript instead of Java, node.js will, for me, never be an option - like I say above, Javascript's duck typing limits it too much (compiling/debugging).  It's a scripting language, not a language for writing servers, it's name gives that hint.

In the "What it's good for" section, he goes on to say:

"Node is extremely well designed for situations where you are expecting a high amount of traffic and the server-side logic and processing required isn't necessarily large before responding to the client"

Correct - and the main point is that the response needs to return asap because node's single thread blocks other incoming request from being processed until the response is written.  What I have said in my article above, is that I expect a mature non-blocking server to allow some threading so that the event queue doesn't get blocked if SOME requests takes a little more processing power.  See also my response to Jose Maria.

Michael's example on the Twitter queue is also flawed.  These are short lived requests, so there is no need for a non-blocking server.  He suggests handing the requests over to an in-memory cache - which is not good if the process crashes!  A much more robust solution would be to send the events straight onto a persistent message queue.  Where my solution is better than node.js is that the container could inject the a JMS resource into the handler, so that the programmer can concentrate on writing business code, and the deployer can worry about a standardised configuration :-)

A great critisism of Michael's article is here: http://blog.nodejitsu.com/ibm-doesnt-care-about-nodejs-people

But that critisism shows more node.js problems, namely that there are 20 templating engines and 30 MVC frameworks available for node.js today.  That is NOT good, because developers don't know which one will be best supported, long term.  How do they choose one?  Trial and error?  Instead of a standard, like you get with Java EE, you get everybody reinventing the wheel.  It's costly, and in the end, every app written on node.js is a bespoke custom solution using it's own modules.  It's typical of any immature platform - Java and .NET were similar at the start.  My article explains what I expect node.js to do in order to become mature, i.e. conform to industry standard specifications - and I propose what a standard might look like.

Cheers,
Ant

Jonathan Fisher replied on Mon, 2011/05/23 - 3:55pm

Thanks for the great article! As expected, say something nice about Java and the web2.0 dynamic language mob has shown up with a bucket of tar and feathers! :D
To inject some rational discussion, I would compare a framework like Rails to JEE. Neither Rails nor JEE were meant to handle low/level protocol communication, but both are excellent are solving business problems quickly while freely the developer from writing boilerplate code. Both Rails and JEE are capable of re-inventing the wheel (which what the main purpose of node.js seems to be), but why would you when you could just run Tomcat or Glassfish (which are both NIO capable)?

Ant Kutschera replied on Mon, 2011/05/23 - 4:28pm

Wow - http://tomcat.apache.org/tomcat-6.0-doc/aio.html

Tomcat can already do all this stuff by the looks of it, using Servlets!

It even looks like you could write your own protocol and configure it:

http://tomcat.apache.org/tomcat-6.0-doc/config/http.html

I guess:

  a) you learn something new every day,

  b) I am as guilty of reinventing the wheel as anyone working on node.js,

  c) mature platforms really can already do everything - respect to Apache :-)

 

Subbu Allamaraju replied on Mon, 2011/05/23 - 6:36pm in response to: Ant Kutschera

It would do good if you can backup each point under "The main problems are that:" with numbers and/or references. If you can't find any beyond anecdotal or heresy mentions, please say so.

Nicolas Bousquet replied on Tue, 2011/05/24 - 4:49am

@Subbu Allamaraju

I understand that as a node.js evangelist and as a strong node.js fan the kind of article Ant writed can upset you.

But the problem is are your detractor rights or not? Really I don't care the details. Node.js has two main concepts for me:

  • JS on server side using V8
  • Non blocking IO

So I would say why JS? You like JS? Maybe. Nice. Not me (to bad). But if it was only me. Only a few people do like JS on the entreprise side. I don't see so many people that like like dynamic language at all for professionnal use and big softwares. At least python, ruby or even lisp had some success. But JS is not really beloved. Using JS as the basis of the platform is not an asset. It is a problem. To many people dislike dynamically typed language, and those that like would be likely to choose another one.

Non blocking IO. Well you can do that in C. This is nowhere new you know. This as its usage. That what an OS do, or a router. Some web server use non blocking IO with sucess. That a technical low level stuff. People don't really care.

You know, here it is my personnal opinion. If I were to choose the more fun dynamically typed language I could find. The one I'd really want to use. It would be a lisp flavor. I could imagine Python. JS, no. JS is there only because Netscape introduced it. It is not especially good.

If I'd wanted hundred  thousands of concurrent task or more on my server, I would go for TypeSafe the new company founded by Martin Ordersky and the Akka creator. They have a typed language that already has some momentum on the server side. They can use the whole JEE stack and libraries if need. They can build on the java echosystem. They have the scala language that is statically typed with IDE support improving everydays.

Or I would go for lift. It is build uppon Jetty non blocking IO support and use scala actor for web processing. It is fast. It work great and is used by novell.

node.js is a fun project. But it doesn't look professional. It doesn't look mature. Subbu, have fun with it. Life is short and that the main point. Have fun with it. You can find other people that like it, and make a good living with it, I hope.

But it will never be the next big thing. Many people will think that you are loosing time and will view your baby more as a pet and fun project than anything else. They will not want that for their company. You can blame them, but the problem will remain.

Ant Kutschera replied on Tue, 2011/05/24 - 7:54am in response to: Subbu Allamaraju

Hi Subbu,

It isn't my job to convince people not to use node.js.  But if node.js wants to make it big, then it has the job of convincing hundreds of thousands of people like me that we should use it.  This article is about why I currently will not use node.js, and what I would like node.js to offer before I will consider using it.

But in the interest of making my article better, I will tell you what I was thinking when I wrote those points down.

    1. you deploy Javascript to the server

To me, this is a problem because Javascript is a duck typed language.  The compiler (well, er, there isn't one...) can't tell you about any problems you might have if you for example try and read an attribute in an object and spell it's name wrong.  So whenever I develop with Javascript, I end up in the debugger a lot more than I would like to, which I find inefficient.  For me, code that gets deployed on a server needs to be VERY robust, because you don't want your server to ever crash, and I find it very hard to write robust code with Javascript, compared to using Java.  Javascript cannot be entirely statically analysed either, making it hard to have tools which can measure your code and highlight potential problems, much like findbugs or sonar can do for Java.  Of course, this is a subjective point, and some people will perfer Javascript over Java.

    2. it doesn't seem to specify a standardised way of writing components so that I can concentrate on writing business software rather than solving technical issues

On the node.js site, there are examples of how to write a server, but they are very low level.  I appreciate that node.js is still young, and is about writing low level code.  That said, I understand that there are many modules (2000+), with up to 10 new packages per day being written.  For me, that is a problem, because if there are say 30 MVC modules, I don't know which one to use.  How do I know that the one I choose will be well supported in the future?  It makes decision making hard.  If however, node.js were to lay down standards, like the interfaces which an MVC framework needs to implement, or interfaces for sending emails, so that I don't end up with quasi vendor (module) lock in, then I would have less difficulty in choosing a framework, because I would know that my code would run long term.  If a module disappeared or became out dated, I could swap it out for a different that implements the same standards, with no or only few changes to my code.

    3. while it is rumoured to be fast, studies such as this suggest it's half as slow as Java

A reference has already been supplied in the main article at that bullet point.  Show me an article which says Java is slower than node.js - I'm sure the internet has one - you can find anything you like on the internet :-)

    4. compared to Java, the node.js API and Javascript libraries available today are immature - think about things like sending email, ORM, etc.

Similar to the point made above about standards really.  I am not the only one with these concerns; see www.quora.com/What-are-the-disadvantages-of-using-Node-js#  Take ORM as an example.  How long has ORM been available to serverside Javascript when compared to Java or .NET?  There is no standard API that I can use in node.js so that I don't get locked to a particular module or package.  Are all the bugs ironed out?  Sure, one day there will be mature ORM in node.js, perhaps even conforming to a standard set by node.js or some independent Javascript body.  But think back to why I wrote this article and it's predecessor (also available on DZone - click on my profile link to see it).  I was asking why people would want to write node.js, rather than build up a non-blocking server based on existing proven technologies like Java or .NET.  I have no problem at all with non-blocking on a single thread, if that is what you want to do, but what I don't understand is why people want to start from virtually scratch.

    5. node.js has political problems because it relies on Google. If Google don't want to support Javascript on the server (their V8 engine is designed for Chrome, client side), and node.js needs a patch or development on V8 to handle a serverside issue, they might never get it. OK, like I have a chance to get a Java bug patched by Oracle ;-)

I referenced where I got that from above.  Here it is again: http://www.olympum.com/future/nodejs-to-v8-or-not-to-v8/  OK, it is more of an opinion than a fact, I agree.  Like I said, I have the same problem with Java/Sun/Oracle too!  But when you choose a technology to use, things like this need to be considered.  Take the discussion of threads.  Let's say the node.js community decides one day that they do indeed want threads in node.js.  But Google doesn't - they don't need it for their browser.  Threads is something that needs to come from V8, because it's core to the platform.  It also potentially needs language changes, although not necessarily.  At least with Java I have the JCP and I can submit a JSR and if the community feels strongly enough about it, I will eventually get it in Java.  Might take 5 years... but at least I have that option.

Cheers,
Ant

Alessandro Santini replied on Tue, 2011/05/24 - 10:52am in response to: Nicolas Bousquet

But it will never be the next big thing. Many people will think that you are loosing time and will view your baby more as a pet and fun project than anything else. They will not want that for their company. You can blame them, but the problem will remain.

I would be careful making such strong statements: HP included Node.js in its WebOS 2 operating system. I do not dare to say it means huge adoption, but words like never should be handled with more care.

Ryan McDonough replied on Tue, 2011/05/31 - 6:39am in response to: Alessandro Santini

That is an excellent point Alessandro. Node.js is very light weight making it very attractive for devices with limited resources. For example, I can run Node.js on my Synology NAS with its scant amount of memory. I can't run Tomcat, or even a JVM. For such a device, a JVM might be overkill. Node.js is lean and mean and I wouldn't be surprised to see Node.js gain some traction in the embedded space.

Kaan yy replied on Tue, 2012/07/10 - 8:43am

Absolutely, I do not understand to insist on node.js.

Today I can not find a mature oracle driver for node.js. With java (or any jvm dynamic lang.) you can already take all the benifts that node.js offer.

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.