When to use ASMX, ES or Remoting
This subject never ends!
I have just got back from MGB (Microsoft Global Briefing) where I engaged in many, many conversations with our technical and architectural consulting staff. By far the most pressing questions were around Service Orientation which I will cover in later posts, and “when should I use ASMX, ES or Remoting” ... or in more direct terms, “whaddya mean we shouldn't be using .NET Remoting for Project x?????”.
On my return to Redmond this morning, there were three emails asking questions about this and a few people asking for my view of blog conversations (such as this one on Rocky Lhotka's site and this one on Michele Leroux Bustamante's “DasBlonde” site) discussing the same subject. Rather than answer each one individually, I thought it best to share this information more broadly ...
Okay, to answer the question, let's bear in mind the Four Tenets of Service Orientation while we discuss our options:
- Service Boundaries are Explicit
- Services Are Autonomous
- Services expose Schema and Contract, not Object and Type
- Services integrate using Policy
Let's start by considering a few key scenarios and which technologies are most appropriate:
I am building my service boundary
Use ASMX enhanced with WSE if required. By implementing your service in ASMX/WSE, your service will automatically have an explicit boundary, expressed in a standards-based schema, sharing standards-based schematized data documents and will communicate over open standards transports. This cannot be said of ES or Remoting components!
Inside my service, I need to spread my implementation across n physical tiers and therefore need to call objects on remote machines
If you can implement the logic on each of the physical tiers as individual services, do so! By implementing mini-services inside your larger service, you'll be more closely aligning yourself with Microsoft's entire Distributed Applications strategy and will reap great benefits when Indigo is released.
Operations within my Service involve retrieving, storing and processing high volumes of complex data and requires many traversals between objects
Consider consolidating the code which performs the highest number of communication traversals on the same physical box to avoid the penalty imposed by traversing the network.
Consider creating Mini-Services for the portion of your Services that are most intensive implemented as ASMX Web Services which broker calls to internal ES/COM+ logic or databases etc. The reason for this is that Web Services have a great scale-out story and enables you to quickly, simply and effectively improve the scalability of the most computationally or communicatively expenive parts of your system through the use of Load Balancing.
If you must physically separate components (ie: on separate boxes) which need to exhange large amounts of data or communicate intensively, use .NET Enterprise Services (ES) components on each tier. Design all methods to be as chunky as possible (aim to perform a complete business operation in one traversal wherever possible). The reason we opt for ES here is that ES uses DCOM on the wire and is by far the fastest technology on the Microsoft platform for remoting object invocations and data exchanges. Again, consider wrapping access to this portion of your Service with an ASMX service. You can then take advantage of the scalability improvments that Load Balancing can give you as discussed above.
If you call ES components on the local box, consider configuring and activating them as Library (in-process) rather than Server (out-of-process) components wherever possible - especially if you are able to locate all Web Service and ES/COM+ code on the same physical box.
I need to handle custom message formats on the wire
This is one of only two scenarios where the use of .NET Remoting is recommended today. .NET Remoting gets you very close to the wire and allows you to write your own custom formatters and sinks etc. This allows you to directly format the message going onto or coming from the wire.
I need to communicate between two components in different AppDomains inside the same process
This is the second of the two scenarios where .NET Remoting is recommended. Remoting has explicit high-performance support for cross-AppDomain communications. Note that this is only for communications between AppDomains inside the same process. If you have two .NET components that must be hosted in two different processes (on the same machine), we recommend implementing the logic as .NET ES components hosted in COM+.
Okay, so hopefully we now understand these scenarios, let me just make a few statements. Some may be a surprise, some may repeat things I (and others have already said). Hopefully, but the end we'll have cleared up a few misconceptions:
.NET Remoting is NOT the fastest way to call a remote object!
.NET Enterprise Services is! We're currently preparing a paper that will be published on MSDN in a few weeks which clearly illustrates this fact. Note that by remote, I mean an object that runs in a process remote from yours ... whether it's on a remote process or a remote machine!
Networks annihilate performance!
While networking technology has improved enormously in terms of performance, so have motherboards, processors, memory and disks. So much so in fact that in relative terms, the network is now slower than ever before compared to the speed of the processor. This means that (again, in relative terms) your code has to wait longer than ever before for data to traverse a network. There is a truism that “in the world of distributed computing, try not to touch the network” and it's never mattered more than today!! Of course, sometimes we must and that's why we build technologies like ethernet, frame-relay, TCP/IP, RPC, DCOM, IIOP, HTTP, FTP, HTML, SOAP, etc. But it doesn't matter which technology you use ... it rarely matters how big your payload or how fast your data stream, traversing the network will significantly slow your system. So, if you don't have to traverse the network, don't! Try and co-locate as many things that need to talk on the same physical box. Where you must traverse the network, do so as infrequently as possible.
Chunky interfaces remote better than chatty ones
Following on from the point above ... I can't count the number of times I have been asked to troubleshoot a system which “is performing badly” only to find that some poor design/implementation choices have forced the underlying remote object technology to traverse a network multiple times per use of a given object. Instead of implementing logic on the caller that, for any one business process, makes many calls against a remote object, instead consider moving the logic to the remote component and calling it once. The performance improvements from such simple changes can be colossal!
DO implement interfaces such as ...
[Serializable] class Customer { string name; int age; DateTime dob; }
[WebService] class CustomerServices { ... [WebMethod] int AddCustomer(Customer cust); ... } |
DO NOT implement interfaces like this:
class CustomerServices { ... int CreateCustomer(); void SetCustomerName(int id, string name); void SetCustomerAge(int id, int age); void SetCustomerDob(int id, DateTime dob); ... } |
[N.B. Both of the above examples are used purely for illustrative purposes and are not necessarily how one would go about designing a real customer services application.]
The latter sample requires several method calls to create and then initialize a Customer and if the customer object is remote, this will result in several network traversals - one for each method call (plus a few extras that your Distributed Application technology adds on top). Obviously, this is a poor design for a distributed component, but you'd be amazed at how many such designs are out there in the wild!
ASMX & WSE are your best bet for building interoperable Services today
By now, you should be getting the picture with Web Services and should hopefully be understanding their value. Of course, one of the largest forces driving the IT world towards standardizing on wire protocol support is the fact that all our customers are fed up with having to deal with a million incompatible API's and protocols. Web Services are the best chance we have of building applications that are broadly interoperable. The best way to build such services today is by building your services using ASMX and enhancing these services with WSE if you need next-generation Web Services protocol support such as WS-Security.
.NET Remoting is NOT a good bet for this goal. Remoting uses an older SOAP Encoding mechanism which means it will not be broadly interoperable moving forward. Also, .NET Remoting does not support WSDL which is why you have to ship assemblies from the server onto the caller. It also has no security mechanism built in and is not Microsoft's strategic technology for Service development. All in all, .NET Remoting ? Web Services!
So where are we?
Hopefully, this post should have cleared up most misconceptions around a number of subjects related to where to use Microsoft's current stack of Distributed App technologies in different scenarios and where not to use those technologies.
Moving forward, Indigo will provide an alternative path for those implementing Service Oriented Distributed Applications (SODA ... oh no ... I've just coined another acronym!!! Like we needed any more!!!!). The Indigo path will be more consistent, powerful, flexible and extensible than anything that has been seen before. It will reset the bar by which all other SODA platforms are be measured. Tall claims, and some may say, biased. Nonetheless, bear with us. As they say (in the UK at least!), "the proof is in the pudding". We're now engaging our Technical Adoption Program (TAP) and Beta planning is underway so before too long, you'll be able to experience for yourself the benefits of Indigo.