📄 ch10.htm
字号:
objects to other applications.<H3><A NAME="Heading5"></A><FONT COLOR="#000077">Mixed Server/Client Applications</FONT></H3><P>The guidelines for the use of threads in pure servers (applications that behaveas servers only, never as clients) are clear-cut: If the response time requirementswarrant it, multithreading is preferred; otherwise, single threading is adequate.The guidelines for pure clients are simple as well: Under most circumstances, multithreadingis not required. Therefore, you can conclude that single-threaded architectures areadequate for most CORBA applications. If your applications were all pure serversand clients, you'd be right.</P><P>When an application demonstrates behaviors of a server and a client--call it a<I>mixed server/client application</I> for lack of a better term--the design issuesassociated with using a single-threaded architecture become insidious. Illustratedin Figure 10.3 is the basic problem: If a single-threaded, mixed server/client applicationpasses one of its objects to a second application in a remote method call, and thesecond application, in turn, tries to access the object passed to it, both applicationsbecome blocked. <BR><BR><A HREF="javascript:popUp('03.jpg')"><B>Figure 10.3.</B></A> <I>Single-threaded mixedserver/client application operation.</I> <BR><BR>Of course, this problem is neatly solved by the use of multithreading in the mixedserver/client application, as illustrated in Figure 10.4. If multithreading is notan option for whatever reason, another solution is required. The remainder of thissection discusses potential solutions to the problems involved in developing single-threadedapplications that need to assume the roles of both client and server.</P><P>Presented here are two useful design patterns for designing CORBA applicationsusing only single-threaded components. Again, the use of multithreading is probablythe cleanest method of implementing CORBA applications, but when multithreading isnot an option, you will want to consider one of these design patterns.<H4><FONT COLOR="#000077">Object Factory Pattern</FONT></H4><P>Recall that single-threaded applications that are pure servers or pure clientsdon't suffer from the deadlock problem illustrated in <BR><BR><A HREF="javascript:popUp('03.jpg')"><B>Figure 10.3.</B></A> The <I>Object Factorypattern</I> <BR><BR>capitalizes on this property of pure client and pure server applications by movingfunctionality to the appropriate component of the application, resulting in applicationcomponents that are either pure clients or pure servers.<BLOCKQUOTE> <P><HR><B>Note:</B>In the <I>Object Factory design pattern,</I> a factory object is responsible for creating objects of a particular type. For example, the <TT>Bank</TT> object can be thought of as an Account factory, since Banks are responsible for creating all Account objects in the system. <HR></BLOCKQUOTE><P><A HREF="javascript:popUp('04.jpg')"><B>Figure 10.4.</B></A> <I>Multithreadedmixed server/client application operation.</I> <BR><BR>To understand how this is feasible, consider the following scenario: A client wishesto call a remote method on a server. The method takes a particular type of objectas a parameter; call it a Widget. Now assume that the Widget is created by the client.If the client were to pass a Widget that it created to the server through a remotemethod, and that method attempted to call a method on the Widget, the result wouldbe a deadlock scenario, as described in Figure 10.3. These are the typical applicationsemantics over which single-threaded applications stumble. It would be most usefulif these types of semantics could be achieved in a way that worked with single-threadedapplications.</P><P>This is where the Object Factory pattern steps in (see Figure 10.5). This patterntakes the place of the object creation step. Rather than create the Widget itself,the client requests the Factory (which is the same object as the server whose methodthe client wishes to invoke) to create the Widget on the client's behalf. The clientcan then manipulate the Widget, if desired, and can finally invoke the desired remotemethod on the server, passing the Widget as a parameter. Now, because the Widgetexists in the same address space as the rest of the server, the server can manipulatethe Widget as it sees fit. <BR><BR><A HREF="javascript:popUp('05.jpg')"><B>Figure 10.5.</B></A> <I>Object Factory pattern.</I><BR><BR>The Object Factory pattern boasts the advantage of enabling single-threaded clientsto pass objects as parameters to remote methods. This capability comes at a price:The server must provide methods for creating every type of CORBA object that a clientmight want to create. Although providing implementations for these methods is simple,it can be tedious, particularly in applications containing large numbers of classes.Also, it can be more inconvenient for clients to call additional methods to createobjects rather than to directly use constructors, although this inconvenience mightbe minimal. These drawbacks, however, are often outweighed by the advantages offeredby the Object Factory pattern.<H4><FONT COLOR="#000077">Exclusive oneway Call Pattern</FONT></H4><P>Another approach to creating harmony between single-threaded applications andCORBA is what you might call the <I>Exclusive </I><TT>oneway</TT><I> Call pattern.</I>This pattern calls for the exclusive use of <TT>oneway</TT> invocations throughoutthe application. Because <TT>oneway</TT> methods don't block, the deadlock issueassociated with single-threaded CORBA applications is eliminated. However, this advantagecomes at a price, as you'll soon find out.<BLOCKQUOTE> <P><HR><B>Note:</B>The <I>Exclusive </I><TT>oneway</TT><I> Call design pattern</I> calls for the exclusive use of <TT>oneway</TT> methods for communication between CORBA objects. <HR><BR> <BR> <HR><B>Note:</B>For a review of CORBA <TT>oneway</TT> methods, refer to Day 3, "Mastering the Interface Definition Language (IDL)." <HR></BLOCKQUOTE><P>The exclusive use of <TT>oneway</TT> method calls throughout a CORBA applicationexacts a potentially stiff penalty: First, the concept of a clearly laid-out programflow is lost. Consider a typical client application. There is generally a well-definedflow of control through the program. That is, there is a main method--it might verywell be C/C++/Java's <TT>main()</TT>--at which the program begins and proceeds tocall other methods. Usually, the flow of the program can be determined by tracingthe sequence of method calls. In other words, the behavior of the application isat least somewhat predictable because the execution flow can be traced relativelyeasily.</P><P>Using <TT>oneway</TT> methods exclusively, however, radically alters the landscapeof an application, as illustrated in Figure 10.6. Instead of a well-defined flowof control traceable throughout the application, the client features a series ofseemingly disjointed <TT>oneway</TT> methods. The exchange between client and server,rather than following the familiar pattern of "client calls server/server returnsresult" is transformed into a volley of <TT>oneway</TT> calls from one applicationto the other. The client starts by calling a method on the server. That method, whencompleted, calls a method on the client that performs the second step in the application.That method, in turn, calls another method on the server, which eventually callsa method on the client, and so on.</P><P>Again, because each method called is <TT>oneway</TT>, there is no blocking dueto the client or server being busy. Consequently, each application is free to passany CORBA objects--including objects created by itself--without fear of blocking.The downside of this architecture is that because the flow of control is now sharedbetween two applications, it is much more difficult to trace.</P><P>Another penalty that must be paid by developers wanting to use the Exclusive <TT>oneway</TT>Call pattern stems from a characteristic of <TT>oneway</TT> methods which you shouldrecall--namely, that <TT>oneway</TT> messages are not guaranteed to be deliveredto their destination. Building an entire application based on this mechanism is certainto be a trying experience, primarily because if there are any methods in the applicationwhich require reliable delivery, the developer must implement a mechanism to determinewhether a <TT>oneway</TT> method call actually executed successfully. In other words,the developer essentially must implement reliable delivery semantics on top of theunreliable <TT>oneway</TT> mechanism, in addition to implementing all the usual applicationfunctionality. <BR><BR><A HREF="javascript:popUp('06.jpg')"><B>Figure 10.6.</B></A> <I>Exclusive </I><TT>oneway</TT><I>Call pattern.</I> <BR><BR>To summarize the Exclusive <TT>oneway</TT> Call design pattern, it should be stressedthat this pattern would be extremely difficult to implement for most real-world productionsystems. Consequently, developers are strongly encouraged to pursue a different methodof marrying client and server functionality in a single-threaded application if atall possible.<H2><A NAME="Heading6"></A><FONT COLOR="#000077">Object Lifetime</FONT></H2><P>In a non-distributed application, management of object lifetime is a non-issue:When the application is finished using an object, it simply destroys it. With garbage-collectedlanguages like Java, the developer does not even need to write code to do this--theapplication handles it automatically. If the application crashes, the memory usedby its objects is reclaimed by the operating system. Because all objects are self-containedin the application, there are no issues associated with object lifetime.</P><P>In a distributed application, circumstances are different. An application mightuse objects that are local to the application--that is, objects that live in thesame address space as the application--or it might use remote objects, which mightreside in a different process on the same machine or on a different machine somewhereon the network. Many CORBA ORB products use reference counting for managing objectlifetime--a mechanism which works well when applications behave normally. Althoughthe use of a reference-counting mechanism is not dictated by CORBA, its inclusioninto some major ORB products merits some discussion here. Recall that in such a reference-countingmechanism, object references are duplicated--that is, their reference count is incremented--whenthe reference is passed to an application. Similarly, when an application is finishedusing an object, it releases the object reference, that is, decrements the referencecount. When the reference count reaches zero, the object is no longer in use andcan safely be destroyed.</P><P>But what happens when an application holding an object reference crashes beforeit can release that object reference? This is where the reference-counting mechanismbegins to break down. Under these circumstances, the object's reference count neverreaches zero, and thus the object is never destroyed. This can be thought of as asort of memory leak in a distributed application. Consequently, developers mightneed to think beyond the reference counting mechanism and consider a contingencymechanism that picks up where reference counting leaves off.</P><P>Because a distributed application cannot truly know when all other applicationsare finished using its objects (because it doesn't know whether any of those applicationshave crashed), a mechanism over and above the basic reference-counting mechanismis required. Such a mechanism manages the lifetime of CORBA objects, automaticallydetermining whether an object is in use and, if not, destroying that object. Buthow does this mechanism determine whether an object is still in use? Actually, itcan only <I>guess</I>. To understand how such a mechanism works, consider the followingcase study.</P><P>One such mechanism, known as the Evictor<I>,</I> manages object lifetime by trackingthe usage of each CORBA object within a server (each CORBA server would contain itsown Evictor). When an object has not been in use for a predetermined period of time(for example, a day), the Evictor <I>evicts</I> that object. Although it's possiblefor the eviction process to simply destroy the unused object, recall that the Evictordoes not know for certain that the object is no longer in use. It is possible thatone of the clients using that object could be dormant for a period of time, and ifthe object were destroyed, the client, on waking up, would no longer be able to accessthat object. To accommodate this possibility, the Evictor does not actually destroya CORBA object after a period of non-use but evicts it into a persistent store, suchas a database. If that object is needed later, it can be resurrected from the persistentstore. All this occurs transparently to clients, which are completely unaware thatobjects are being evicted and resurrected as necessary.</P><P>Of course, a mechanism such as the Evictor, rather than enabling potentially unusedobjects to consume memory in a server process's address space, simply moves the unusedobjects to some form of persistent storage. The result is that unused objects stillexist somewhere--in this case, the persistent storage rather than the server applicationaddress space. Using persistent storage for this purpose, in addition to offeringthe advantage of freeing up a server machine's memory resources, provides for simplermaintenance. That is, the objects in persistent storage can be cleaned up periodically,perhaps as a part of the system's periodic maintenance cycle. Purging the databaseof unused objects in this way would not require system administrators to bring downthe server, thus enhancing the server availability.<H2><A NAME="Heading7"></A><FONT COLOR="#000077">Lack of Pass-by-Value Semantics</FONT></H2><P>Perhaps one of the trickiest issues associated with CORBA development is thatCORBA does not currently support the capability to pass objects by value. (This limitationis expected to be removed in a later version of CORBA; see Appendix C, "WhatLies Ahead? The Future of CORBA," for more details on this and other future
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -