Archive for January, 2009

Install Erlang on Mac OSX from sources

If you don’t want to use Flink or MacPorts to get you up and running with Erlang environment then you can follow these steps to compile and install Erlang from sources on your Mac.

First make sure you have installed latest Apple’s Xcode Developer Tools which will provide gcc compiler among the other toys.

The next step is to download Erlang sources and man pages. At the time of writing this post the latest version of Erlang was R12B-5. Consult the Erlang download page for details of current release. Let’s get the above mentioned files :

%  wget http://erlang.org/download/otp_src_R12B-5.tar.gz
%  wget http://erlang.org/download/otp_doc_man_R12B-5.tar.gz

Untar the sources and change current directory:

%  tar xzvf otp_src_R12B-5.tar.gz
%  cd otp_src_R12B-5

What we have to do now is to do usual configure/make/make install steps of compilation. To check available configuration options run:

%  ./configure --help

I will configure Erlang with:

%  ./configure --prefix=/sw/erlang --enable-threads
--enable-smp-support --enable-kernel-poll

Next steps are creating the target directory, compilation and installation, uncompressing the man pages:

%  sudo mkdir /sw/erlang
%  make
%  sudo make install
%  sudo cp ../otp_doc_man_R12B-5.tar.gz /sw/erlang/
%  cd /sw/erlang
%  sudo tar xzvf otp_doc_man_R12B-5.tar.gz
%  sudo rm otp_doc_man_R12B-5.tar.gz

The last step will create man folder in /sw/erlang. Everything almost ready. We should add Erlang to the PATH and man pages to the MANPATH i.e. in ~/.bashrc.

export PATH=$PATH:/sw/erlang/bin
export MANPATH=$MANPATH:/sw/erlang/man

The last step is to load the updated .bashrc file:

%  . ~/.bashrc

Everything should be up and running now. Try:

%  man erlang
%  erl

Popularity: 63% [?]

Comments (2)

On dynamic cluster configuration using Terracotta Cluster Events

World awaits Obama’s magic but I’ll write about something slightly more down-to-earth. I’ve been thinking recently about an implementation possibilities for the dynamic cluster configuration. Lets simplify and assume that a system will consist of identical nodes which can take on different responsibilities depending only on a configuration on the node. The communication between nodes would be achieved by using some kind of messaging technology. So, where am I going with this? It would be good to be able to dynamically reconfigure the cluster nodes to serve as required at the time. The cluster can obviously change over time, some nodes might fail, some other nodes might join the cluster and having a cluster manager which can apply configuration to the current cluster shape and size would be great from flexibility and maintainability perspective. And then the Terracotta comes into the picture. Its feature which can be really useful here is set of cluster events which one can listen to:

  • com.tc.cluster.event.thisNodeConnected — The local client connecting to a Terracotta server
  • com.tc.cluster.event.thisNodeDisconnected — The local client disconnecting from a Terracotta server
  • com.tc.cluster.event.nodeConnected — Another client connecting to a Terracotta server
  • com.tc.cluster.event.nodeDisconnected — Another client disconnecting from a Terracotta server

To consume the events we will use javax.management classes and first we will get reference to a MBeanServer:

MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();

Then we should get the cluster bean. I created small helper class ClusterUtils as described in the Terracotta JMX Guide:

ObjectName clusterBean = ClusterUtils.getClusterBean(mbeanServer);

We can alrady check what is the identificator of the current node:

String nodeId = mbeanServer.getAttribute(clusterBean, "NodeId").toString();

The only remaining step is registration to the JMX notifications:

mbeanServer.addNotificationListener(clusterBean, new SimpleJmxNotificationListener(), null, null);

Where the SimpleJmxNotificationListener implements javax.management.NotificationListener. We are ready now to consume the events and react accordingly to the changes in the size of the cluster. There is also a JMX Util library that makes using Terracotta Cluster Events even more easy.

By default the cluster nodes will be indentified by strings in format ClientID[SEQ_NUMBER] like ClientID[85]. If we wanted to set different identification in theory we could use -Dtc.node-name=NAME property when starting a given JVM. However there is currently (Terracotta 2.7.1) an open problem with handling of that property which hopefully will be resolved soon.

Everything what is needed to create a dynamic cluster manager is in place now. Cluster manager would be deployed on each node and share own state in Terracotta cluster. It is not difficult to imagine creating a bit of logic to handle connections/disconnections of new nodes in a cluster and dynamically reconfigure the existing nodes to accommodate to the change. There is always a recurring topic of partitioning when using Terracotta, how to follow paradigm of locality of reference when building a low latency, scalable systems. Combination of the cluster management described above with dynamic subscription to messaging topics with sticky routing could be a nice solution to the problem. Just musing…

Popularity: 45% [?]

Comments (2)

Last value queues in Apache Qpid

Apache Qpid is an open source implementation of Advance Message Queuing Protocol (AMQP), an emerging open standard for inter-operable Message Oriented Middleware (MOM) communication in financial market data delivery. I have been looking recently at Red Hat MRG Messaging which is based on Apache Qpid.
The feature of Qpid which I wanted to write about today is called Last Value Queues. Definition from MRG User Guide:

“The last value queue type causes logically updated versions of previous messages to appear to overwrite the older messages. To use this feature, add a qpid.last_value_queue key to the arguments supplied. The value of the key is irrelevant. Messages published to the queue then need to specify a value for the qpid.LVQ_key in the headers of messages they publish. The last value queue uses the value of the qpid.LVQ_key to determine whether a newly published message is an update to an existing message on the queue. If this is the case, the new message will appear to overwrite the older message. A subscriber that requests messages after this has occurred will see only the newer message.”

Common example would be a queue with latest price updates per symbol when we are interested only in the last value per instrument. The documentation of MRG Messaging mentions only last value queues defined by providing qpid.last_value_queue parameter when creating a queue. There is also slightly different implementation of this feature defined by parameter qpid.last_value_queue_no_browse. The difference is described on qpid website.

Let start and create a last value queue using qpid-config tool:

qpid-config add queue lvq --last-value-queue

Check if the queue has been created:

qpid-config queues

Queue Name                                        Attributes
======================================================================
lvq                                               --last-value-queue

The messages with the same value of the qpid.LVQ_key property will be replaced, so if we wanted to write simple price publisher that publishes 12 messages of four symbols SYMBOLS = new String [] {”Crude”, “Gold”, “Silver”, “Copper”} which uses the last value queue feature the code would look like:

Destination destinationQueue = new AMQQueue("amq.direct", "lvq");
MessageProducer producerQueue = session.createProducer(destinationQueue);
TextMessage txtQueueMsg = session.createTextMessage();
for (int i=1; i < = 12; i++) {
    String symbol = SYMBOLS[(i-1)%4];
    txtQueueMsg.setStringProperty("qpid.LVQ_key", symbol);
    txtQueueMsg.setText(String.format("Tick %d for symbol %s", i, symbol));
    producerQueue.send(txtQueueMsg);
    log.info(String.format("Producer: sent message => %s",  txtQueueMsg.getText()));
}

Let’s create a synchronous client to consume the messages:

Destination destinationQueue = new AMQQueue("amq.direct", "lvq");
MessageConsumer consumerQueue = session.createConsumer(destinationQueue);

boolean finished = false;
while(!finished) {
    TextMessage message = (TextMessage) consumerQueue.receive(5000);
    if (message != null) {
        log.info(String.format("Consumer: received message %s key=%s", message.getText(), message.getStringProperty("qpid.LVQ_key")));
        message.acknowledge();
    } else {
        log.info("Timeout");
        finished = true;
    }
}

Assume that consumer subscribed to the queue after publisher finished publishing the 12 messages. In this case the consumer will receive only 4 messages, one per symbol:

Consumer: received message Tick 9 for symbol Crude key=Crude
Consumer: received message Tick 10 for symbol Gold key=Gold
Consumer: received message Tick 11 for symbol Silver key=Silver
Consumer: received message Tick 12 for symbol Copper key=Copper

Popularity: 84% [?]

Comments (2)

Close
E-mail It