Monday, 23 July 2018

NodeJS & Apache Kafka & JMS

Apache Kafka is a distributed publish-subscribe messaging system and a robust queue that can handle a high volume of data and enables you to pass messages from one end-point to another.

Kafka is suitable for both offline and online message consumption. Kafka messages are persisted on the disk and replicated within the cluster to prevent data loss.

Kafka is a unified platform for handling all the real-time data feeds.

------------------------------------------------------------------------------------------

Using Node.js as the backend technology, makes the application single language dependent (One Code Base) i.e. JavaScript is used in both client-side as well as server-side. This helps in -
Ryan Dahl introduced a run-time environment called Node.js which can be used to create a web server, file server, tcp server and many more.
Netflix migrated from java to nodejs
All APIs of Node.js library are asynchronous
Node.js uses a single threaded program and the same program can provide service to a much larger number of requests than traditional servers like Apache HTTP Server.
Node.js has absolutely no dependencies and also jells perfectly with any possible client-side technology like Angular, Reactjs etc. and any database like MySQL or MongoDB.
Uses an event-driven, non-blocking (asynchronous) I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
Is an open-source server side run-time environment built on Chrome's V8 JavaScript engine.
If any application involves lots of calculations which requires CPU for processing is not a fit for node.
Node shines well for applications which involves lots of I/O bound operations
Node.js is not a silver bullet for developing software and definitely not suitable for everything especially large-scale, mission-critical enterprise applications mainly because of its single threaded architecture, event-driven async programming model, limited transaction management support, and a few other constraints.

Since Node.js has a single-thread JavaScript event loop, when it executes long-running or high computational intensive tasks (which is quite common in enterprise applications), it queues all the incoming requests to wait for execution. This will result in poor performance.

So, for typical enterprise applications (e.g. batch processing) where you need multi-threaded execution with controlled and cohesive inter-thread communication, Node is not suitable.

Also, everything is asynchronous—which hurts. Coding consists of callbacks within callbacks within callbacks… it’s a Callback hell—pretty messy code, very difficult to understand and maintain. There are ways for having better code and managing callback hell, but then we are relying too much on having good practices and disciplined programmers.

Node developers generally initialize webserver and run business code in the same process—there is no isolation between the application server and business process which other mature servers like Tomcat or Apache HTTP servers provide. Also, not having any isolation leads the server to crash if business code throws some exception.

The weak type nature of JavaScript and Node.js makes it easy to leak defects, no compilation phase, and no type checking meaning that code is lot more prone to bad references or null pointer exceptions which are discovered at runtime. Especially with large enterprise applications having larger code and multiple developers working on the same code base, the missing types are more a problem for productivity than an advantage. Actually, in weak typed languages, the programming discipline must be even stricter than in strongly typed ones.

There are a few other limitations which will prevent Node.js from being a choice enterprise application technology stack. There's no support for distributed transactions, limited debugging & IDE support (StrongLoop debugger works only in a couple of browsers), a lack of standard and matured libraries, and a lack of a good IDE which seriously impacts development. According to my experience, explicitly typed languages are more readable, generate robust code, and have good IDE + testing tool support.

JDK 7 onwards, Java also supports buffer oriented, Non-blocking I/O using channels. Basically, with the help of NIO, data is read from channels into buffers and written from buffers into channels. Even in Servlet 3.1, which now supports NIO using Read & Write listeners, has callback methods. These methods are invoked only when the content is available to be read or written without blocking.

JDK 7 onwards, Java also supports buffer oriented, Non-blocking I/O using channels. Basically, with the help of NIO, data is read from channels into buffers and written from buffers into channels. Even in Servlet 3.1, which now supports NIO using Read & Write listeners, has callback methods. These methods are invoked only when the content is available to be read or written without blocking.

As we know, Node.js achieves much of its speed because of it is single threaded (no context switching), asynchronous event-driven, and supports non-blocking I/O. But likewise, the Java ecosystem has a few options like Spring Reactor, Vert.x, and Akka which are promising event-driven and non-blocking server frameworks that can utilize multiple CPU cores for achieving high scalability without the complexity of handling threads. Performance-wise also, if you ignore the warm-up time, the absolute performance of Java applications is much better. By the way here is one of the latest performance test comparisons of several web application platforms which clearly shows many Java-based frameworks like Servlet, Jersey, Tapestry, Dropwizard, etc. are really fast.

mongoose is one among the built-in modules used to connect with MongoDB from Node.js application.

import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

@Stateless
public class JMSMessageSender implements MessageSender {

@Resource(mappedName = "jms/ConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/Queue")
private Queue queue;
private Connection connection;

@Override
public void sendMessage(String message) throws MessageSenderException {
Session session = null;
MessageProducer messageProducer = null;
TextMessage jmsMessage = null;

try {
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(queue);
jmsMessage = session.createTextMessage();
jmsMessage.setText(message);
messageProducer.send(jmsMessage);
} catch (JMSException e) { }
}

------------------------------------------------------

@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class JMSResponseMessageReceiver implements ResponseMessageReceiver {

@Resource(mappedName = "jms/ResponseConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/ResponseTopic")
private Topic topic;
private Connection connection;
private Session session;
private MessageConsumer consumer;

connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(topic, "JMSCorrelationID = '" + uuid + "'");

Message message = consumer.receive(timeoutMillis);

if (message instanceof TextMessage) {
LOGGER.debug("Text message matched selector with ID {}", message.getJMSCorrelationID());
result = ((TextMessage) message).getText();
}

No comments: