I am (metaphorically speaking) the man on the cover of this book. Or at least I was four years ago. That's when I first encountered the Microsoft Transaction Server (MTS), the precursor to COM+, and knew that my life as a COM developer had changed forever. I very rapidly discovered that the traditional COM object models I was used to did not work in the MTS environment. That annoyed and fascinated me, so I set out to understand why. At first I was blind in my belief that the MTS team had things all wrong--that its creators did not understand distributed objects at all. Over time, however, I came to see why MTS worked the way it did. The answer, quite simply, was scalability.
MTS was designed to simplify the development of scalable distributed applications, and everything it did was in service of that goal. Viewed in that light, the things MTS did with objects (e.g., not sharing them between clients and deactivating them when their transactions ended) finally made sense to me. While all of this was happening, I was spending a lot of time writing and teaching classes about MTS. I met a number of developers who were struggling the same way I had and who needed help. Like me, they wanted to know how MTS worked, why it worked that way, and, most important, how to design systems that used it. It became clear to me that I had a story to tell and that I had to write this book.
It took a long time. In fact, the writing process took so long that this book isn't about MTS at all, but its descendant, COM+. What Is COM+?
COM+ is a runtime environment that provides services to instances of classes that declare their desire to use the services. For example, if a class declares that it needs causality-based call synchronization, the COM+ runtime makes sure that only one logical thread of action invokes an instance's methods at a time. Or, if a class declares that it needs a distributed transaction, the COM+ runtime makes sure that one is available. COM+-based systems can be written in C++, Visual Basic 6, or any other COM-friendly language today; and the systems in C#, Visual Basic 7, or any other Common Language Runtime-friendly language tomorrow. The COM+ runtime serves as the foundation for many higher-level technologies, including Internet Information Server (IIS), Active Server Pages (ASP), Site Server, Application Center 2000, and Biztalk Server 2000.
COM+ is the cornerstone of a framework of technologies designed to support the development of large-scale distributed applications on the Windows platform. The current, shipping version of the framework is called Windows DNA. The next version is called .NET. Both versions have similar overall architectures that are based on three assumptions about the needs of scalable systems:
They must be accessible by multiple users on internal networks' machines and the Internet, running both browser-based and custom client applications. They must use multiple server machines to handle a high volume of client requests concurrently. They must be robust in the face of failure.
From these assumptions, both frameworks derive three basic principles:
System logic is consolidated on servers, not on clients or in backend databases. Servers can share resources (e.g., database connections), encapsulate database schemas and data access technologies, and offer a tightly controlled security environment. Transactions are at the center of the programming model. They provide a standard model for protecting distributed system state in the face of both concurrent access and system failure. The majority of system state must be kept under transactional control (e.g., in a database). The components in a system communicate using a variety of protocols. Clients typically communicate with servers using HTTP and, increasingly, Simple Object Access Protocol (SOAP); DCOM and Microsoft Message Queue (MSMQ) also are sometimes used. Servers typically communicate with one another using DCOM, MSMQ, and database-specific data access protocols; in addition, sometimes HTTP and SOAP are used.
COM+ is designed to make it easier to develop systems that adhere to these principles. It first assumed this position in the Windows DNA framework, and it retains it as we move forward into the .NET arena. What This Book Is About
Transactional COM+: Building Scalable Applications is about how and why COM+ works and how to build COM+-based applications. You cannot write software to solve a problem unless you understand the problem's essential nature and general solution, as well as the full details of the technology you are using. To that end, in the abstract, this book is about the design of scalable systems. In the concrete, it is about the mechanics of the COM+ runtime, including its use of processes, contexts, causalities, threads, objects, transactions, and communication protocols. What to Expect
Here is a brief description of each chapter in the book.
Chapter 1, Scalability, describes the basic problem of scalability, explains why scalable systems use transactions, and why they do not use traditional object models. It evolves the basic object model used in COM+-based systems.
Chapter 2, Atoms, describes context and causality, the two basic constructs on top of which all of the COM+ runtime services are built. It explains how both constructs relate to objects and how objects can interact with them.
Chapter 3, Mechanics, examines the relationship between contexts and objects, including the context relativity of interface pointers and the overhead that contexts represent in both time and space.
Chapter 4, Threads, introduces apartments and activities, the two higher-level constructs COM+ uses to regulate an object's degree of thread affinity and synchronization, respectively.
Chapter 5, Objects, focuses on object pooling and just-in-time activation (JITA) and how these services change the lifecycle of an object in order to use resources more efficiently. Special attention is paid to deconstructing the myths about the scalability benefits that JITA provides.
Chapter 6, Transactions, explores the mechanics of local and distributed transactions and introduces transaction streams, the higher-level construct COM+ uses to associate objects with distributed transactions.
Chapter 7, Isolation, discusses the basic techniques databases use to stop transactions from interfering with one another while at the same time maximizing concurrency and therefore throughput. Cross-transaction application-level locking schemes are also covered.
Chapter 8, Protocols, examines the integration between the Internet Information Server and COM+, including how ISAPI DLLs and ASP pages relate to contexts, apartments, activities, and transaction streams. In addition, SOAP and MSMQ are covered.
Chapter 9, Design, provides general advice on the design of COM+-based systems. Topics include implementing client tasks using one or more transactions; efficient data access; middle-tier, shared-state, and per-client conversation state management; and the inherent tension between scalability and reusability.
There are also four appendices. Appendix A, Toward .NET, covers the shift to .NET and explains how CLR classes take advantage of COM+. Appendix B, Building a Better Connection Pool, shows how to use object pooling to build a database connection pool that is more flexible than the one provided by OLE DB (and used by ADO). Appendix C, Debugging, provides useful information that makes debugging COM+ code easier. Appendix D, Catalog Attributes and Component Services Explorer Property Pages contains diagrams that map catalog attributes to the user interface elements on Component Services Explorer property pages. What Not to Expect
This book is intended for developers who are designing and implementing COM+-based systems. It assumes that you know how to implement COM classes and how to write a simple ASP page. It also assumes that you know how to use the COM+ and IIS administration tools, the Component Services Explorer (CSE), and the Internet Services Manager, respectively.
There are three COM+ topics that I did not include in this book. First, while this book mentions COM+ role-based security at a couple of points in the narrative where it becomes relevant, it does not include a complete treatment of the topic because it has already been covered in detail in Keith Brown's excellent book, Programming Windows Security.
Second, I chose to ignore the two ancillary COM+ services--Queued Components (QCs) and Loosely Coupled Events (LCEs)--because both mechanisms have significant limitations that render them useless in the general case. Specifically, although QCs can be used to send messages asynchronously into a COM+ server process, they cannot be used to send messages to other processes, that is, back to a client process. Although LCEs make it possible for a publisher to send an event to multiple subscribers without having to know who they are, the default delivery mechanism is a synchronous, blocking method call. You can make LCEs asynchronous by using them with QCs, but then events can only be fired into COM+ server processes. These problems make both services essentially useless for bidirectional client-server communication (they may in some circumstances be useful for server-server communication). In general, I discard both QCs and LCEs in favor of the Microsoft Message Queue, which makes it easy to build equivalent functionality without these unfortunate limitations.
Third, I did not include Compensating Resource Managers (CRMs) because of a lack of both time and space. Rules
This is not a COM+ cookbook. However, I have done my best to provide as much concrete advice as possible to help you understand how to design and implement COM+-based systems. Specific pieces of advice are identified as "Rules."
There are fewer rules in later chapters, a simple reflection of the fact that as topics get more complex there are fewer concrete guidelines on how to do things. The final chapter compensates for this by offering general advice on system design that follows the rules defined earlier. A Note about Source Code
This book includes a Web site, which features sample code and other resources. The URL is develop/books/.
I have done my best to ensure that this book is free of errors. However, given the scope of the work, especially spelunking through the dark corners of the COM+ runtime, there are bound to be some issues. If you find a bug, please post it to the book's Web site, where I'll maintain an up-to-date list of fixes. Acknowledgments
First and foremost, I would like to thank Sarah Shor for sharing her life with me. Never doubt that you come before all technology. Thank you also to the rest of my family for letting me ignore you for so long. And a special thank you to Alan Ewald for always being willing to share his experiences and insights about the design of distributed systems.
Thank you to all of my technical colleagues at DevelopMentor, the incredibly special community in which I am privileged enough to work. By participating in seemingly endless conversations about how COM+ works, you have influenced this work more than you know. A special thank you to Craig Andera, Dan Sullivan, Martin Gudgin, Jon Flanders, Bob Beauchamin, Stu Halloway, Simon Horrell, Keith Brown, and Chris Sells for believing that I had an interesting story to tell. And an incredibly special thank you to Don Box for knowing I had a song in my heart that I needed to sing and for helping me live a rich and fulfilling technical life. Thank you to everyone else at DevelopMentor, too. You have all been very patient with me while I finished this project. Thanks especially to Mike Abercrombie for understanding that my technical work had to come first.
Thank you to Simon Horrell, Dan Sullivan, Bob Beauchamin, Stu Halloway, Martin Gudgin, Alan Ewald, and Mary Kirtland of Microsoft for reviewing chapters and providing feedback. Thank you to all the students, conference attendees, and mailing list participants who have provided feedback about different parts of this story too. Thank you to Joe Long of Microsoft for answering questions about the mechanics of various COM+ runtime services and to Jonathan Hawkins of Microsoft for explaining the relationship between .NET and COM+.
Thank you to David Chappell for writing my foreword and for dressing so well. You give us all something to aspire too.
Thank you to everyone at Addison-Wesley who helped produce this book, including Marilyn Rash for speeding production despite my endless delays; John Wait for explaining some of the inner workings of the technical publishing industry; Carter Shanklin for signing my contract (before leaving Addison-Wesley to pursue other aims); and, most importantly, my editor Kristin Erickson for suffering through this with me and for still being willing to accept my phone calls.
And finally, thank you to Microsoft for creating the technologies that have kept me occupied for the past ten years. COM+ was quite a puzzle; keep them coming.