Chapter 8: Communication Guidelines
J.D. Meier, Alex Homer, David Hill, Jason Taylor, Prashant Bansode, Lonnie Wall, Rob Boucher Jr, Akshay Bogawat
- Learn the guidelines for designing a communication approach.
- Learn the ways in which components communicate with each other.
- Learn the interoperability, performance, and security considerations for choosing a communication approach.
- Learn the various communication technology choices.
One of the key factors that affect the design of an application—particularly a distributed application—is the way that you design the communication infrastructure for each part of the application. Components must communicate with each other; for example, to send user input to the business layer, and then to update the data store through the data layer. When components are located on the same physical tier, you can often rely on direct communication between these components. However, if you deploy components and layers on physically separate servers and client machines—as is likely in most scenarios—you must consider how the components in these layers will communicate with each other efficiently and reliably.
In general, you must choose between direct communication (e.g. method calls between components) or message-based communication. There are many advantages to using message-based communication, such as the ability to decouple your components from each other. Decoupling components is not only good for maintainability and but can also give additional flexibility to change your deployment strategy in the future. However, message-based communication raises issues that you must consider, such as performance, reliability, and security.
This chapter presents design guidelines that will help you to choose the appropriate communication approach, understand how to get the best results from your chosen approach, and anticipate security and reliability issues that might arise.
When designing a communication strategy for your application, consider the performance impact of communicating between layers, as well as between tiers. Because each communication across a logical or a physical boundary increases processing overhead, design for efficient communication by reducing round trips and minimizing the amount of data sent over the network.
Consider the following guidelines when deciding on a communication strategy:
- Consider communication strategies when crossing boundaries. Understand each of your boundaries and how they affect communication performance. For example, the application domain (AppDomain), computer process, machine, and unmanaged code all represent boundaries that that can be crossed when communicating with components of the application or external services and applications.
- Consider using unmanaged code for communication across AppDomain boundaries. Use unmanaged code to communicate across AppDomain boundaries. This approach requires assemblies to run in full trust in order to interact with unmanaged code.
- Consider using message-based communication when crossing process boundaries. Use Windows Communication Foundation (WCF) with either the TCP or named pipes protocol to package data into a single call that can be serialized across process boundaries.
- Consider message-based communication when crossing physical boundaries. Consider using WCF or Microsoft Message Queuing (MSMQ) to communicate with remote machines across physical boundaries. Message-based communication supports coarse-grained operations that reduce round trips when communicating across a network.
- Reduce round trips when accessing remote layers. When communicating with remote layers, reduce communication requirements by using coarse-grained message-based communication methods, and use asynchronous communication if possible to avoid blocking or freezing the user interface (UI).
- Consider the serialization capabilities of the data formats passed across boundaries. If you require interoperability with other systems, consider Extensible Markup Language (XML) serialization. Keep in mind that XML serialization imposes increased overhead. If performance is critical, consider binary serialization because it is faster and the resulting serialized data is smaller than the XML equivalent.
- Consider hotspots while designing your communication policy. Hotspots include asynchronous and synchronous communication, data format, communication protocol, security, performance, and interoperability.
Message-based communication allows you to expose a service to your callers by defining a service interface that clients call by passing XML-based messages over a transport channel. Message-based calls are generally made from remote clients, but message-based service interfaces can support local callers as well. A message-based communication style is well suited to the following scenarios:
- You are implementing a business system that represents a medium- to long-term investment; for example, when building a service that will be exposed to and used by partners for a considerable time.
- You are implementing large-scale systems with high-availability characteristics.
- You are building a service that you want to isolate from other services it uses, and from services that consume it.
- You expect communication at either of the endpoints to be sporadically unavailable, as in the case of wireless networks or applications that can be used offline.
- You are dealing with real-world business processes that use the asynchronous model. This will provide a cleaner mapping between your requirements and the behavior of the application.
Consider the following guidelines when using message-based communication:
- Be aware that a connection will not always be present, and that messages may need to be stored and then sent when a connection becomes available.
- Consider how to handle the case when a message response is not received. To manage the conversation state, your business logic can log the sent messages for later processing in case a response is not received.
- Consider using acknowledgements to force the correct sequencing of messages.
- If message response timing is critical for your communication, consider a synchronous programming model in which your client waits for each response message.
- Do not implement a custom communication channel unless there is no default combination of endpoint, protocol, and format that suits your needs.
Asynchronous vs. Synchronous Communication
Consider the key tradeoffs when choosing between synchronous and asynchronous communication styles. Synchronous communication is best suited to scenarios in which you must guarantee the order in which calls are received, or when you must wait for the call to return before proceeding. Asynchronous communication is best suited to scenarios in which responsiveness is important or you cannot guarantee that the target will be available.
Consider the following guidelines when deciding whether to use synchronous or asynchronous communication:
- For maximum performance, loose coupling, and minimized system overhead, consider using an asynchronous communication model.
- In cases where you must guarantee the order in which operations take place, or where you use operations that depend on the outcome of previous operations, consider a synchronous model.
- For asynchronous, in-process calls use the platform features (such as Begin and End versions of methods and callbacks) to implement asynchronous method calls.
- Consider implementing asynchronous interfaces in the same layer as the caller to obtain maximum responsiveness.
- If some recipients can only accept synchronous calls, and you need to support synchronous communication, consider wrapping existing asynchronous calls in a component that performs synchronous communication.
If you choose asynchronous communication and cannot guarantee network connectivity or the availability of the target, consider using a store-and-forward message-delivery mechanism to avoid losing messages. When choosing a store-and-forward design strategy:
- Consider using local caches to store messages for later delivery in case of system or network interruption.
- Consider using MSMQ to queue messages for later delivery in case of system or network interruption or failure. MSMQ can perform transacted message delivery and supports reliable once-only delivery.
- Consider using Microsoft BizTalk® Server to interoperate with other systems and platforms at the enterprise level, or for electronic data interchange (EDI).
Coupling and Cohesion
Communication methods that impose interdependencies between the distributed parts of the application will result in a tightly coupled application. A loosely coupled application uses methods that impose a minimum set of requirements for communication to occur.
Consider the following guidelines when designing for coupling and cohesion:
- For loose coupling, consider using a message-based technology such as ASP.NET Web services (ASMX) or WCF.
- For loose coupling, consider using self-describing data and ubiquitous protocols such as HyperText Transfer Protocol (HTTP) and SOAP.
- To maintain cohesion, ensure that interfaces contain only methods that are closely related in purpose and functional area.
It may be necessary for the communicating parties in an application to maintain state across multiple requests.
Consider the following guidelines when deciding how to implement state management:
- Only maintain state between calls if it is absolutely necessary, since maintaining state consumes resources and can impact the performance of your application.
- If you are using a stateful programming model within a component or service, consider using a durable data store, such as a database, to store state information and use a token to access the information.
- If you are designing an ASMX service, consider using the Application Context class to preserve state, since it provides access to the default state stores for application scope and session scope.
- If you are designing a WCF service, consider using the extensible objects that are provided by the platform for state management. These extensible objects allow state to be stored in various scopes such as service host, service instance context, and operation context. Note that all of these states are kept in memory and are not durable. If you need durable state, you can use the durable storage (introduced in the .NET Framework 3.5) or implement your own custom solution.
The format you choose for messages, and the communication synchronicity, affect the ability of participants to exchange data, the integrity of that data, and the performance of the communication channel.
Consider the following guidelines when choosing a message format and handling messages:
- Ensure that type information is not lost during the communication process. Binary serialization preserves type fidelity, which is useful when passing objects between client and server. Default XML serialization serializes only public properties and fields and does not preserve type fidelity.
- Ensure that your application code can detect and manage messages that arrive more than once (idempotency).
- Ensure that your application code can detect and manage multiple messages that arrive out of order (commutativity).
Passing Data Through Tiers - Data Formats
To support a diverse range of business processes and applications, consider the following guidelines when selecting a data format for a communication channel:
- Consider the advantage of using custom objects. These can impose a lower overhead than DataSets and support both binary and XML serialization.
- If your application works mainly with sets of data, and needs functionality such as sorting, searching, and data binding, consider using DataSets. Consider that DataSets introduce serialization overhead.
- If your application works mainly with instance data, consider using scalar values for better performance.
Data Format Considerations
The most common data formats for passing data across tiers are scalar values, XML, DataSets, and custom objects. Scalar values will reduce your initial development costs; however, they produce tight coupling that can increase maintenance costs if the value types need to change. XML may require additional up-front schema definition but will result in loose coupling that can reduce future maintenance costs and increase interoperability (for example, if you want to expose your interface to additional XML-compliant callers). DataSets work well for complex data types, especially if they are populated directly from your database. However, it is important to understand that DataSets also contain schema and state information that increases the overall volume of data passed across the network. Custom objects work best when none of the other options meets your requirements, or when you are communicating with components that expect a custom object.
Use the following table to understand the key considerations for choosing a data type.
|Scalar values ||You want built-in support for serialization. |
| ||You can handle the likelihood of schema changes. Scalar values produce tight coupling that will require method signatures to be modified, thereby affecting the calling code. |
|XML ||You need loose coupling, where the caller must know about only the data that defines the business entity and the schema that provides metadata for the business entity. |
| ||You need to support different types of callers, including third |
| ||You need built |
|DataSet ||You need support for complex data structures. |
| ||You need to handle sets and complex relationships. |
| ||You need to track changes to data within the DataSet. |
| ||You want built-in support for serialization |
|Custom objects ||You need support for complex data structures. |
| ||You are communicating with components that know about the object type. |
| ||You want to support binary serialization for performance. |
The main factors that influence interoperability of applications and components are the availability of suitable communication channels, and the formats and protocols that the participants can understand.
Consider the following guidelines for maximizing interoperability:
- To enable communication with wide variety of platforms and devices, consider using standard protocols and data formats, such as HTTP and XML..
- Keep in mind that protocol decisions may affect the availability of clients you are targeting. For example, target systems might be protected by firewalls that block some protocols.
- Keep in mind that data format decisions may affect interoperability. For example, target systems might not understand platform-specific types, or might have different ways of handling and serializing types.
- Keep in mind that security encryption and decryption decisions may affect interoperability. For example, some message encryption/decryption techniques might not be available on all systems.
The design of your communication interfaces and the data formats you use will also have a considerable impact on performance, especially when crossing process or machine boundaries. While other considerations, such as interoperability, may require specific interfaces and data formats, there are techniques you can use to improve performance related to communication between different layers or tiers of your application.
Consider the following guidelines for performance:
- Avoid fine-grained “chatty” interfaces for cross-process and cross-machine communication. These require the client to make multiple method calls to perform a single logical unit of work. Consider using the Façade pattern to provide a coarse-grained wrapper for existing chatty interfaces.
- Consider using Data Transfer Objects (DTOs) to pass data as a single unit instead of passing individual data types one at a time.
- Reduce the volume of data passed to remote methods where possible. This reduces serialization overhead and network latency.
- If serialization performance is critical for your application, consider using custom classes with binary serialization.
- If XML is required for interoperability, consider using attribute-based structures for large amounts of data instead of element-based structures.
Communication security consists primarily of data protection. A secure communication strategy will protect sensitive data from being read when passed over the network, protect sensitive data from being tampered with, and if necessary, guarantee the identity of the caller. There are two fundamental areas of concern for securing communications: transport security and message-based security.
Transport security is used to provide point-to-point security between the two endpoints. Protecting the channel prevents attackers from accessing all messages on the channel. Common approaches to transport security are Secure Sockets Layer (SSL) encryption and Internet Protocol Security (IPSec).
Consider the following when deciding whether to use transport security:
- When using transport security, the transport layer passes user credentials and claims to the recipient.
- Transport security uses common industry standards that provide good interoperability.
- Transport security supports a limited set of credentials and claims compared to message security.
- If interactions between the service and the consumer are not routed through other services, you can use transport security.
- If the message passes through one or more servers, use message-based protection as well as transport security. With transport security, the message is decrypted and then encrypted at each server it passes through, which represents a security risk.
- Transport security is usually faster for encryption and signing since it is accomplished at lower layers, sometimes even on the network hardware.
Message security can be used with any transport protocol. You should protect the content of individual messages passing over the channel whenever they pass outside your own secure network, and even within your network for highly sensitive content. Common approaches to message security are encryption and digital signatures.
Consider the following guidelines when deciding whether to use message security:
- Always implement message-based security for sensitive messages that pass out of your secure network.
- Always use message-based security for sensitive messages if there are intermediate systems between the client and the service. Intermediate servers will receive the message, handle it, and then create a new SSL or IPSec connection, and can therefore access the unprotected message.
- Combine transport and message-based security techniques for maximum protection.
WCF Technology Options
Windows Communication Foundation (WCF) provides a comprehensive mechanism for implementing services in a range of situations, and allows you to exert fine control over the configuration and content of the services. The following guidelines will help you to understand how you can use WCF:
- Consider using WCF to communicate with Web services to achieve interoperability with other platforms that also support SOAP, such as the J2EE-based application servers.
- Consider using WCF to communicate with Web services using messages not based on SOAP for applications with formats such as Really Simple Syndication (RSS).
- Consider using WCF to communicate using SOAP messages and binary encoding for data structures when both the server and the client use WCF.
- Consider using WS-MetadataExchange in SOAP requests to obtain descriptive information about a service, such as its Web Services Description Language (WSDL) definition and policies.
- Consider using WS-Security to implement authentication, data integrity, data privacy, and other security features.
- Consider using WS-Reliable Messaging to implement reliable end-to-end communication, even when one or more Web services intermediaries must be traversed.
- Consider using WS-Coordination to coordinate two-phase commit transactions in the context of Web services conversations.
- Consider using WCF to build REST Singleton & Collection Services, ATOM Feed and Publishing Protocol Services, and HTTP Plain XML Services.
WCF supports several different protocols for communication:
- When providing public interfaces that are accessed from the Internet, consider using the HTTP protocol.
- When providing interfaces that are accessed from within a private network, consider using the TCP protocol.
- When providing interfaces that are accessed from the same machine, consider using the named pipes protocol, which supports a shared buffer or streams for passing data.
ASMX Technology Options
ASP.NET Web Services (ASMX) provide a simpler solution for building Web services based on ASP.NET and exposed through an Internet Information Services (IIS) Web server.
ASMX has the following characteristics:
- Can be accessed over the Internet.
- Uses port 80 by default, but this can be easily reconfigured.
- Supports the HTTP protocol only.
- Has no support for Distributed Transaction Coordinator (DTC) transaction flow. You must program long-running transactions using custom implementations.
- Supports IIS authentication.
- Supports Roles stored as Windows groups for authorization.
- Supports IIS and ASP.NET impersonation.
- Supports SSL transport security.
- Supports the endpoint technology implemented in IIS.
- Provides cross-platform interoperability and cross-company computing.
REST vs. SOAP
Representational State Transfer (REST) and SOAP represent two different styles for implementing services. REST is based on HTTP, which means that it works very much like a Web application, so you can take advantage of HTTP support for non-XML MIME types or streaming content from a service request. Service consumers navigating through REST resources interact with URIs the same way a human user might navigate through and interact with Web pages. SOAP is an XML-based messaging protocol that can be used with any communication protocol.
The main difference between these two styles is how the service state machine is maintained. Don’t think of the service state machine as the application or session state; instead, think of it as the different states that an application passes through during its lifetime. With SOAP, movement through different states, such as initialize and update, is encapsulated behind the service endpoint. With REST, the service state machine is explicit and the representation of its state is addressable by URIs, which are HTTP addresses.
While both REST and SOAP can be used with most service implementations, the REST architectural style is better suited for public services or cases where a service can be accessed by unknown consumers. SOAP is much better suited for implementing a Remote Procedure Call (RPC) interface between layers of an application. With SOAP, you are not restricted to HTTP. The WS-* standards, which can be utilized in SOAP, provide a standard and therefore interoperable method of dealing with common messaging issues such as security, transactions, addressing, and reliability. REST can also provide the same type of functionality, but you must create a custom mechanism because few agreed-upon standards currently exist for these areas.
Consider the following guidelines when choosing between REST and SOAP:
- SOAP is a protocol that provides a basic messaging framework upon which abstract layers can be built.
- SOAP is commonly used as an RPC framework that passes calls and responses over networks using XML-formatted messages.
- SOAP handles issues such as security and addressing through its internal protocol implementation, but requires a SOAP stack to be available.
- REST exposes an application and data as a state machine, not just a service endpoint. REST allows standard HTTP calls such as GET and PUT to be used to query and modify the state of the system.
- REST is sometimes described as having a “stateless nature”, meaning that each individual request sent from the client to the server must contain all of the information necessary to understand the request since the server does not store the session state data.