Service Composition
Services are only of value when they are employed in a business process. While some value is provided when a service is first employed as part of one business process, additional value—the added value that justifies making the functionality into a service—is provided when the service is employed in other business processes as well. The service makes it possible to create, modify, or extend other business processes faster and at a lower cost than would be possible without it. The ultimate goal of a service-oriented architecture is to enable the low-cost assembly of business processes from existing services, and the process of combining the services together is referred to as composition.
Composition is often discussed as a technique for combining services together to form a new higher-level service. Such a service is referred to as a composite service. However, the idea of composing services together is distinct from the idea of turning the resulting composite into a new service. The majority of composites you are likely to encounter are not services—they are business processes. The core value provided by SOA is the ability to quickly and inexpensively create these composites. Turning a composite into a service is gravy.
Hard-Wired Composition
The simplest way to compose services is to hard wire them together so that the result of one service becomes the input to the next (Figure 4-22). This type of composition is termed hard-wired because there is no explicit embodiment of the overall process. To determine what this overall process actually is, you have to trace the sequence of interactions between the participants. While this type of composition may not strike you as being particularly service-oriented, it is the most commonly found composition technique in use today, although the participants in such compositions are often not designed as services.
Figure 4-22 Hard-Wired Composition
In hard-wired composition, the result produced by one service may not be in the proper form to serve as the input to the next, or the component producing the result may not be configured to direct it to the next service. In such cases, intermediate components can be used to transform the results and deliver them to the appropriate destinations. Part IV of this book explores these components and their attendant design issues.
Nested Composition
Service-oriented architectures lead to a very natural style, modularizing functionality into request-response service operations and then building composites that invoke these services (Figure 4-23). This compositional style is an excellent first thought in terms of organizing functionality, but it must be examined from a performance perspective to determine whether the modularization is adequate for the task. The performance examination must explore both response latency and the downstream service capacity limitations.
Figure 4-23 Nested Composition
When requests are nested in this manner, the accumulated latency resulting from the nested request-response calls may result in unacceptable overall response time from the user's perspective. For each service call, there is a communication delay in each direction. On top of this, there is the time it takes the service provider to respond to the request, and the additional time it takes the service provider to perform the work. These delays add to the time required for the user to interact with the composite and the time it takes the composite to do its own work. When the underlying services are themselves composites, additional latencies are introduced. Depending upon the needs of the user, the accumulated composite latency may become unacceptable.
You also need to consider the load being placed on the lower-level service. The service may not have been designed to handle the volume of requests coming from the composite. One hotelier with multiple properties in the same location decided to change the service its customers use to locate hotel rooms in a city. Instead of having the customer first select from a list of hotels and then check room availability in that hotel, they implemented a new composite service that checked the availability of all hotels in the city for each customer request. The impact was that the volume of queries increased dramatically on all the hotels—by a factor of eight! During peak periods (the most important times for hotel bookings), the resulting demand exceeded the capacity of the individual hotel systems. As a result, the majority of the queries timed out and provided no response. Instead of delivering a new and improved service to customers, many room availability queries went unanswered.
Performance evaluation for any use of a service should be a routine part of the design process. Chapter 39 shows how to perform this type of analysis.
Cached Composites
The nested composition performance lesson is one that was first learned when businesses first started adding customer-facing web self-service front-ends. These web sites allowed customers to check the status of their orders and shipments. However, the underlying back-office production systems that processed these orders were never designed to handle this kind of dynamic query load. Early web site implementations that simply queried the back-office production systems not only performed poorly, but their query load often had an adverse impact on the back-office system's ability to perform its work.
To cope with this type of situation, an architectural style evolved in which status information is extracted from the production system and cached for convenient access by the web application server. In service-oriented terms, the style of interaction with the underlying service changed from a request-reply interaction to a subscription interaction (Figure 4-24).
Figure 4-24 Cached Composite
Note that this architectural change impacted not only the composite, but the underlying service as well. Interaction with the underlying service changed from a request-reply to a subscription, and the composite changed from a nested composition to a cached composition. Once again, you can see the importance of understanding the intended utilization of a service—particularly the volume of activity and the required response times. This understanding will impact the architecture of both the composite and the service, and will deeply influence the operation interfaces.