Mitchell I. Kramer, Patricia Seybold Group
Prepared for Microsoft Corporation
November 1996
Not much more than a year ago, multitier applications were at the leading edge of development. Only a few tools supported this architecture, and only a small number of production-level applications implemented it. Today, multitier applications are mainstream. Two factors are responsible for this dramatic change: scalability and the Internet. Two-tier applications don't scale well, and developers ran out of memory and processing resources on client platforms. As application logic grew in size, they needed some place to deploy the code. Finding places to run code other than on the client is also a key element of the Internet factor. For Internet applications, logic must be deployed on the middle tier. Everyone wants to Internet-enable existing applications or begin to do "e-commerce on the Web." With the requirements to support thin clients, all these Internet applications must have multitier applications.
Microsoft Transaction Server is designed to simplify the development of the middle tier of multitier applications by providing much of the infrastructure needed to execute the business logic that runs there. It will insulate developers from dealing with such issues as connectivity, security, directory, process and thread management, and database connection management—the infrastructure elements required to support robust, production-class, run-the-business Internet, intranet, or internal LAN applications.
Thirty to forty percent reduction in development. Microsoft estimates that Transaction Server will reduce the development effort for multitier applications by between 30 and 40 percent. We agree with that estimate, as do several developers with whom we spoke. A case study presented in this report identifies and qualifies the areas where Transaction Server delivers these reductions.
This report describes and analyzes the advantages of Transaction Server compared with custom approaches to creating the infrastructure needed to support multitier applications. It is divided into four sections. The first section will present the requirements for this infrastructure. In the next, the issues that developers have identified in building such an infrastructure will be examined. In the third section, we'll examine a real-life example of a custom-developed infrastructure: a customer contact system built by a line-of-business development team at a major bank in the Northeast. The final section will describe the capabilities of Transaction Server and analyze how Transaction Server might have been used for the customer contact system.
In order to get some perspective on the magnitude and complexity of the effort to build multitier applications, contrasting them with earlier two-tier structures will be useful.
The database did all the work. The databases at the back ends of two-tier client/server applications insulated developers from most systems, from networking, and from management coding. Databases performed connectivity, security, directory, transaction processing, and recovery. In addition, database routing software on the client handled all communications. As a result, the databases freed developers to concentrate on the business aspects of the application.
Databases also gave these applications performance and scalability. The number of users that an application could support was a function of the database. Developers ran on clients. Their code supported a single user. This code could be written inefficiently or might run on client platforms with limited resources, thus limiting performance and scalability; but improving performance and, especially, scaling up were database related.
Developers could concentrate on application logic when they built two-tier applications, but multitier applications are forcing them to expand development efforts to include infrastructure as well. Connectivity and the processing environment on the middle tier will require the most work. Two factors are responsible for the increased development burden:
Addressing these factors will complicate application development. Developers have told us that that 30 to 40 percent of the total time taken to build applications can be spent on these infrastructure tasks. Figure 1 shows the structure, components, and architecture of three-tier applications.
Figure 1. The components of three-tier applications are clients, application servers, and databases. Clients at tier one provide the user interface and, optionally, some portion of the application's logic. Application servers at the middle tier implement most of the application's logic. Databases at tier three provide persistent storage. Clients connect to application servers through a program-to-program protocol. Application servers connect to databases via SQL.
In two-tier architectures, all network communication between clients and servers uses SQL-related syntax. Either clients send SQL statements to the database or the database sends status codes and data back to the client. In three-tier architectures, this program-to-data communication takes place between tiers two and three. Program-to-program communication is needed between clients on tier one and servers on tier two in order to connect application logic that runs on both tiers in multitier environments.
Connectivity must be provided. To accomplish this communication, developers must write the code to connect clients with application servers, transfer data between them, and synchronize and coordinate their processing. Data flows must conform to some protocol in order for the communication to have any meaning. That protocol must define the format and structure of the data transferred, the meaning of their content, the sequencing and timing of sending and receiving, and the definition of errors and the approaches to be taken to recover from them.
In multitier architectures, application logic is shared among all users from a server. This is the biggest difference between two- and three-tier approaches, and the one that has the biggest impact on application development. The middle-tier environment must provide security, directory, performance and scalability, and availability and reliability, to the application. It must also provide database access and transaction management.
Security. The application servers that run on tier two implement applications' business logic and access databases in response to client requests. Because they may perform sensitive processing and update sensitive data, access to them must be secured. Ideally, a client must be authenticated, authorized, and granted access privileges before an application server processes a client's request. Security is very important in internal corporate environments; it is critical for Internet applications.
Directory. Directory capabilities are closely linked to security. A directory should contain information about all clients, servers, and databases for an application environment. This information should include identifiers, network locations, passwords, authorizations, and access privileges. It should be accessible to each client and server to assist in satisfying requests for services from the perspectives of location resolution and security.
Performance and scalability. Performance and scalability are key aspects of the middle-tier environment. Ideally, to address performance requirements, each client request should be serviced on demand. In order to address scalability requirements, developers should be able to plan on having the ability to service an ever-increasing number of client requests. The middle tier should support unlimited on-demand concurrency.
Availability and reliability. Application servers must be available to provide services whenever clients request them. When an application server is down, so is the business that it supports. However, servers can be unavailable for many reasons. Some are:
The code for the application server and the code for the environment that supports its execution must be bulletproof. Its reliability must approach that of the operating system on which it runs. Obviously, it must be thoroughly tested.
Recovery and restart. When failures do occur, application servers must have the capability to quickly recover from those failures and to restart themselves. Recovery should recapture as much user work as possible, and data must be left in a consistent state as well. If a server platform will be down for an extended time, the application server might be restarted on a different platform.
Transaction processing. Transaction processing is another aspect of processing that was handled by the database in two-tier environments. In cases where multiple, heterogeneous databases were accessed, developers used transaction processing monitors. In multitier environments, a transaction monitor approach will be required, driven by access to multiple heterogeneous databases, mainframe integration, and supporting resource managers other than databases—message queues, for example.
It takes longer to develop three-tier applications because there is more to build in them than there is in two-tier applications. And this is no small difference. Our experiences and the experiences of developers with whom we've spoken have consistently shown that 30 to 40 percent of a three-tier project can be spent on infrastructure items.
Not only does it take longer to build three-tier applications, but the additional development tasks are considerably more complex. In addition to the business domain aspects at the core of applications, developers get involved in security, directory, performance and scalability, availability and reliability, and recovery and restart. These are some of the most sophisticated aspects of systems and networking. These areas had been the domain of so-called systems programmers.
Developers of two-tier applications were skilled in their business domain and in the use of their selected development tools. Multitier applications will require that development organizations increase their skills base considerably through training, hiring, or consulting services. The technologies for which these additional skills are needed have long, steep learning curves. Hands-on experience has been a crucial factor in building these skills.
Once a multitier application has been deployed, developers have the ongoing responsibility of maintaining, extending, and enhancing both the application's business logic and its infrastructure components. Developers must perform these life-cycle activities not only in response to changes in the business but also in response to changes in operating systems, networking protocols, development tools, and databases. Infrastructure components are "closer" to systems than business logic is. Although they might be built on standard and/or open application programming interfaces (APIs), these APIs are subject to change, especially in the Internet environment, and frequent system changes can cause problems in their proper operation. As a result, maintenance activities can be complex and time-consuming, and they can occur far more frequently than business changes.
One of the most troublesome aspects of successful multitier development projects is that their success is project oriented. All of their infrastructure components were designed and built to address requirements for an individual project. They can't be used for other applications because they're too closely aligned with the application for which they were built. And, more than likely, they're entangled with business logic and can't be identified and extracted as modular components. They are stovepipes or silos—not sharable, not extensible, and not reusable.
A line-of-business development team at a major Northeastern bank built a three-tier customer contact system. Requirements for performance, scalability, availability, and ease of maintenance drove the architecture to three tiers. This was a very successful project, especially since it was the bank's first three-tier experience. A large team of developers from the bank and from a national consultancy completed the project in 18 months. The system supports over 900 users with very good performance. In this section, the system and the developers approach to the three-tier infrastructure are described. Illustration 2 shows the components, structure, and architecture of this application.
Tier one. In tier one, clients were built with Microsoft® Visual Basic®. They make up the user interface, minimal application logic, and the connectivity to middle-tier application servers. Dynamic link libraries (DLLs) accessed via program calls provide the connectivity. Clients also provide computer-telephone integration (CTI).
Tier two. Application servers at tier two provide the major portion of the application's business logic. They were built in C and deployed across four UNIX platforms. The code was written procedurally, and it incorporates all application capabilities through a single entry point.
Tier three. Tier three is a single Informix RDBMS. The database, which is dedicated to the customer contact application, is deployed on one of the four server platforms. In addition to the RDBMS, some tier-three processing involves access to mainframe DB2 databases through Customer Interface Control System (CICS) transactions.
Figure 2. The customer contact system was a three-tier client server application. Clients at tier one were built in Visual Basic. They provided the system's user interface. Application servers at the middle tier implemented all of the application's logic. Client-to-application server connectivity was accomplished through a custom-built protocol on top of TCP/IP sockets. Two databases made up tier three, an Informix RDBMS located on one of the four application server platforms accessed through SQL, and a DB2 RDBMS accessed through CICS transaction programs located on a remote mainframe accessed through a custom-built SNA LU6.2 gateway.
Connectivity. In an approach quite common for initial three-tier projects, the development team used Transmission Control Protocol/Internet Protocol (TCP/IP) sockets as the connectivity mechanism. The reasons were that sockets were available on all client and server platforms, they are well understood, and they offer good performance.
Connectivity between the middle-tier server and the mainframe was provided through a custom Systems Network Architecture (SNA) gateway using the LU6.2 CPI-C protocol, one of the native CICS protocols. As a result, no coding was required on the mainframe, but building the gateway was a major undertaking.
Considerable additional function was built on top of the sockets interface and the Common Programming Interface-Communication (CPI-C) gateway. For the sockets API, a message structure and protocol were created, a time-out capability was added, and a message-queuing capability was built. The application server wrote responses intended for clients to a persistent queue if clients were unavailable. For the SNA gateway, the development team also built time-out and message-queuing capabilities. A fixed number of SNA sessions was bound between the application server and the mainframe. When all sessions were in use, the next request was queued.
Security. No security capabilities were built into the customer contact system. Rather, the development team leveraged existing security. Users log on to UNIX on the server platforms with user IDs and passwords. The user IDs are then authenticated through Remote Access Control Facility (RACF) on the mainframe using the SNA gateway to transfer this information. Once users were authenticated, no additional security processing was performed.
Directory. Only rudimentary directory capabilities were developed. A configuration file on each client platform contained the network address of each of the four servers. Users attempt to log on to the first server on the list. The four entries in the list provide the only reliability and recovery in the system. That is, when a server is unavailable, the user logs into the next server.
Performance and scalability. The development team invested significantly in the performance and scalability of the customer contact system. Message queuing, process management, and a performance management system were built.
The performance management system was a major undertaking. The development team instrumented the application in order to collect information in real time at many key points during application processing. The information was managed in a memory buffer and displayed on X-Window terminals attached to the server platforms. Operators and administrators got up-to-the-minute information on response times and queue depths. This information was used for load-balancing and capacity-planning.
An instance of the application server was launched in an operating system process for each client request up to a maximum number of concurrent threads. When the maximum number was reached, subsequent messages would be queued until a process was completed.
Transaction processing. The capabilities of the Informix RDBMS and of CICS were used to provide transaction processing to the customer contact system. No attempt was made to coordinate Informix transactions with CICS transactions, although this distributed transaction processing support will become a requirement in the future.
Recovery and restart. The Informix RDBMS provided most of the recovery and restart function in the system through its transaction commit/rollback and its journal-based roll-forward and rollback capabilities. No recovery/restart capability was provided for tier-one clients. At tier two, messages representing responses to client are persistently queued when the client becomes unavailable, and requests for mainframe services, RACF authentication, or CICS database access are queued when all SNA gateway sessions are busy.
Availability. Availability was delivered through the ability of any client to log into any of the four servers. As described in the paragraph on directory above, clients maintain a configuration file of all four server addresses. When one server fails, they can log on to another.
The development team leader estimated that 40 percent of the development effort was devoted to building the described infrastructure. The infrastructure addresses the needs of the customer contact system, but the team leader admitted that it cannot be used for other applications and it would be difficult to modify or extend it to meet future application requirements.
Note that the infrastructure provides little or no capabilities in the areas of security and directory. Database pooling is not provided, either. Any efforts in these areas would have driven up the infrastructure development effort to half or more of the total project. On the other hand, the SNA gateway and the performance management system will not be common custom-built infrastructure capabilities.
A corporate charter to build a common infrastructure. Corporate IT at the bank has recognized the magnitude of the infrastructure development effort and the fact that it cannot be reused to support other applications. As a result, IT is leading a new effort to define requirements for an infrastructure and to address those requirements with open, standards-based products. The goals are to provide an infrastructure on which all future applications can be built and to minimize infrastructure aspects of future application development efforts. At this writing, requirements have been defined, and the bank is in the process of product evaluation.
Microsoft Transaction Server is an infrastructure product that can address a broad range of requirements in developing and deploying multitier applications. In fact, it would be a very good fit for the distributed processing requirements at the bank. Developers shouldn't be confused by the name of this product. Transaction Server can free developers from most infrastructure coding in addition to transaction processing functions. Let's take a closer look at what it does and how developers can take advantage of its capabilities, keeping in mind the development efforts at the bank described above and the more general issues of building multitier applications discussed earlier.
Three-tier structure and components. Transaction Server supports the multitier application structure and components that we've been discussing throughout this report. Clients at tier one provide the user interface and some amount of the application logic. Application servers at the middle tier provide most of the application logic. They run under the control of Transaction Server. Databases at the back end provide persistent storage for application information.
Component-based applications and application development. Transaction Server assumes component-based applications and a component-based approach to development. In general, we feel that components offer developers the best way to build distributed applications. Their object-oriented properties of modularity, information-hiding, and inheritance make them easy to extend and easy to maintain. Because they're large and coarsely grained, they very naturally implement entire business entities such as customers, products, or employees. So, at development time, they're easily reused, and at deployment time, they simplify application partitioning and distribution.
COM and ActiveX. Transaction Server leverages Microsoft's Common Object Model (COM) and ActiveX™ technology. COM provides the connectivity and defines the interfaces and protocols for communication within and between application components. Developers build and implement application components as ActiveX modules. The most salient description of Transaction Server is that it's a complete middle-tier server environment for ActiveX.
As we mentioned in the last paragraph, connectivity in the Transaction Server environment is provided by COM. When a user or a program references the interface of an ActiveX component by sending it a message or an event, COM will locate the component and route the message or event to it. The referenced component may be running on a local or remote platform. Local connectivity is provided by inter-process communications capabilities of Windows® 95 or Windows NT®. Remote connectivity is provided by TCP/IP networking.
In this environment, developers have to do little or no connectivity programming. They have only to make the ActiveX reference in their code. COM and DCOM (the distributed, networking extension to COM) do the rest. Directory services, described below, provide the key information to COM and DCOM for resolving ActiveX references.
Transaction Server leverages the security capabilities of Windows NT. Windows NT provides platform-based login via user ID and password and access control to resources by users and groups. Transaction Server extends access control to the individual interfaces of application components. This fine-grained access control may be implemented administratively within Windows NT users and groups. It may also be implemented programmatically within application components.
Transaction Server's security capabilities can minimize or eliminate many security-related developments. Its administrative approach will be adequate for many applications. If developers choose a programmatic approach, then they have the advantage of building on an existing structure. Transaction Server does not integrate with the security capabilities of non-Windows systems, nor does it provide rigorous authentication capabilities. Requirements in these areas would have to be addressed through programming.
Directory services are provided to Transaction Server and COM through the Windows Registry, Microsoft's directory for Windows 95 and Windows NT. The registry contains information about users, groups, applications, and ActiveX names and interfaces. It provides all the capabilities required to support multitier applications in the Microsoft Windows environments. Creating and maintaining the registry is an administrative task. Developers are insulated from it.
Transaction Server has several built-in capabilities to help developers address requirements for performance and scalability.
Automatic thread and process management. Transaction Server manages a thread pool for application server components. In response to a request for an ActiveX service, it allocates a thread, calls the ActiveX component on that thread, and returns the thread to the pool when the call completes execution. The assignment of the ActiveX components to server processes is determined by settings in the directory. This allows the components to be easily grouped to meet security and fault-isolation requirements, and it is especially attractive when developers integrate new components into a production environment.
This feature can reduce development significantly while improving performance and scalability. Thread and process management is an area that must be addressed for application servers. Here, developers get into the guts of the operating system. It's easier to work with processes, but it's more efficient to work with threads. Threads require less processing and memory overhead, but they're harder to manage. Custom-built approaches typically deal with processes, trading performance and scalability for ease of development. Transaction Server completely insulates developers from threads and processes.
Database connection pool. The database connection pool establishes and manages a set of sessions between the Transaction Server environment and databases that will be accessed by application server components. Rather than establishing database connections in line with application processing either on a request-by-request basis or on a session basis for each client, Transaction Server offers pools of preconnected sessions. The processing overhead incurred when connections are created and terminated occurs all at once within Transaction Server initialization and termination. That way, these expensive operations are removed from normal request execution, improving application performance. Memory usage is optimized because the size of the pool can be much smaller than what is required by statically assigning a connection to each client.
The database connection pool can reduce development effort and can improve application performance and scalability. Developers are completely insulated from the efforts to establish and manage database connections. They simply code the SQL statement to access information in their applications. Database connection pooling is a well-proven and frequently used technique. The development team in our banking example had planned to build a database connection pool but did not because of schedule constraints.
DCOM support. Developers can build highly scalable applications through DCOM support in Transaction Server. Application components may be distributed across several server platforms and may communicate with each other through DCOM. Developers access remote components in exactly the same manner as they access local components. DCOM does the work of locating components through the Windows Registry, where components register themselves when they are installed.
DCOM may also be used to perform load-balancing within multiserver environments. Transaction Server does not build in load-balancing capabilities, however. Developers would have to implement this capability themselves.
Transaction Server does not provide capabilities that explicitly address requirements for reliability and availability other than its support for transaction processing. Failover, the routing of a service request to an alternate server platform when the primary platform is unavailable, may be implemented by developers. They can leverage DCOM support to reduce the task of developing this important facility.
Transaction Server provides a transaction monitor that controls transactional access to resource managers. Transactions may access a single resource manager, or, through support of Microsoft's Distributed Transaction Coordinator (DTC) protocol, transactions may coordinate and synchronize access to multiple resource managers. Resource managers in the initial release of Transaction Server will be Microsoft SQL Server and those databases that support the ODBC interface. Future releases will implement the XA protocol, SNA LU6.2 protocol, and TIP (Transaction Internet Protocol) and, therefore, expand the types of resource managers and processing environments that can participate in transactions.
No coding required. The development effort to implement transactions is minimal. Developers do not have to specify Begin transaction, End transaction, or Abort transaction statements in their code. Rather, transactions are implemented by setting a property of an application component. If the component is marked "transactional," then Transaction Server will build a transaction around its processing. And any components referenced by the transactional component automatically participate in the transaction as well.
Transaction Server will affect the design of application components. If components are transactional, then all of their processing will be encapsulated in a single transaction. Developers must take care to keep the scope of processing granular with respect to resource manager access.
The Shared Property Manager of Transaction Server provides a mechanism to share and access global information among server processes. Developers can use the Shared Property Manager for a range of tasks, including workflow, performance monitoring and management, and process serialization through global locks. Implementation of the performance management system in our banking example would have been facilitated by the Shared Property Manager capability.
The Shared Property Manager eliminates the housekeeping tasks needed to share information among applications. It takes care of memory management, freeing developers to concentrate on program logic. Also, because it's a centralized facility, the fragmentation and leakage that might occur when individual developers create and manage global data pools for single purposes can be eliminated.
Middle-tier application components that run under control of Transaction Manager are implemented as ActiveX DLLs. Developers may build these components in many languages using a range of development tools. Supported development tools currently include:
Language independence. The range of tools supported for ActiveX development makes ActiveX and, in turn, the Transaction Server environment virtually language independent. Language independence means that Transaction Server will be easy to learn and easy to use. The ActiveX modules deployed as middle-tier server components are easy to create. Developers have to remember not to include visual components. The hard part is in designing them to be modular.
Developing transaction server components. Transaction Server is not completely transparent to developers, but it comes very close. To build a Transaction Server component, developers will make use of one new API call and one new object interface. The API call GetObjectContext provides developers with the information needed to understand the processing state and context of a call to a server component. The object interface IObjectContext provides several methods for managing this state of a server component, including performing programmatic access control and indicating the outcome of the call.
Invoking an application server component. To invoke a Transaction Server component, clients or other Transaction Server components create an instance of that component. In Visual Basic, this is done with the CreateObject statement. In Visual C++, developers use the CoCreateInstance API. The parameters of these statements specify the component name and an object reference. COM, the Windows Registry, and the Transaction Server work together to locate the component and create a new instance (object) for the client. This is how Visual Basic Remote Automation servers and other remote OLE servers had been invoked prior to ActiveX and Transaction Server. There is nothing really new here, except that the Transaction Server also establishes and manages the execution context for the object. For example, this is how transactions are automatically provided from components.
Transaction Server components are deployed as packages. Packages are the unit of deployment and distribution for Transaction Server applications. Their definitions have considerable flexibility. Examples are:
Microsoft Transaction Server provides infrastructure facilities that can significantly reduce the time and skills required to develop and deploy multitier Internet, intranet, and internal LAN applications. This product insulates developers from complex systems-oriented tasks, such as process and thread management. It also eliminates the need for them to get involved in tedious, time-consuming tasks such as directory management. Combined with the capabilities of DCOM, Transaction Server offers a very attractive package.
If the Transaction Server could have been used for the custom contact system in our banking case study, we estimate that approximately two-thirds of the 40 percent of the development effort devoted to infrastructure could have been eliminated. Transaction Server would have reduced infrastructure development in several areas, such as the following:
DCOM would have provided most of the connectivity functionality that the development team built on top of sockets. Developers would not have had to write any communications code.
Process and thread management capabilities would have simplified development, and, through the use of threads instead of processes, both application performance and scalability could have been improved. Transaction Server would have eliminated all development done for the customer contact system in this area and would have provided a better solution.
Transaction Server could have provided the database connection pool that the development team did not have the time to build, thus improving performance and scalability.
The Shared Property Manager would have reduced the effort to build the performance management system. Memory management coding could have been eliminated. However, most of the performance management system would still have had to be developed.
SNA LU6.2 resource manager support, available in a future Transaction Server release, could have simplified integration with RACF and CICS. Developers would not have had to custom-build an LU6.2 gateway, which is a very complex task.
Some infrastructure development would still be required. Some aspects of the customer contact infrastructure are not addressed by Transaction Server. Those are persistent queuing, load-balancing, and failover, although the bank's static client configuration files can hardly be considered to be a robust implementation of load-balancing or failover.
Reusable for future applications. By and large, however, the advantages of Transaction Server compared with custom infrastructure development are quite significant. And, from a broader perspective than the development of a single application, the Transaction Server infrastructure is not a stovepipe solution. Its infrastructure is sharable among multiple applications, and components built to run in its environment may be easily reused.
The infrastructure built into the Transaction Server environment can have an immediate, positive impact on the development of multitier, component-based applications. At first release, it will have a distinctly Microsoft orientation. Indeed, DCOM is its foundation. But future releases will begin to offer good integration with non-Microsoft resources. For example, support for XA and SNA LU6.2 will provide access to a broad range of resource managers and will integrate mainframe resources. In addition, through Microsoft partnerships with Digital and Software AG, DCOM will be supported on many non-Microsoft platforms.