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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.


