Having this issue on my mind I’ve decided to go through ways of communicating between apps known in the projects I have been dealing with. I hope it is a valuable source of information for you, as it is a very good sum-up for me.
Shared folder / FTP drop-off
The most basic method known to me. Especially good when “communicating” with a really old application or hardware devices that spit out files with data. Two approaches are common in this area – polling every n seconds or registering for directory changes. As for the latter, .NET comes with a very nice FileSystemWatcher class (in System.IO namespace) that can be really helpful when updates are rare but important and you want to avoid scanning the directory every 5 seconds ;)
Here’s a simple example from http://www.dotnetspider.com/forum/147002-FileSystemWatcher-Example.aspx
1: using System.IO;
2:
3: static void Main(string[] args)
4: {
5: FileSystemWatcher watcher = new FileSystemWatcher();
6: watcher.Path = @"C:\";
7:
8: //Register for events
9: watcher.Created += new FileSystemEventHandler(watcher_Changed);
10: watcher.Deleted += new FileSystemEventHandler(watcher_Changed);
11:
12: //Start Watching
13: watcher.EnableRaisingEvents = true;
14: Console.Read();
15: }
16:
17: //Event Handler
18: static void watcher_Changed(object sender, FileSystemEventArgs e)
19: {
20: Console.WriteLine("Directory changed({0}): {1}", e.ChangeType, e.FullPath);
21: }
Sharing a database
Nearly all software environments known to me implement some kind of database interaction. Hence communication between .NET and Java or between old DOS application and an ass-kicking WPF application could be achieved by one connecting into another’s database. Most probably the WPF App would connect into mdb or dbf file of the prior. Really good thing about this kind of communication is that it allows us to implement transactions and locking. It’s never perfect though since we are in the guts of the other domain/model and architecturally we are committing a big faux pas.
There is also a powerful toy that comes with SQL Server 2005 and the successors – Microsoft Integration Services – where you can build data integration solutions (ETL packages). It has quite nice graphical tools for creating and debugging those. It can perform FTP operations, execute SQL statements, send email messages.
Here’s a sample SSIS everyday view. Looks nice and encouraging when you want to stay close to wizards and as far as possible from writing code.
What happens with SSIS though is that after some time you keep rewriting the same kind of code – pulling data out from a source and storing data in some destination. It gets boring pretty fast…
Web Services’ popularity almost exploded after 2005. If you didn’t do SOAP, XML communication you were definitely out of the loop. We’ve quickly learnt how easy it is to asynchronously talk from one application to another. We could send any kind of data, validate it, ACK it and even send errors back! Awesome… but there were drawbacks. Mainly the fact that XML is quite sparse… Serializing data to XML takes time and lots of space. Transferring a XML file over the network had a significant overhead not necessarily in CPU usage but definitely in bandwidth. Serialization and deserialization is quite efficient and not too harsh on the CPU load, however adds an extra layer to the project.
Since we’re dealing with HTTP protocol, when you are in demand of security, you can add one more layer – SSL and have it all nicely wrapped up and safer. For the bigger problem – the bandwidth – implementing compression is quite a relief and noticeable improvement. Again at the cost of the CPU usage.
It’s worth keeping in mind though that Web Services put you in asynchronous mode which brings some extra frustration when dealing with the real world. Especially when debugging and testing. Also when the message format changes, both sides of the communication ought to be updated. Resisting to do so can work at least for a short while. General approach is that both sides should get updated which is inconvenient especially when your interfaces keep growing in time.
This emerged pretty fast after we’ve realized that web services are cool but too big to operate on. We need our systems to stay robust and to achieve this, we need the requests to be as small in size as possible. There came the .NET Remoting which is not much else than Web Services with binary serialization (instead of XML Serialization).
The speed gain is really helpful here, the drawback? We’re out of commonly used standards so it’s great for internal stuff, and not so great for communicating with other companies.
1: remoteService T = (remoteService) Activator.GetObject(typeof(remoteService),
2: "tcp://host:1500/RemoteService");
There is one more thing about .NET Remoting that is sometimes scary. By default it’s not using HTTP, it’s a straightforward TCP. Which means that if you are using Squid or any other Proxy, your requests will not get through. Fortunately it is possible to run a .NET Remoting service with HTTP protocol just by registering an HttpChannel in place of a TcpChannel. This really helps with stubborn local administrators who think that opening another port in the firewall is a disaster.
There is lots of examples available online, I’m usually getting back to this one when looking for code snippets: http://www.codeproject.com/KB/IP/remotingchatsample.aspx
MSMQ, which has been there since 1997, is the first professional approach to communication I’ve ever experienced when dealing with communication. And this includes JMS as well. What we get here is a durable and guaranteed delivery over multiple protocols with such advanced features as triggers, multicasting and authorizations. MSMQ is a service provided by operating system, not a language feature. To be fair with J2EE, JMS is an Application Server’s service. What is important is that the messages are handled outside of Application Domain in a different process. MSMQ handles durable messaging and reliable delivery. The technology involved is astonishing.
With Messaging we’re finally in asynchronous mode. We can implement pooling and prevent killing our applications with initial loads or unpredicted volume of traffic. I’m convinced that all external interfaces to our systems should be using a queuing interface unless we are convinced that there is a controlled amount of traffic.
There is one thing worth mentioning. MSMQ has multiple modes of operation: private queue and public queue. Private queues are accessible directly from the code whereas public queues are available through Active Directory which sounds at least troublesome and performance-problem-some. Thus it’s recommended to use private whenever possible.
It should not take too long to notice the Net.MSMQ transport in WCF, which means that it is strongly based on the old friend - MSMQ. Which is a great news because it is a neat and stable solution. That’s pretty much it for good oldies. What’s new and unfortunately painful is all the configuration hell. One can die in the bushes of XML settings and configurations. I really hope that they will come up with a GUI for that, and as soon as in VS 2010! We’ll see. For now I see more pain than gain and I’m waiting for some improvements.
Everything depends on your needs, how much you want to spend, whether you need support or what kind of applications you want to communicate with each other.
MassTransit is something much more that just a MSMQ … it is a really interesting project with which I haven’t dealt yet, but I would love to try it one day. It is definitely a next step in the queuing world.