Jul 2, 2012

ActiveMQ Broker Networks - Think, Demand Forwarding Bridge


When we build a mental model of how something works, our initial images are always tainted by our experience of the words used to describe it. Sometimes we have to remold our existing perception of the words based on our new learning context, when the words have multiple meanings, we can often start from the wrong premise.

With this in mind, I want to share the meaning of the words I have used to describe ActiveMQ Broker Networks and provide some context to the words. The hope is that this will help build a model in your mind that is a valid reflection of their reality.


A broker network is two or more brokers that are connected via a "Demand Forwarding Bridge". Lets expand on each word in turn, but in reverse:

Bridge

This part is easy, a bridge it is a link between two brokers. The bridge is identified by the transport url of the remote broker it will connect to. The bridge is realized by a socket connection over which messages will pass for specific destinations. A bridge is initiated on a broker via xml configuration of the form:
 <networkConnector url="scheme://host:port" />

Forwarding

The directionality is implicit in the forwarding. Messages flow in one direction only, from the local broker where the bridge is created, to the remote broker where messages end up. Messages are forwarded, which means they are consumed from the local broker, and sent to the remote broker. This is regular JMS send semantics, the message is acknowledged locally when the send to the remote broker completes. So a message only lives in one broker at a time.

Demand

The bridge is aware of demand. In ActiveMQ, demand for messages comes from consumers. A bridge will only forward messages if it knows that there are consumers for that destination on the remote broker. The trick here is the use of ActiveMQ Advisory messages. When a bridge is started, it registers a  consumer with the remote broker for consumer advisory messages. In this way, the bridge becomes aware of the creation and removal of consumers on the remote broker. The bridge reacts to a new consumer advisory notification by creating a local (proxy) consumer for that destination. When this proxy consumer gets a message dispatch, it responds by forwarding (sending) the message to the remote broker. When the remote consumer disconnects, the corresponding remove advisory notification fires and the local proxy consumer is removed. Messages are no longer forwarded for that destination. In this way, the bridge is led by demand.

Next time you encounter <networkConnector ... /> in xml configuration, think of these three words, Demand, Forwarding, Bridge", then proceed to (re)build your mental model.



Nov 22, 2011

ActiveMQ - multiple kahaDB instances (mKahaDB) helping reduce journal disk usage

The default store implementation in ActiveMQ, KahaDB, uses a journal and index. The journal uses a sequence of append-only files to store messages, acknowledgements and broker events. The index holds references to messages on a per destination basis. Essentially, the index holds the runtime state of the broker, mostly in memory, where as the journal maintains the persistence store of  raw data and events. It is the journal of record in a sense.
Periodically, unreferenced journal files are removed through a garbage collection process, so disk usage is kept in check.
In the main, this scheme works well, however, when multiple destinations on a broker are used in very different ways, it can lead to excessive disk usage by the journal. What follows is some detail on a solution to that problem.

Mixed destination usage; frequent fast tasks vs infrequent slow tasks
Imagine a toy makers order-processing. There are two types or orders, custom and standard. A custom order takes a few days to fulfill, a standard order takes a matter of hours. You can easily imagine two order queues, standard and custom. Now imagine that we only process custom orders once a month but process standard orders all the time. So we expect a large backup of custom orders that is slowly consumed at the start of each month and a steady load on the standard order queue.

What the broker sees
From a broker perspective, in the single shared journal, there will be a batch of journal files that are filled with custom order messages. Subsequent journal files that will have mostly 'standard order' messages and acknowledgements with the odd acknowledgement for a 'custom order' message. The sporadic distribution of  acknowledgements for 'custom orders' in the journal files can be problematic because even when that journal file no longer contains any unacked 'standard order' messages, it must still be retained.

Some background on the need to retain journal files
Journal data files are append only. Both messages and acknowledgements are appended, nothing is deleted from a data file. Journal data files that are unreferenced are periodically removed (or archived). The idea is that the index (JMS destination state) can be recreated in full from the journal at any point in time. Any message without a corresponding acknowledgement is deemed valid.


Referenced journal files

In the simplest case, a journal file is 'referenced' if it contains messages that have not been acknowledged by a consumer. The more subtle case reflects the persistence of acknowledgements (acks). A journal file is 'referenced' if it contains acks for messages in any 'referenced' journal file. This means that we cannot garbage collect a journal file that just contains acks until we can garbage collect all of the journal files that contain the corresponding messages. If we did, in the event of a failure that requires recovery of the index, we would miss some acks and replay messages as duplicates.

Problem
So back to the broker perspective of our toy makers order processing. The first range of journal data files remain till the 'custom orders' queue is depleted. Custom order message acknowledgements get dotted across journal files that result from the enqueue/dequeue of the 'standard orders' queue and the end result is lots of referenced journal files and excessive disk usage.

Solution
Reducing the default journal file size can help in this case, but at the cost of more runtime file IO as messages are distributed across more files. In an ideal world, the 'custom order' queue could be partitioned into its own journal where linear appends of messages and acks would result in a minimal set of journal files in use. Correspondingly, the 'standard order' queue with their short lived messages could share a journal.

With the Mulitple KahaDB persistence adapter, destination partitioning across journals is possible. It provides a neat solution to the scenario described above.
Replacing the default persistence adapter configuration:

<persistenceAdapter>
     <kahaDB directory="${activemq.base}/data/kahadb" />
</persistenceAdapter>

with:

<persistenceAdapter>
    <mKahaDB directory="${activemq.base}/data/kahadb">
      <filteredPersistenceAdapters>
       <filteredKahaDB queue="CustomOrders">
        <persistenceAdapter>
          <kahaDB />
        </persistenceAdapter>
       </filteredKahaDB>
       <filteredKahaDB>
        <persistenceAdapter>
          <kahaDB />
        </persistenceAdapter>
       </filteredKahaDB>
      </filteredPersistenceAdapters>
    </mKahaDB>
</persistenceAdapter>
  
The mKahaDB (m, short for multiple) adapter is a collection of filtered persistence adapters. The filtering reuses the destination policy matching feature to match destinations to persistence adapters. In the case of the above configuration, the 'custom orders' queue will use the first instance of kahaDb and all other destinations will map to the second instance. The second filter is empty, so the default 'match any' wild card is in effect.
This configuration, splitting the destinations based on their usage pattern over time, allows the respective journal files to get reclaimed in a linear fashion as messages are consumed and processed, resulting in minimum disk usage.


Overhead

When transactions span persistence adapters, there is an additional overhead of local two phase commit to ensure both journals are atomically updated. Two phase commit requires that the outcome is persisted so there is an additional disk write required per transaction. This can be avoided by colocating destinations that share transactions in a single kahaDB instance. When transactions access a single persistence adapter or when there are no transactions, there is no additional overhead.


Alternative Use Cases: Relaxed Durability Guarantee

Each nested kahaDB instance is fully configurable so one scenario where the use of different persistence adapters makes sense is where your durability guarantee is weaker for some destinations than others. JMS requires that a write be on disk before a send reply is generated by the broker. To this end, a disk sync is issued by default after every journal write. This default behavior is configurable by the kahaDB attribute enableJournalDiskSyncs. If some destinations don't need this guarantee, they can be assigned to a kahaDB instance that has this option disabled and have their writes return faster, leaving it to the file system to complete the write. Here is an example configuration:


<persistenceAdapter>
    <mkahaDB directory="${activemq.base}/data/kahadb">
      <filteredPersistenceAdapters>
      <filteredKahaDB queue="ImportantStuff">
        <persistenceAdapter>
          <kahaDB />
        </persistenceAadapter>
      </filteredkahadb>
      <filteredkahadb queue="NotSoImportantStuff">
        <persistenceAdapter>
          <kahaDB enableJournalDiskSyncs="false"/>
        </persistenceAdapter>
      </filteredKahaDB>
    </filteredPersistenceAdapters>
  </mKahaDB>
</persistenceAdapter>


Apr 22, 2011

Government agencies: cut future IT spend - share costs, invest in open source

Open letter to Minister of State for Public Service Reform, Mr. Brian Hayes TD

Hi Brian,
I would like to share a quick response to my reading of the Irish times article: State to demand price cuts from suppliers to reduce €16bn bill.

In order to best serve the needs of the Irish people right now and into the future, you need to seriously consider open source IT solutions. Across all departments and across all of Europe, government IT departments should be collectively investing in free open source solutions that solve their common IT needs.

Investment in open source IT solutions seeds innovation and is a commitment to shared future value. Investment in proprietary IT solutions is an innovation tax and a commitment to repetition.
This is not some sort of Marxist rant; open source is the best way to innovate. Open source software is a key reason amazon, google, twitter, facebook etc. emerged; they stand on the shoulders of giants.

I imagine this would mean a small shift in how government IT is organised. You would need to extract real value from the smart people therein. Rather than out sourcing decisions to global consultancy companies, you allow a shared need to be met from within.
You enable innovation, by allowing smart individuals to take ownership of both the problem and the solution and most importantly, to share the fruit of their labour.

The bottom line is this, all of the government departments have IT needs in common, they are much more alike than they wish to admit. The also share these needs with other governments thoroughout Europe.
There is no reason to constantly reinvent the wheel. We just need to enable people to share and evolve the best designs. Open source provides the freedom and motivation to do just that.

Apr 10, 2011

Consider Unhosted and open source for eHealth and eGov #DERIopenDay

DERI Galway produced an insightful open day on their developments in the semantic web of linked data. While I listened, two thoughts kept recurring that I want to explore. Chances are I am preaching to the choir but shucks, just in case I am not...

For a web architecture of the future look at Unhosted
At the root of the problem of siloed data and fragmentation (the database hugging phenomena) is the issue of ownership. Institutions have data that they don't really own because that data is of a personal nature. The collection of data is theirs, but not the individual components.
With Unhosted, the ownership problem is turned on its head. Users and aggregators of data only have a 'handle' (a URI) to personal data. A handle that is only useable with permission. Collections of data containing 'handles' can safely be shared. Granted, lots of issues need to be ironed out, but I think the architecture is on the right track and the concept is bang on.

Open source your research
Lots of what you do is plumbing. For new plumbing to be broadly adopted it needs to be better and it needs to be cheap. Publish and be damned. If the research is great the plumbing will proliferate at very little cost. If it does proliferate, you continue to research and innovate and profit above the new infrastructure, it is all good. If it does not proliferate..., well open source was not the problem!

Enterprise Ireland: open source can be a viable business model for shared infrastructure research. It is a world of constant iterative improvement. The profits are smaller but the rewards are greater because simply put, value shared is value multiplied.
In essence, open innovation puts the focus on execution rather than protection, if puts everyone on the front foot.

Oct 29, 2010

Independent FuseSource, a future of shared value

The future is bright for FuseSource and open source adoption, the challenge is to spread the word on shared value so more organisations can benefit.

At FuseSource, we are independent, we have a proven subscription based business plan and we have a clear message: "The experts in open source integration and messaging". A message that that is backed up by our Apache committers and consultants, many of whom are project founders. We are on the right track.

I think the growth of FuseSource is testament to the fact that enterprises are understanding a key benefit of liberal licensed open source:

Value shared is value multiplied

Put simply, each deployment of Apache ServiceMix, Apache ActiveMQ, ApacheCXF and Apache Camel, contributes positively to the shared pool of knowledge about these products. At FuseSource, all enhancement and fixes are delivered first at Apache, so everyone can benefit immediately. A great innovation this week becomes the start point for a new deployment next week. There are no barriers to entry. We all get smarter together.

The reality is that open source consultants rarely repeat themselves, work done for one client is work done for everyone. It is a model of shared incremental improvement. It is constantly challenging work, but most rewarding and always interesting.

My hope is that more organisations, where information technology (IT) is not the core of their competitive advantage, will see the benefit of an open collaborative approach to infrastructure investment. The approach is simple: Use the same open source products as others, invest in those products, contribute back and reap the benefits of the contributions of others. Though we consider our selves individuals, when it comes to what we need computers to do, we are mostly the same.

If you work in health care, government or retail and have an IT problem, somewhere in the world some one is struggling with the same problem as you. You need not be alone, you just need to share a common language and join the community. Open source infrastructure can be that language.

Note: those organisations that use IT for competitive advantage are already on the open source band wagon, layering higher value services over existing open implementations, standing on the shoulders of giants. They just don't always have the same incentive to share.

Aug 16, 2010

Reminder: JMS is client server infrastructure; update broker ∴ update client

Often we get the following question:
If I upgrade the broker to version 5.x, do I also need to upgrade all my clients?
 The short answer is:
maybe, but error on the safe size and upgrade your clients if it does not cause too much disruption.

For the longer answer there are at least two things to consider:
  • Does the reason for upgrade include the need for fixes that affect client side code? If yes, then obviously update all clients. (Issues of this kind typically focus on some aspect of the JMS API or consumer delivery semantics.)
  • Is there an increment to the openwire protocol version? if so, does it affect me? read on...

Does an update to the openwire protocol version affect me?
The openwire protocol is the set of commands that is used to communicate between an ActiveMQ client and an ActiveMQ broker (and from broker to broker in a cluster scenario). The openwire protocol supports version negotiation such that an old client can negotiate the lowest common version with it's peer and use that version. As a result, in most cases, old clients can work as expected with a newer broker.

There are two potential pitfalls that you should be aware of:
  • fixes/features that depend on the openwire version update.
  • the ever increasing and incomplete version testing matrix.

Fixes or features that depend on the openwire version update
These are typically fixes that require additional information to be passed from the clients to the broker or vice versa. Some examples include the addition of a last delivered sequence id parameter to a consumer close command such that the redelivery count could be more accurately calculated. Another is the addition of a reconnecting flag to a connection command that allows duplicate suppression to be implemented consistently at the transport connection level. In some cases it is not obvious if an issue requires a protocol update without some consideration of the implementation, if in doubt ask on the activemq mailing list.

The ever increasing and incomplete version testing matrix
With every protocol version change, there are new additions to the client/server testing matrix. In ActiveMQ, virtually all tests assume a uniform openwire version, with the exception of a few that validate negotiation. The net result is that validation of the compatibility matrix is largely completed by the community. This works in practice but it is important to be aware of. If you are in doubt as to whether a particular scenarios will work across a broker version mismatch, be sure; ask the computer yourself with a little test.

In summary, If you update the broker, you also need to update the clients; or at least consider it!

Jan 18, 2010

ActiveMQ (prefetch and asyncDispatch) negative destination inflight values in Jconsole explained

While tracking down an issue for a customer over the past few days I noticed the inflight count for my destination in jconsole has a negative value. On closer inspection, I found that the value was fluctuating wildly with negative values before settling down again to a more reasonable positive range. I took a detour to investigate and it turns out this behavior is expected. The negative values are the result of prefetch and asyncDispatch, let me explain with a little note to self:

The use case included a pre filled queue with ~30k messages and multiple(10) consumers which dequeued a small amount(again 10) of messages before disconnecting and immediately reconnecting. In this case, a prefetch value of 10 is ideal, but with the default prefetch value of 1000, the broker is busy dispatching messages to the consumer long after it has decided to quit. In addition, with asyncDispath, while dispatch to a consumer is instigated by the broker, the actual delivery is delegated, to the broker transport connection worker thread. This means that the delivery attempts back up on the individual transport connections rather than slowing down the broker.

The destination inflight count is a measure of the number of messages that have been dispatched by the broker but not yet acknowledged by any consumer. On each dispatch completion by the worker thread, the inflight value is incremented. The decrementing normally happens on a message acknowledge. In the event of a consumer closure with unconsumed messages, the remaining value is decremented when the consumer closes.

This is the crux. From the broker perspective, on consumer closure, it has dispatched 1000 messages and got an ack for 10 so it needs to decrement the inflight by 1090 990 (thanks for the correction Arjan). But from the perspective of the worker thread, busy doing the actual dispatch, it still has a lot of incrementing to do. The negative values arise from the consumer closure occurring before async dispatch is complete. When there are many concurrent consumers, the negative swing can be quite noticeable and quite large.

The good news is that this is perfectly fine, the books are kept in balance and there is eventual consistency. In addition, using either of a prefetch value of 10 or asyncDispatch=false ensures that the negative values do not occur as the broker is kept directly in step with message delivery to the consumer. In general though, the an appropriate value of prefetch is the correct solution if it is known in advance that a consumer will do work in batches.

Oct 15, 2009

Interpreting the ActiveMQ 5.3.0 SpecJMS2007® Result

Hot on the heels of the latest Apache ActiveMQ release, official SpecJMS2007® Results appear. ActiveMQ does 156 vertical and 60 horizontal. But what does that mean?

Some Background
SpecJMS2007® is a representative, long-running, comparative test. Let me take each of these in turn.

By representative, I mean that it contains a mix of business interactions that utilises point to point (or queue semantics) and publish/subscribe (topic) semantics. The message sizes vary within limits using random generators and there is a mix of non-persistent and persistent messages. All persistent messages are delivered and consumed within transactions. In reality, the interactions are based around a supermarket supply chain application which provides a rich tapestry for realistic actor interplay. Supermarkets querying suppliers, suppliers interacting with distribution centers and throughout, management in headquarters, keeping track of all dealings.

By long running, I mean that the scenario lasts a minimum of 30 minutes, excluding a warm-up period. The verification phase is based on periodic throughput and response time sampling during that period. In this way, the test verifies the sustainable load characteristics of a JMS Broker.

By comparative, I mean that the test artifacts and environment are completely specified such that results are totally reproducible. For example, if the broker implementation is swapped out from the ActiveMQ submission bundle, a comparable result for the same platform can be obtained. The platform (or OS and hardware configuration) must be maintained to produce comparable results. This focuses the comparison on the implementation of the broker, which is the intention.

Explain the Numbers

The numbers are seed values. They provide the base value or multiplier on which subsequent decisions like the number of destinations, quantity of messages etc. are determined for a given test run. An increase in the seed value has a cascade effect on the overall load that is placed on the system. If the seed value is too high, the overall load will result in a failed test. Either because of unacceptable throughput variance or because of response times exceeding predetermined ranges. To pass the test for a given seed value, all response time and throughput expectations must be met.

The vertical and horizontal qualifiers refer to the SpecJMS2007® workload topologies. The topologies are not directly comparable because the seed multipliers have different effects in both topologies.

Vertical
As the seed value increases, the vertical scenario aims to increase the number of messages that are processed for a given number of destinations. So in the supermarket supply chain parlance, this means increasing the quantity and variety of stock that is maintained and the frequency of replenishment of said stock. The number of supermarkets and suppliers etc. remains constant as the base seed value increases. In this way, the ability of the broker to deal with increased load on existing destinations is explored. Another way of looking at this is that the depth of the destinations rather than the number of destinations is increased.

Horizontal
As the seed value increases, the horizontal scenario aims to increase the number of destinations while using a fixed load of messages. This corresponds to adding more supermarkets, suppliers and distribution centers. The quantities of stock and the frequency of replenishment is constant. In this way, the ability of the broker to deal concurrently with large numbers of destinations is explored.

In short, the numbers are meaningless in isolation as they are the units of SpecJMS2007® performance measurement and these units have no real-world corollary. Where they are useful is when used in comparison with another run of the SpecJMS2007® test using a different JMS implementation or with some broker configuration tweak.

For example, there are two platform variants of the results, one with Hyper Threading(HT) enabled and the other with HT disabled. The effect is significant indeed, with the vertical successful seed value going from 138 to 156 and horizontal from 52 to 60. So turn HT on!

Jul 14, 2009

Apache ActiveMQ Out Of Memory!

Apache ActiveMQ is adaptable and configurable. A large part of its popularity is due to its flexibility. However, it comes with a default activemq.xml configuration file that cannot possibly suit everybody's needs. The default configuration is a compromise between memory utilisation, low latency and high throughput, with a smattering of feature demonstrations. In all, it is probably too much for one configuration file, but that is another issue that is in part addressed in version 5.3.0.

With the current defaults, it is relatively easy to push the broker's heap memory utilization past the -Xmx512m heap limit passed to the JVM in the start script. When that happens the broker begins to fail in various places with java.lang.OutOfMemoryError: unable to create new native thread or java.lang.OutOfMemoryError: Java heap space.

What to do?
Well Google is your friend but there is also the ActiveMQ FAQ and particularly the entry that deals with the likely causes and relevant configuration that can alleviate ActiveMQ OutOfMemoryError Exceptions.

In short, the answer is nearly always configuration and the intent is that the OutOfMemory FAQ entry will provide a comprehensive reference for the relevant options. Let it be your first port of call.

Jan 9, 2009

Building activemq from source with m2eclipse on Mac OsX

On Mac OsX, when building activemq from source using the neat m2eclipse import maven project feature, the activemq-fileserver module fails with error:
'Access restriction: The type HttpURLConnection is not accessible due to restriction on required library /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Classes/classes.jar'.

This is in fact, a reasonable error. It is not desirable to have a dependency on a sun internal class. When using a sun jdk it is not really an issue but the default eclipse java builder on OsX is using the Apple JVM and the java builder is correctly configured to consider this sort of reference an error. To get a clean build this error needs to be reduced to a warning.

The option to disable is at:
Eclipse -> Preferences -> Java ->
Compiler ->
Errors/Warnings ->
Deprecated and restricted API ->
Forbidden reference (access rules)
Change the drop down selection from Error to Warning.

Should this be fixed? Yeah, we should probably depend on commons http client instead. I will need to dig a little further to understand why access to the implementation class is needed in the first place.
Short term, suppressing this error allows the build to proceed.

activemq systemUsage xml configuration and sendFailIfNoSpace ...

I was caught out with this twice in 24hrs. The systemUsage sendFailIfNoSpace attribute must be configured on the XBean element content, not on the element wrapper.
The use case is to limit the pending message length by memory usage and to fail the producer with an exception when the memory limit (or 70% of the memory limit) is reached. The limit can be reached very easily with a fast producer and slow (or no) consumer.

In activemq XML configuration use:
<systemUsage>
 <systemUsage sendFailIfNoSpace="true">
   <memoryUsage>
     <memoryUsage limit="20 mb">
   </memoryUsage>
 </systemUsage>
</systemUsage>
If the attribute is incorrectly added to the top level element, it is ignored and the result is that a producer will experience the default "wait for space to become available" behaviour and will hang.
Note to self, be sure to double check where XBean attributes are specified!

Jan 2, 2009

Speaking at IJTC 2008 - Choosing a JMS

I will be presenting at IJTC 2008 next week. The focus of my talk will be on choosing a java messaging solution with an emphasis on making a decision in context. Trying to make all the goodness of the web and community work for you. It should be fun.

Nov 21, 2008

Apache ActiveMQ 5.2.0 Release

The Apache ActiveMQ 5.2.0 release goes a long way towards hardening the broker. There has been a particular emphasis on use cases involving large scale networks with high message volumes. The Kaha message store resilience has improved and the remaining issues around slow restart recovery will be addressed for 6.0.

The behavior or the broker and subscriptions in the event of slow or unreliable networks has also seen numerous improvements. One upshot is that failover in now included in the default brokerURL.

The resolved issue count has topped 200, so this release was a little overdue, but I think it will be worth the wait.

Oct 29, 2008

Open Source and Open Standards; Crtl & Esc

Open Source gives the Ctrl; you can see what is going on through the source. You are free to modify and extend it. You can make it better to make your solution better. Given sufficient effort (and time), it is mailable.

Open Standards give the Esc; once due care is given to the use of standard apis, the escape hatch is always open. If a better implementation comes along you are free to go, you are free to switch-out an implementation.

The combination of open source and open standards is a perfect match. While the proprietary extensions will still exist, the good extensions are eventually subsumed or become de facto standards in themselves.

Access to the source provides the ultimate freedom to protect one's investment and influence the future direction of a project. Patch the source and if you get it right, there is a good chance that the patch will filter through to the user community. It may even eventually make its way to the standard.

Note: With FOSS, there is also intrinsic Esc; at least in the early stages. The barrier to entry is so low, the barrier to exit is no more than the cost of the experience. We are all entitled to change our opinions as we learn.

Oct 17, 2008

Testing: simulating a network failure

Figuring out how distributed software behaves in the event of a network failure or partition can be difficult. It requires testing that involves multiple machines, multiple networks and many hands!.
Virtualisation helps, but for really simple testability, a single VM environment is what you need. What follows, with some context, is a simple solution that may help.

Recently I was trying to track down an issue with Apache ActiveMQ network support. The test scenario required a bunch of VMWare images, dual network cards and periodic manual network disabling.
In order to understand the scenario I tried to reduce it to something more manageable. The iptables firewall in Linux meant I did not have to yank out any network cables. With iptables, and a good tutorial, it is relatively easy to simulate a network failure or temporary network outage by instructing iptables to drop network packets that originate from, or are destined for, an individual port.
For my test, I had a simple network of two embedded brokers, a producer on one broker and a consumer on the other. Both the producer and consumer used the vm protocol, leaving the tcp connector free for the networking calls. The connector was using port: 61616. To simulate a network failure, by dropping all tcp packets to and from port 61616, the following iptables rules do the trick:
$ sudo iptables -I INPUT 1 -p tcp --sport 61616 -j DROP;sudo iptables -I INPUT 2 -p tcp --dport 61616 -j DROP
In order to enable communication again, the two rules added above need to be deleted (for simplicity I just delete the first rule twice):
$ sudo iptables -D INPUT 1;sudo iptables -D INPUT 1
This works fine because I have control over the Linux box and I don't typically run any iptables rules. But this will not always be the case and this will not hold on other platforms or on shared Linux work stations. In addition it requires some manual intervention so it cannot be easily automated.

What I needed I thought, was a simple java socket proxy that could sit as an intermediary between the two ends of the network and which I could control through code. Something that will let traffic pass through until it is instructed not to do so. A quick google did not produce any obvious candidate for reuse so I coded a simple solution that worked for me and built a test case around it. The resulting SocketProxy is uses in BrokerQueueNetworkWithDisconnectTest. The usage pattern is based around replacing required tcp URIs with a proxy URL:

socketProxy = new SocketProxy(remoteURI);
DiscoveryNetworkConnector connector = new DiscoveryNetworkConnector(new URI("static:(" + socketProxy.getUrl() + ")"));
The proxy takes the target URI, sets up a listener and forwarder to the target and through getUrl() returns the proxy URL. To simulate a network failure, socketProxy.stop() is called during the test execution. socketProxy.resume() allows a network reconnect such that recovery can be validated. It made my life a little easier and meant I could produce a reliable and portable test case using a single JVM. I know I will use it again :-)

Note: There is also the option to pause/resume the proxy. This keeps the sockets open but does not allow any traffic to pass through. Pausing allows the simulation of a slow network which was handy for exercising the ActiveMQ inactivity monitor.

Oct 15, 2008

Who, what, why?

Among other things, I design, write, test, extend, refactor and troubleshoot software. Over the past few years, my focus has moved to open source. I want to share some of what I discover as I explore the domain and work to harden and expand some existing implementations. May the sharing, learning and (r)evolution continue.