Note that the information on this page is the BETA 1 of a guide that is now released. See http://www.codeplex.com/AppArchGuide for the latest PDF and HTML content.

Chapter 22 – Services Application Archetype

- J.D. Meier, Alex Homer, David Hill, Jason Taylor, Prashant Bansode, Lonnie Wall, Rob Boucher Jr, Akshay Bogawat

Objectives

  • Understand the nature and use of services.
  • Learn the general guidelines for different service scenarios.
  • Learn the guidelines for the key attributes of services.
  • Learn the guidelines for the layers within a services application.
  • Learn the guidelines for performance, security, and deployment.
  • Understand the technology choices for services.

Overview

A service is a public interface that provides access to a unit of functionality. Services literally provide some programmatic "service" to the caller, who consumes them. Services are loosely coupled and can be combined within a client or within other services to provide more complex functionality. Services are distributable and can be accessed from a remote machine as well as from the local machine on which they are running. Services are message oriented, meaning that service interfaces are defined by a WSDL file, and operations are called using XML-based message schemas that are passed over a transport channel. Services support a heterogeneous environment by focusing interoperability at the message/interface definition. If components can understand the message and interface definition, they can use the service regardless of their base technology.

ch22-fig1.JPG

Common Services Scenarios

Services are, by nature, flexible, and can be used in a wide variety of scenarios and combinations. The following are key typical scenarios:
  • Service exposed over the Internet. This scenario describes a service that is consumed by Web applications or Smart Client applications over the Internet. Decisions on authentication and authorization must be made based upon Internet trust boundaries and credentials options. For example, username authentication is more likely in the Internet scenario than the intranet scenario. This scenario includes business-to-business (B2B) as well as consumer-focused services. A Web site that allows you to schedule visits to your family doctor would be an example of this scenario.
  • Service exposed over the Intranet. This scenario describes a service that is consumed by Web applications or Smart Client applications over an intranet. Decisions on authentication and authorization must be made based upon intranet trust boundaries and credentials options. For example, Active Directory is more likely to be the chosen user store in the intranet scenario than in the Internet scenario. An enterprise Web-mail application would be an example of this scenario.
  • Service exposed on the local machine. This scenario describes a service that is consumed by an application on the local machine. Transport and message protection decisions must be made based upon local machine trust boundaries and users.
  • Mixed scenario. This scenario describes a service that is consumed by multiple applications over the Internet, an intranet, and/or the local machine. For example, a line-of-business (LOB) application that is consumed internally by a thick client application and over the Internet by a Web application would be an example of this scenario.

Design Considerations

When designing service based applications, there are general guidelines that apply to all services. In addition to the general guidelines, there are specific guidelines that you should follow for different types of services. For example, with a Service Oriented Application (SOA) you should ensure that the operations are application-scoped and that the service is autonomous. Alternatively, you might have an application that provides workflow services, or you may be designing an Operational Data Store (ODS) that provides a service based interface. The design considerations in this section begin with general guidelines that apply to all services. Specific guidelines for different service types follow these.

General

  • Design coarse-grained operations. Avoid chatty calls to the service, which can lead to very poor performance. Instead, use the Façade pattern to package smaller fine-grained operations into single coarse-grained operations.
  • Design entities for extensibility. Data contracts should be designed so that you can extend them without affecting consumers of the service.
  • Compose entities from standard elements. When possible, use standard elements to compose the complex types used by your service.
  • Design without the assumption that you know who the client is. You should not make assumptions about the client and how they plan to use the service you provide.
  • Design only for the service contract. Do not implement functionality that is not reflected by the service contract. In addition, the implementation of a service should never be exposed to external consumers.
  • Design to assume the possibility of invalid requests. Never assume that all messages received by the service are valid.
  • Separate functional business concerns from infrastructure operational concerns. Cross-cutting logic should never be combined with application logic. Doing so can lead to implementations that are difficult to extend and maintain.
  • Ensure that the service can detect and manage repeated messages (idempotency). When designing the service, implement well-known patterns, or take advantage of infrastructure services, to ensure that duplicate messages are not processed.
  • Ensure that the service can manage messages arriving out of order (commutativity). If there is a possibility that messages arrive out of order, implement a design that will store messages and then process them in the correct order.

SOA Services

  • Design services to be application-scoped and not component-scoped. Service operations should be coarse-grained and focused on application operations. For example, with demographics data you should provide an operation that returns all of the data in one call. You should not use multiple operations to return sub-sets of the data with multiple calls.**
  • Decouple the interface from the implementation. In an SOA application, it is very important to keep internal business entities hidden from external clients. In other words, you should never define a service interface that exposes internal business entities. Instead, the service interface should be based on a contract that external consumers interact with. Inside the service implementation, you translate between internal business entities and external contracts.
  • Design services with explicit boundaries. A service application should be self-contained with strict boundaries. Access to the service should only be allowed through the service interface layer.
  • Design services to be autonomous. Services should not require anything from consumers of the service, and should not assume who the consumer is. In addition, you should design services assuming that malformed requests can be sent to a service.
  • Design compatibility based on policy. The service should publish a policy that describes how consumers can interact with the service. This is more important for public services, where consumers can examine a policy to determine interaction requirements.

Data Services

  • Avoid using services to expose individual tables in a database. This will lead to chatty service calls with interdependencies between service operations, which can lead to dependency issues for consumers of the service.
  • Do not implement business rules with data services. Different consumers of the data will have unique viewpoints and rules. Attempting to implement rules in data access services will impose restrictions on the use of that data.

Workflow Services

  • Use interfaces supported by your workflow engine. Attempting to create custom interfaces can restrict the type of operations supported, and will increase the effort required to extend and maintain the services.
  • Design a service that is dedicated to supporting workflow. Instead of adding workflow services to an existing service application, consider designing an autonomous service that supports only workflow requirements.

Services Application Frame

Area Key Issues
Authentication and Authorization Lack of Authentication across trust boundaries.
Lack of Authorization across trust boundaries.
Granular or improper authorization.
Communication Incorrect choice of transport protocol.
Chatty communication with the service.
Failing to protect sensitive data.
Data Consistency Failing to check data for consistency.
Improper handling of transactions in a disconnected model.
Exception Management Not catching exceptions that can be handled.
Not logging exceptions.
Compromising with message integrity when an exception occurs.
Message Construction Not appreciating that message contents may be time-sensitive.
Incorrect message construction for the operation.
Passing too much data in a single message.
Message Endpoint Not supporting idempotent operations.
Implementing filters to handle specific messages.
Subscribing to an endpoint while disconnected.
Message Protection Not protecting sensitive data.
Using transport layer protection for messages that cross multiple servers.
Not considering data integrity.
Message Transformation Unnecessary use of transformations.
Implementing transformations at the wrong point.
Using a canonical model when not necessary.
Message Exchange Patterns Using complex patterns when not necessary.
Using Request/Response for one-way messages.
REST Providing limited schema support.
Not appreciating that tools for REST are primitive.
Using hypertext to manage state.
SOAP Not choosing the appropriate security model.
Not planning for fault conditions.
Using complex types in the message schema.
Validation Not validating message structures sent to the service.
Failing to validate data fields associated with the message.

Authentication

The design of an effective authentication strategy for your service is based on the type of service host you are using. If the service is hosted in IIS, you can take advantage of the authentication support provided by IIS. If the service is hosted using a Windows Service or a console application, you will need to use message-based authentication.

When designing an authentication strategy, consider following guidelines:
  • Identify a suitable mechanism for securely authenticating users.
  • Consider the implications of using different trust settings for executing service code.
  • Ensure that secure protocols such as SSL are used with basic authentication, or when credentials are passed as plain text.
  • Use secure mechanisms such as WS Security with SOAP messages.

Authorization

Designing an effective authorization strategy for your service application is important for the security and reliability of your application. Failing to design a good authorization strategy can leave your application vulnerable to information disclosure, data tampering, and elevation of privileges.

When designing an authorization strategy, consider following guidelines:
  • Set appropriate access permissions on resources for users, groups, and roles.
  • Use URL authorization and/or file authorization when necessary.
  • Where appropriate, restrict access to publicly-accessible service methods using declarative principle permission demands.
  • Execute services under the most restrictive account that is appropriate.

Communication

When designing the communication strategy for your service, the protocol you choose should be based on the deployment scenario your service must support. If the service will be deployed within a closed network, you can use TCP for more efficient communications. If the service will be deployed in to a public facing network, you should choose the HTTP protocol.

When designing a communication strategy, consider following guidelines:
  • Use dynamic URL behavior with configured endpoints for maximum flexibility.
  • Validate endpoint addresses in messages.
  • Determine your transport protocol.
  • Determine how to handle asynchronous calls.
  • Decide if the message communication needs to be one-way or two-way.
  • Determine how to handle communication reliability.
  • Determine how to handle idempotency and commutativity.

Exception Management

Designing an effective exception management strategy for your service layer is important for the security and reliability of your application. Failing to do so can leave your application vulnerable to denial of service (DoS) attacks, and may also allow it to reveal sensitive and critical information.

Raising and handling exceptions is an expensive operation, and it is important for the design to take into account the impact on performance. A good approach is to design a centralized exception management and logging mechanism, and consider providing access points that support instrumentation and centralized monitoring in order to assist system administrators.

When designing an exception management strategy, consider following guidelines:
  • Do not use exceptions to control business logic.
  • Design a strategy for handling unhandled exceptions.
  • Design an appropriate exception logging strategy.
  • Design an appropriate notification strategy for critical errors and exceptions
  • Do not reveal sensitive information in exception messages and log files.
  • Use SOAP Fault elements or custom extensions to return exception details to the caller.
  • Disable tracing and debug-mode compilation for all services except during development and testing.

Message Construction

When data is exchanged between a service and a consumer, it must be wrapped inside a message. The format of that message is based on the type of operations you need to support. For example, you may be exchanging documents, executing commands, or raising events. When using slow message delivery channels, you should also consider including expiration information in the message.

When designing a message construction strategy, consider following guidelines:
  • Determine the appropriate patterns for message constructions (such as Command, Document, Event, and Request-Reply).
  • Divide very large quantities of data into relatively smaller chunks, and send them in sequence.
  • Include expiration information in messages that are time-sensitive. The service should ignore expired messages.

Message Endpoint

The message endpoint represents the connection that applications use to interact with your service. The implementation of your service interface represents the message endpoint. When designing the service implementation, you must consider the type of message that you are consuming. In addition, you should design for different scenarios related to handling messages.

When designing message endpoints, consider following guidelines:
  • Determine relevant patterns for message endpoints (such as Gateway, Mapper, Competing Consumers, and Message Dispatcher).
  • Determine if you should accept all messages, or implement a filter to handle specific messages.
  • Design for idempotency in your message interface. Idempotency is the situation where you could receive duplicate messages from the same consumer, but should only handle one. In other words, an idempotent endpoint will guarantee that only one message will be handled, and all duplicate messages will be ignored.
  • Design for commutativity. Commutativity is the situation where the messages could arrive out of order. In other words, commutative endpoint will guarantee that messages arriving out of order will be stored and then processed in order.
  • Design for disconnected scenarios. For instance, you may need to support guaranteed delivery.
  • Design for invalid messages. You should never assume that all received messages are valid.

Message Protection

When transmitting sensitive data between a service and its consumer, you should design for message protection. You can use transport layer protection or message-based protection. However, in most cases, you should use message-based protection. For example, you should encrypt sensitive sections within a message and use a digital signature to protect from tampering.

When designing message protection, consider following guidelines:
  • If interactions between the service and the consumer are not routed through other services, you can use just transport layer security such as SSL.
  • If the message passes through one or more servers, always use message-based protection. In addition, you can also use transport layer security with message-based security. With transport layer security, the message is decrypted and then encrypted at each server it passes through; which represents a security risk.
  • Use encryption to protect sensitive data in messages.
  • Use digital signatures to protect messages and parameters from tampering.

Message Transformation

When passing messages between a service and consumer, there are many cases where the message must be transformed into a format that the consumer can understand. This normally occurs in cases where non-message based consumers need to process data from a message-based system. You can use adapters to provide access to the message channel for a non-message based consumer, and translators to convert the message data into a format that the consumer understands.

When designing message transformation, consider following guidelines:
  • Determine relevant patterns for message transformation. For example, the Normalizer pattern can be used to translate semantically equivalent messages into a common format.
  • Use metadata to define the message format.
  • Consider using an external repository to store the metadata.

Message Exchange Patterns

A Message Exchange Patterns (MEP) is used to define a conversation between a service and the service consumer. This conversation represents a contract between the service and the consumer. The W3C standards group defines two patterns for SOAP messages; Request-Response and SOAP Response. Another standards group named OASIS has defined a Business Process Execution Language (BPEL) for services. BPEL defines a process for exchanging business process messages. In addition, other organizations have defined specific message exchange patterns for BPEL.

When designing message exchange patterns, consider the following guidelines:
  • Choose patterns that fit your requirements without adding unnecessary complexity. For example, avoid using complex business process exchange patterns when a Request/Response pattern is sufficient.
  • When using business process modeling techniques be careful not to design exchange patterns based on process steps. Instead the patterns should support operations that combine process steps.
  • Use existing standards for message exchange patterns instead of inventing your own. This promotes a standards-based interface that will be understood by many consumers. In other words, consumers will be more inclined to interact with standards-based contracts instead of having to discover and adapt to non-standard contracts.

Representational State Transfer (REST)

Representational state transfer (REST) represents an architecture style for distributed systems. It is designed to reduce complexity by dividing a system into resources. Each resource is identified by a Uniform Resource Indicator (URI). The operations supported by a resource represent the functionality provided by a service that uses REST. The URI used to identify a REST resource is normally a Uniform Resource Locator (URL), which represents the Web address for the resource.

When designing REST resources, consider following guidelines:
  • Identify and categorize resources that will be available to clients.
  • Choose an approach for resource identification. A good practice would be to use meaningful names for REST starting points and unique identifiers, such as a GUID, for specific resource instances. For example, http://www.foo.com/employee/8ce762d5-b421-6123-a041-5fbd07321bac4 represents an employee starting point while the GUID represents a specific employee.
  • Decide if multiple views should be supported for different resources. For example, decide if the resource should support GET and POST operations, or only GET operations.

SOAP

Simple Object Access protocol (SOAP) is a message-based protocol used to implement the message layer of a service. The message is composed of an envelope that contains a header and body. The header can be used to provide information that is external to the operation being performed by the service. For example, a header may contain security, transaction, or routing information. The body contains contracts, in the form of XML schemas, which define the service.

When designing SOAP messages, consider following guidelines:
  • Define the schema for the operations that can be performed by a service.
  • Define the schema for the data structures passed with a service request.
  • Define the schema for the errors or faults that can be returned from a service request.

Validation

Designing an effective input and data validation strategy is critical to the security of your application. Determine the validation rules for data you receive from consumers of the service. Understand your trust boundaries so that you can validate any data that crosses these boundaries.

When designing a validation strategy, consider following guidelines:
  • Validate all data received by the service interface.
  • Understand your trust boundaries so that you can validate data that crosses these boundaries.
  • Determine if validation that occurs in other layers. If data is already trusted, you may not need to duplicate validation.
  • Consider the way that data will be used. For example, if the data will be used in database queries, you must protect the database from SQL Injection attacks.
  • Return informative error messages if validation fails.

Service Layer Considerations

The service layer contains components that define and implement services for your application. Specifically, this layer contains the service interface, which is composed of contracts, the service implementation, and translators that convert internal business entities to and from external data contracts.
  • You should not implement business rules in the services layer. The service layer should only be responsible for managing service requests and translating data contracts into entities for use by the business layer.
  • Access to the service layer should be defined by policies. Policies provide a way for consumers of the service to determine the connection and security requirements, as well as other details related to interacting with the service.
  • Use separate assemblies for major components in the service layer. For example, the interface, implementation, data contracts, service contracts, fault contracts, and translators should all be separated into their own assemblies.
  • Interaction with the business layer should only be through a well-known public interface. The service layer should never call the underlying business logic components.
  • The service layer should have knowledge of business entities used by the business layer. This is typically achieved by creating a separate assembly that contains business entity value objects, or lightweight domain objects. The main issue is that you should not include business rules in these business entities.

Business Layer Considerations

The business layer in a services application uses a façade to translate service operations into business operations. The primary goal when designing a service interface is to use coarse-grained operations, which can internally translate into multiple business operations. The business layer façade is responsible for interacting with the appropriate business process components.
  • Components in the business layer should have no knowledge of the service layer. The business layer and any business logic code should not have dependencies on code in the service layer, and should never execute code in the service layer.
  • When supporting services, use a façade in the business layer. The term "façade" is French for “front” or “face”, and is often used to mean a "false front". In software, a façade represents the main entry point into a layer. Its responsibility is to accept coarse-grained operations and break them down into multiple business operations.
  • Design the business layer to be stateless. Service operations should contain all of the information, including state information, which the business layer uses to process a request. A service can handle a large number of consumer interactions, and attempting to maintain state in the business layer would consume considerable resources in order to maintain state for each unique consumer. This would restrict the number of requests that a service could handle at any one time.
  • Define all business entities within a separate assembly. This assembly represents a shared component that can be used by both the business layer and the data access layer.

Data Layer Considerations

The data layer in a services application includes the data access functionality that interacts with external data sources. These data sources could be databases, other services, the file system, SharePoint lists, or any other applications that manage data.
  • The data layer should be deployed to the same tier as the business layer. Deploying the data layer on a separate physical tier will require serialization of objects as they cross physical boundaries.
  • Always use abstraction when providing an interface to the data access layer. This is normally achieved by using the Data Access or Table Data Gateway pattern, which use well-known types for inputs and outputs.
  • For simple CRUD operations, consider creating a class for each table or view in the database. This represents the Table Module pattern, where each table has a corresponding class with operations that interact with the table.
  • Avoid using impersonation or delegation to access the data layer. Instead, use a common entity to access the data access layer, while providing user identity information so that log and audit processes can associate users with the actions they perform.

Performance Considerations

When designing the service interface, it is vital to use operations that are as coarse-grained as possible. This depends on the type of service you are designing. In an SOA service, the operations should be application-scoped. For example, you should define an operation that returns all of the demographic data for a person in one call; you should not define operations that return portions of demographic data as this would require multiple calls to retrieve the data.

Never think of services as being components with fine-grained operations that provide building blocks for an application. A service is an application that provides operations that are used to support different business processes. Avoid creating a web of dependencies between services and service consumers, and the chatty communications that would result from a component-based design. The end result would be poor performance, coupled with a design that is hard to extend and maintain.

When designing for maximum performance, consider the following guidelines:
  • Keep service contract operations as coarse-grained as possible.
  • Do not mix business logic with translator logic. The service implementation is responsible for translations, and you should never include business logic in the translation process. The goal is to minimize complexity and improve performance by designing translators that are only responsible for translating data from one format to another.

Security Considerations

Security in service applications covers a broad range of features and capabilities. However, you should be aware of these key considerations..

When designing a security strategy, consider the following:
  • When using message-based authentication, you must protect the credentials contained in the message. This can be accomplished by using encryption, or encryption combined with digital signatures.
  • You can use transport layer security such as SSL. However, if your service passes through other servers, consider implementing message-based security. This is required because each time a message secured with transport layer security passes through another server, that server decrypts the message and then re-encrypts it before sending it on to the next server.
  • When designing Extranet or business-to-business (B2B) services, consider using message-based brokered authentication with X.509 certificates. In the B2B scenario, the certificate should be issued by a commercial certificate authority. For Extranet services, you can use certificates issued through an organization-based certificate service.

Deployment Considerations

When deploying a service layer, consider the performance and security issues inherent within the production environment. Services may be deployed to a client, a single server, or multiple servers across an enterprise.

When deploying a service layer, consider following guidelines:
  • Locate the service layer on the same tier as the business layer to improve application performance.
  • When a service is located on the same physical tier as the consumer of the service, use TCP for communication.
  • If the service is accessed only by other applications within a local network, consider using TCP for communication.
  • Configure the service host to use transport layer security only if consumers have direct access to the service without passing through other servers or services.

Pattern Map

Category Relevant Patterns
Authentication Brokered Authentication
Direct Authentication
Federated Authentication (Single-Sign-On or SSO)
Authorization Claims Based Authorization
Impersonation and Delegation
Resource Based Authorization
Role Based Authorization
Trusted subsystem
Communication Duplex
Fire and Forget
Reliable Sessions
Request Response
Data Consistency Atomic Transactions
Cross-service Transactions
Long running transactions
Exception Handling Exception Shielding
Message Construction Command Message
Document Message
Event Message
Request-Reply
Message Endpoint Competing Consumer
Durable Subscriber
Idempotent Receiver
Message Dispatcher
Messaging Gateway
Messaging Mapper
Polling Consumer
Selective Consumer
Service Activator
Transactional Client
Message Protection Data Confidentiality
Data Integrity
Data Origin Authentication
Exception Shielding
Federation
Replay Protection
Validation
Message Transformation Canonical Data Mapper
Claim Check
Content Enrichir
Content Filter
Envelope Wrapper
Normalizer
REST Behavior
Container
Entity
Transaction
Store
Service Interface Remote Façade
SOAP Data Contracts
Fault Contracts
Service Contracts

Key Patterns

  • Service Contracts – Schemas that define operations that the service can perform.
  • Service Interface – represents the external contracts that consumers will use to interact with the service.
  • Façade – Provides a coarse grained interface to a set of operations to simply the calls.

Technology Considerations

The following technical considerations should be considered when designing a service layer:
  • Use Windows Communication Foundation (WCF) services wherever possible, for maximum feature availability and interoperability.
  • When using WCF, consider defining service contracts that use an explicit message wrapper instead of an implicit one. This allows you to define message contracts as inputs and outputs for your operations, which then allows you to extend the data contracts included in the message contract without affecting the service contract.
  • Use ASP.NET Web services (ASMX) for simplicity, but only when a suitable Web server will be available

patterns & practices Solution Assets

For more information on service interface layer design, message design, and versioning see the following sections of the Web Service Software Factory: Modeling Edition guidance:

Additional Resources

Last edited Dec 16, 2008 at 8:19 AM by rboucher, version 3

Comments

No comments yet.