Designing an effective distributed software system becomes especially tricky when considering the fact that services and processes might need to interact with each other across multiple protocols.
Most distributed systems encapsulate the protocol details of interprocess communication within the processes or services that use each given protocol. Either that or the details are embodied within some manager class charged with handling communications for a given protocol. Both mechanisms raise the need to redesign, reprogram, recompile, and test whenever a new protocol is needed. Depending upon the amount of coupling between the protocol-dependent code and the services themselves, there is usually a fair amount of interdependencies created, leading to potentially difficult couplings to deal with when the underlying communication infrastructure changes.
Designing for protocol independence
A service-oriented architecture (SOA) depends on a minimum amount of interdependencies between services. This loose-coupling must propagate all the way to the protocol layer of the architecture. Thus communication infrastructure used within an SOA should be designed to be independent of the underlying protocol layer.
Code reusability becomes one of the most important benefits derived from a well-designed protocol-independent communication framework, since the code that uses the framework will not be tied to the protocols used. Transparent replacement of the underlying protocol is also a very important benefit derived from a protocol-independent design. This facilitates deployment of a new protocol without the typical redeployment headaches such as server restarts and frustrated clients.
Patterns for protocol independence
- Business Delegate: Hides underlying implementation details of a business service, such as lookup and access details.
Example: A wrapper Java Bean which aggregates multiple objects and presents an easily understood business interface
- Remote Proxy or Surrogate: Acts as a stand-in for objects which exist in a different tier.
Example: RMI’s stub class design
- Adapter or Wrapper: An Adapter provides transparent access to disparate objects or services by converting requests and possibly responses from one interaction interface to another.
Example: Java’s Portable Object Adapter
- Broker: Decouples business tier objects from objects and services in other tiers.
Example: CORBA’s ORB environment
- Factory: Instantiates objects at runtime based on dynamic configurations. Factories are often instantiated objects designed around the Strategy pattern or Bridge pattern.
Example: RMI’s custom socket factory environment
Protocol abstraction layer
One of the most important pieces of technology in a protocol-independent framework is a protocol abstraction layer. Among other benefits, a protocol abstraction layer allows access to services from multiple, simultaneous protocols; hides protocol details from the service developer; and facilitates transparent protocol replacement. Figure A illustrates this concept:
|Protocol abstraction layer|
Protocol independence with SOAP
The Simple Object Access Protocol (SOAP) is a lightweight, XML-based protocol for exchanging information in a decentralized, distributed environment. SOAP supports Remote Procedure Call (RPC) style of information exchange and message-oriented style of information exchange. SOAP is designed around a number of loose-couplings including protocol independence, language independence, platform independence, and operating system independence.
The SOAP specification defines the structure of an XML document that is to be used to exchange data between two entities over a variety of other protocols.
The SOAP specification, version 1.2, defines a binding framework explaining the responsibilities for transporting a SOAP message from one node to another. This makes SOAP processors protocol-agnostic and protocol-independent. Thus, SOAP version 1.2 messages can be transported across HTTP, SMTP, or any other protocol for which a binding conforms to the binding framework.
The SOAP binding framework:
- Declares the features provided by a binding.
- Describes how the services of the underlying protocol are used to transmit SOAP message infosets.
- Describes how the services of the underlying protocol are used to honor the contract formed by the features supported by that binding.
- Describes the handling of all potential failures that can be anticipated within the binding.
- Defines the requirements for building a conformant implementation of the binding being specified.
The SOAP Binding framework can be easily integrated with existing protocol abstraction layers by providing bindings for protocols that are already handled in the legacy code. For example, let’s look at Figure B, which shows the protocol abstraction layer integrated with the SOAP binding framework:
|SOAP and the protocol abstraction layer|
As shown in the diagram, the service-request interface and the service invocation interface do not need to change. This allows for easy migration without runtime disturbances or interfacing code changes.
Designing an effective distributed software system can become complex when services and processes need to interact with each other across multiple protocols. The introduction of each new protocol also typically introduces the need to redesign, reprogram, recompile, and retest the system. However, a service-oriented architecture built around a properly designed protocol abstraction layer using standard industry patterns can effectively reduce or even eliminate these problems.