DBMS
 

 


Inside DCOM: Microsoft's Distributed Object Architecture Extends the Capabilities of COM to Work Across the Network. By Mark Roy and Alan Ewald

Complex multitier applications are becoming more and more commonplace as companies rush to meet their information processing needs. Distributed object computing is a key enabler for these applications: It combines object-oriented concepts with client/server technology to produce a framework for building modular and scalable distributed applications at a relatively high level of abstraction.

To date, the Object Management Group's CORBA specification and corresponding products have provided the distributed object computing platform of choice. [For more information on CORBA, see Warren Keuffel's article in DBMS, March 1997, page 42.] Software professionals must now seriously consider another distributed object architecture from Microsoft Corp. called Distributed COM, or DCOM.

DCOM is an extension of the Component Object Model (COM), which has been part of the Windows family of operating systems for many years as the underlying framework that makes OLE, and more recently ActiveX, possible. COM is an object-based framework for developing and deploying software components. COM lets developers capture abstractions as component interfaces and then provide binary classes that implement those interfaces. Encapsulation is enforced by COM such that client applications can only invoke functions that are defined on an object's interface.

COM's binary interoperability standard facilitates independent development of software components and supports deployment of those components in binary form. The result is that ISVs can develop and package reusable building blocks without shipping source code. Corporate application developers can use COM to create new solutions that combine in-house business objects, off-the-shelf objects, and their own custom components.

DCOM extends COM to the network with remote method calls, security, scalability, and location transparency. As DCOM becomes available on platforms other than Windows NT and Windows 95, companies can build software architectures that take advantage of their existing infrastructure and deploy business objects that access legacy applications and databases.

In this article, we present an overview of the DCOM architecture. We begin with a discussion of the fundamentals of COM and then show how DCOM extends the architecture for the network.

COM Overview

COM is an object-based programming model designed to allow development of software components at different times by different vendors using a variety of languages, tools, and platforms. Once developed, COM components are easily deployed and integrated in a customer's environment. To appreciate how COM development and deployment is possible, it is important to understand some of COM's key concepts, including interfaces, classes and servers, object life cycle, binary interoperability, and location transparency.

Interfaces

A COM interface defines the behavior or capabilities of a software component as a set of methods and properties. An interface is a contract that guarantees consistent semantics from objects that support it. Each COM object must support at least one interface (called IUnknown), although it may support many interfaces simultaneously.

Component designers describe interfaces using Microsoft's Interface Definition Language (MIDL), an object-oriented extension of the DCE RPC IDL. Microsoft provides an MIDL compiler that generates proxy and stub code in C or C++ from an interface definition. The generated proxy code provides a client-side application programming interface (API) for objects that support the interface in question. Stub objects decode incoming client requests and deliver them to the appropriate object in the server. Internally, the proxy and stub code interact with the appropriate runtime libraries to exchange requests and responses. The COM runtime software is smart enough to bypass this extra work in the case of objects deployed in the same process as the client.

Component designers assign a universally unique identifier (UUID) to each interface to eliminate any ambiguity that might arise from name collisions. The identifier, called an interface identifier or IID, is also the cornerstone of COM's interface versioning model.

Each COM object must support at least the standard IUnknown interface. IUnknown defines methods that provide the basic building blocks for managing object life cycles and allowing graceful evolution of interfaces supported by an object.

The QueryInterface method of IUnknown is used by clients to determine whether or not a particular interface, specified as an IID, is supported by an object. Over time, an object may support new interfaces or new versions of the same logical interface, each with its own unique IID. Existing clients can continue using an earlier version of an interface without even being recompiled, and new clients can query for -- and take advantage of -- the latest version of the interface.

QueryInterface returns a pointer called an interface pointer. Internally, an interface pointer points to a data structure that is dictated by COM's binary interoperability standard (further described later in this article). The standard dictates the way interface functions must be called, regardless of differences in the implementation environments of the client and server programs.

Classes and Servers

Interfaces by themselves are not sufficient to build complete COM applications. A COM class is a body of source code that is, among other things, an implementation of one or more COM interfaces. It provides real functions in any supported programming language for each interface method it supports.

Just as each interface is uniquely identified by an IID, each COM class has a unique identifier, called a CLSID. To interact with a component, a client application must know about (or be able to find out about) at least one CLSID and an IID for an interface that is supported by that class. Using this information, a client can ask COM to create an object and return an appropriate interface pointer.

One or more COM classes are packaged into a server using one of several available techniques. A COM server can be packaged as a dynamic link library (DLL) that is loaded into the client process when a class within the server is first accessed by a client. This is called an in-process server. An ActiveX control is an in-process COM server. A COM server may also be packaged as a separate executable. This type of server can run on the same machine as a client or on a remote machine that is accessible using DCOM. These servers are called out-of-process servers. The client code for interacting with the different kinds of COM servers is identical.

Client applications interact with COM objects through interface pointers. Encapsulation provided by COM ensures that a client is not dependent on any implementation details of a COM object. In the case of in-process COM servers, calls made by a client using an interface pointer go directly to an object that is created in the client's process. Calls to objects in an out-of-process server go first to an in-process proxy object responsible for invoking the request using a remote procedure call. In the out-of-process server, a stub object receives each incoming call and dispatches it to the appropriate COM object. Figure 1 shows a COM client interacting with COM objects packaged in several different ways.

Object Life Cycle

Now that you have a basic understanding of the concepts of interface and class and the communication between COM client and server, let's examine how a client causes a COM object to be created in the first place. Each COM object is an instance of a COM class. Each COM class is associated with another COM class called a class factory, whose job is to create instances of a COM class. COM's factory mechanism is illustrated in Figure 2. The factory typically supports a standard interface defined by COM, called IClassFactory. Given a CLSID and a description of the associated COM server, the COM runtime can locate a factory for the given CLSID.

A client application interacts with the factory for a COM class in a standard way to create an instance of the class and obtain an interface pointer to the resulting COM object. Figure 3 shows an example of how COM interfaces, classes, and objects relate.

Once a COM object has been created, COM specifies a standard protocol for tracking how many outstanding references there are to an object and when that object can be destroyed. COM objects maintain a reference count that is manipulated through the AddRef and Release methods defined on the IUnknown interface. Each COM class must implement these methods to track the number of current uses of its instances. At the discretion of the developer, this reference tracking can be done as a single count for the entire object or as individual counts for each interface the object supports.

When a reference count goes to zero, it is assumed that there are no longer any clients referring to the object, and thus it can be destroyed. Any methods that return interface pointers, including QueryInterface, must call AddRef to indicate a new reference to an object. Clients using interface pointers must call Release when they are finished accessing an interface pointer.

Binary Interoperability

A central theme of COM is interoperability of components. To that end, COM defines a binary call standard that dictates the layout of the call stack for all method invocations. DCOM augments this interoperability by defining a network interoperability protocol. These interoperability specifications enable developers to focus on building components without worrying about customizing them for different client environments. The binary standard makes it easy to use off-the-shelf components without having access to source code.

The binary standard defines an interface pointer as a pointer that points to a pointer to a function table. For in-process servers, the function table points to actual object implementation functions. For out-of-process servers, the function table points to proxy functions.

Packaging Transparency

A key feature of the COM architecture is packaging transparency. Developers can deploy components as DLLs or as executables. COM client applications need not be concerned with how a server is packaged or where its DLL or executable is located. Instead, the application uses COM to create objects based on a desired CLSID. The client can restrict the kind of server but does not need to do so. The client code for interacting with an in-process server is identical to that for calling out-of-process servers.

The COM Library locates the implementation of a requested class and establishes a connection between the client and the server. COM offers this service by requiring providers of COM classes to register information about the type of server and the location of its DLL or executable in a local registry.

COM's Service Control Manager (SCM) has the job of looking up the CLSID in the registry and taking the appropriate action to activate the server. Developers do not interact with the SCM directly; instead, the COM library uses the SCM when asked to create an object or locate a class factory.

How DCOM Extends COM

Distributed COM extends the programming model introduced by COM to work across the network. These extensions include improved location and packaging transparency, additional threading models, new security options, and additional administration capabilities. In this section, we briefly examine each of these extensions.

Location and Packaging Transparency

With COM, client applications are written independently of the packaging of the server. COM objects may be loaded into the client process or launched in a separate process on the same machine. DCOM extends this transparency to include location transparency, allowing objects to exist anywhere on the network.

DCOM "Object RPC" (ORPC) is based on DCE RPC. It extends RPC to include an object reference datatype and adds a parameter to each call for the target object. When a client requests a COM class factory for a remote object, the local SCM contacts the SCM on the remote machine. The remote SCM locates and launches the server and returns an RPC connection to the requested class factory provided by the server. A class factory proxy is created for the client application, and the object creation continues as in the nondistributed case.

With appropriate administration settings, clients can access DCOM objects on remote machines without specific coding for the network. An administrator can experiment with various server packaging and location options to optimize performance and scalability. Alternatively, clients can specify the remote host that should be accessed when creating a new DCOM object. This input could come from application settings controlled by the end user.

Another packaging option introduced with DCOM is the ability to deploy a DCOM server as an NT Service. This capability provides a consistent and convenient mechanism for managing servers that need to be available whenever a particular server machine is running.

Free-Threading Model

Several factors impact the scalability of distributed object systems. To achieve the highest throughput on a single machine, developers typically need to build multithreaded servers. This type of object concurrency enables the server to leverage the power of a multiprocessor server machine. DCOM extends COM's support for development of multithreaded servers in any of the server packaging modes we described earlier in this article.

Prior to the introduction of DCOM on Windows NT 4.0, multithreaded COM servers were restricted to a form of threading called apartment model threading. This model limits each COM object to be accessed by a single thread: the one that created the object. Windows NT 4.0 introduces a concurrency model called free threading.

With free threading, each incoming object invocation may be handled by a separate thread, and multiple incoming calls can be dispatched on a single object at the same time in different threads. Dispatching is managed by the COM library in conjunction with the RPC runtime library. The burden is on the developer to use concurrency primitives such as mutexes to ensure that all of the objects are thread-safe; for applications that need the highest performance, however, the added complexity pays off.

Security

An important part of any distributed architecture is its support for security. DCOM provides multiple levels of security that can be selected as needed by the developer and administrator. The ability to configure security of a component provides another level of transparency for developers: The same binary component can be used in one environment with no security requirements and in another environment that requires very strict security.

DCOM achieves this transparency by supporting Access Control Lists (ACLs) on COM components. If the requesting user is not allowed to access or launch a component, DCOM will deny the request before the component code is ever involved.

For high-level security, you can manage ACLs with a tool called DCOMCNFG. Using this tool, an administrator can manage which users and groups have access to specific object servers on a particular machine. A machinewide default is available as well, which initially permits only administrators to access DCOM objects remotely. One additional level of security that DCOM offers is the ability to control which users and groups are allowed to launch a server. By default, only administrators are allowed to launch remote DCOM objects.

To achieve finer levels of security granularity, DCOM methods can programmatically control authorization of individual method invocations. Using a combination of registry keys and Windows NT APIs, a method can implement custom security policies.

Reference Counting and Pinging

One of the issues faced by distributed application developers is writing servers that can detect when their clients have died. This is particularly important with DCOM, given the use of reference counting to determine when an object should go away. The typical solution is to perform periodic pings that indicate that a process is still alive. In the world of distributed objects, this could result in a vast amount of network traffic between clients and components simply to track the status of the relevant processes. Fortunately, the DCOM architects designed pinging support with high performance in mind.

To optimize pinging, DCOM uses keep-alive messages on a per-machine basis. That is, independent of the number of client processes on a machine and the number of component servers being accessed on a particular remote machine, a single ping message is used between machines. If a client process dies, DCOM detects the situation and invokes the Release calls on the appropriate server interface pointers. Additional optimizations available in DCOM include piggybacking ping messages onto ordinary requests and tracking changes to the set of remote references instead of always transmitting the entire set.

To accomplish this tracking, DCOM implements a component called the Object Exporter, which tracks objects and object references that have been exchanged with other machines. The Object Exporter is responsible for tracking the liveness of client processes on a given machine.

Administration

Distributed object computing has matured significantly over the past several years, yet management and configuration of large-scale distributed object environments are still daunting tasks. The initial DCOM environment is no exception. DCOM provides tools to make the job easier, but it is certainly not trivial.

Each deployed component must be registered on individual client machines as well as one or more server machines. In a small deployment, installation and maintenance are not an issue. As the number of client and server machines and components involved grows, network managers should be concerned with balancing the load of client requests across multiple server machines. DCOM does not have built-in support for load balancing. If an application does not balance the load dynamically, the network manager must statically configure the environment such that certain client machines use a specific server. If a component must be moved to a different server machine, every reference to the old machine must be updated. A similar issue arises with respect to failover. With DCOM, there is no straightforward way to indicate that a client should look for a server on one of a list of machines instead of one specific machine.

Today and Tomorrow

DCOM is part of Windows NT 4.0; at the time of this writing it had entered what is likely to be the final beta test for Windows 95. You can download the Developer Beta RC2 version from Microsoft's Web site and try it out yourself. To satisfy the demands of customers with heterogeneous environments, however, DCOM must go beyond its Windows-centric roots. To accomplish this, Microsoft enlisted Software AG and Digital Equipment Corp. as partners. A beta form of DCOM on Solaris is currently available from Software AG and is expected to be released during 1997 on a number of platforms, including IBM MVS, OS/400, and AIX, HP-UX, Digital Unix and OpenVMS, Linux, and SCO UnixWare.

Regarding improved scalability and robustness, DCOM is counting on a pair of new Microsoft technologies. The first is the next-generation Directory Services, scheduled to ship with Windows NT 5.0. These services will provide a highly scalable store for object references and security information for DCOM.

The second technology extending the reach of DCOM is the Microsoft Transaction Server, which began shipping in early 1997. Transaction Server is a transaction processing system that enables development, deployment, and management of multitier applications composed of COM and DCOM objects. DCOM is used for all object communication among machines. Transaction Server transparently provides transaction support to objects; it also manages threads, processes, database connections, and shared properties so that developers can focus on providing business objects. Transaction Server has a tight integration with SQL Server, but it is architected to support a wide range of databases.

Another area in which COM and DCOM will be important is database access. Microsoft's OLE DB specifies how databases should interoperate and how applications will access databases. [For more information on OLE DB, see Ken North's article in DBMS, November 1996, page 87, or refer to David Linthicum's column on OLE-enabled middleware in DBMS, January 1997, page 26.] OLE DB will provide a single set of component interfaces that let any kind of data store expose data in a tabular form. As Microsoft pushes to provide enterprise-level solutions, OLE DB will be the means to access all corporate data, not just data in relational databases. OLE DB is not intended to replace ODBC. Instead, it will access relational databases through ODBC. Third parties will support non-RDBMS access.

DCOM is poised to be a key player in the world of multitier distributed object solutions. It provides all of the basic components necessary for designing and deploying sophisticated systems, and it promises numerous scalability and robustness improvements in the years to come.


Mark Roy is a principal consultant at Semaphore (North Andover, Massachusetts) and has been designing and developing distributed object systems since 1990. Prior to merging with Semaphore, Mark cofounded NetLinks Technology, a leading provider of distributed object consulting and training. You can email Mark at mroy@sema4usa.com.

Alan Ewald is a software architect at NobleNet Inc. (Southboro, Massachusetts) and has been designing and developing distributed object technology and applications since 1990. Prior to joining NobleNet, Alan was a principal consultant with Semaphore and a cofounder of NetLinks Technology. You can email Alan at aewald@noblenet.com.



* Microsoft Corp., Redmond, WA; 800-426-9400, 206-882-8080, or fax 206-936-7329; www.microsoft.com.


Figure 1.


--DCOM provides location and packaging transparency. An object can be in-process, out-of-process on the local machine, or out-of-process on a remote machine. In the case of out-of-process servers, DCOM uses interface-specific proxy and stub code (typically generated from an IDL file) and an RPC mechanism.


Figure 2.


--COM servers expose classes and class factories. When a client application requests creation of a new object, COM locates and loads or launches the server and asks the factory to create an object. COM returns an interface pointer to the client, and subsequent calls are invoked directly on the COM object.


Figure 3.


--A COM interface defines a related set of methods and is assigned a unique interface identifier. A COM class implements one or more interfaces and is assigned a unique class identifier. Each COM class has an associated class factory responsible for creating COM objects.


Subscribe to DBMS and Internet Systems -- It's free for qualified readers in the United States
April 1997 Table of Contents | Other Contents | Article Index | Search | Site Index | Home

DBMS and Internet Systems (http://www.dbmsmag.com)
Copyright © 1997 Miller Freeman, Inc. ALL RIGHTS RESERVED
Redistribution without permission is prohibited.
Please send questions or comments to dbms@mfi.com
Updated Tuesday, March 18, 1997