Scott Hernandez
Vertigo Software, Inc.
November 1999
Summary: This article describes how and why the Fitch & Mather Stocks 2000 (FMStocks 2000) Store was added to the FMStocks 2000 application. New technologies added to these components are also explained. (13 printed pages)
Why Add a Store?
What Is the Store?
Implementing the Store
Store Walkthrough
Summary
About the Author
For More Information
The rationale for adding a "store front" and shopping cart to the Fitch & Mather Stocks 2000 (FMStocks 2000) core was twofold. We wanted to show how "user state" should be managed in Microsoft® Windows® Distributed interNet Applications (Windows DNA) applications, and how "large-grain" transaction processes can be offloaded from primary business or presentation servers.
In FMStocks 1.0, we used a farm of Web/business logic servers to handle the creation of dynamic active server pages (ASPs). The FMStocks 1.0 two-tier physical deployment had one tier of front-end servers and another physical tier for the Microsoft SQL Server™ 7.0 cluster on the back-end. Figure 1 represents what exists on each tier in this model.
Figure 1. FMStocks two-tier physical architecture
Note In a two-tier physical layout, we only have one tier that generates all of the presentation (IIS) and executes the business logic (COM+). Thus, these two services compete for resources on the same server, and overall scalability of the system is impacted. In FMStocks 2000, we gained additional scalability by adding a third physical tier to minimize this contention. Using Queued Components and Loosely Coupled Events to off-load CPU intensive business components to another application tier, we remove another potential scalability hindrance.
Adding store functionality also demonstrates how a Windows DNA application easily accommodates the added complexity that comes at the checkout point. When the user checks out of the store, the business process becomes complex. New constraints are introduced when incorporating financial systems, like credit cards. Complex issues also arise when enabling systems, such as inventory, shipping, authorization, physical workflow, and order tracking. Most of these systems require special security constraints or unique interoperability requirements.
To support the processes during and after a purchase, we made the operation asynchronous. Once an order is placed, a completely new tier of servers begins to process the order. The new tier offloads work from the primary business servers or presentation servers. Consequentially, these systems are also placed in a tighter blanket of security. In Figure 2, the N Physical tier deployment, the presentation tier does not require an immediate response when a store order is placed.
Note The ASP creates a component to process the order and immediately returns. The user sees a page that with a receipt of the order placement. An out-of-band process then handles the order via a queued component (QC). The Store Order Processor then notifies the user of the order status via e-mail when it is done.
Figure 2. FMStocks 2000 N-Tier physical architecture
The Store has two logical groups of functionality. The first group consists of the operation supporting the front-end ASP pages, which directly run the presentation tier server(s). They primarily manage the state of each shopping cart—summarized as the events before the Buy button is clicked.
These components also allow users to search the database of products. They do not require much CPU; they are lightweight without extra security constraints.
The second group of components represents all the processes triggered by clicking the Buy button. These asynchronous processes are handled on the other server tier(s). In the case of the FMStocks Store, a single subscriber responds to the ExecuteBuy event.
Note A subscriber receives calls made by the publisher in the COM+ Events architecture. An event is a single method in a COM+ interface, originated by a publisher and dispatched to the correct subscriber.
For more information about the implementation details of this process and details on how Events and other queued technologies are used, see Implementing the Store in this article. Summaries of the new objects are listed in the table below.
FMStocks 2000 Store Additions | |
Presentation Tier | 5 new ASP Pages |
Middle Tier: Business Logic | FMSStore_BUS.Product
FMSStore_BUS.ShoppingCart |
Middle Tier: Business Logic Events | FMSStore_Events.ShoppingCart*
(This is the event interface for ExecuteBuy.) |
Middle Tier: Business Logic Event Subscribers | FMSStore_EvtSub_OrderProc.ShoppingCart*
(This does the work for the ExecuteBuy event.) |
Data Access Layer | FMSStore_DB.Product
FMSStore_DB.ShoppingCart (Both of these object use DBHelper.) FMStocks_DB.DBHelper* (Used as a base for the FMStocks 2000 Store DAL.) |
Database Tier | 11 Stored Procedures
2 Tables |
When designing for performance and scalability, keep goals and constraints in mind. Our goal was to add a bookstore and richer state management to the FMStocks 2000 core. We defined the store functionality by listing technical and business constraints. The previous sections refer to a few of those constraints. The table below lists the store implementation constraints.
Priority | Store Implementation Constraint | Category |
1. | Must not impact FMStocks 2000 core performance. | Performance |
2. | Must be independent from FMStocks 2000 core. | Development |
3. | Must support asynchronous operation. | Performance |
4. | Can be installed an the same server as the core. | Development, Deployment |
5. | Business logic can be easily updated. | Development, Deployment |
6. | Must be easy to demonstrate state management. | Scalability, Availability |
We spent considerable time analyzing available technologies for risk. We reviewed each technology's individual risks, as well as the overall impact on the entire application.
First, we investigated how to support asynchronous operations. The following table lists the options. Queued Components is the selected method or option that we used.
Technology | Pros | Cons | Comments |
SMTP/MAPI | Easy to send mail | Hard to receive mail and call our components. | Exchange Server Events to watch and evaluate messages, but an Exchange Server is required. |
MSMQ | Great support for LAN and WAN networks, supports Windows NT® 4.0, and Windows 95 clients | Requires custom code, and custom message format definition.
Don't want to write a service to watch for new items. |
Sounds like a very good option. Supports most of our constraints. Local queues would permit everything to work on one server. |
Database Table | Already have a database server | H to manage the table, and write new code for this.
Don't want to write a service to watch for new items. |
Easy, but ties us into a single database. Could get complicated if we need to route requests. |
Queued Components | Allows Async COM Method calls. Very reliable. Supports COM+ Role based Security settings. | Interface requirements | Built on MSMQ |
Asynchronous DCOM | - | - | Not easily done in VB. |
Asynchronous RPC | - | - | No Asynchronous DCOM abstracts: not an option. |
Queued Components (QCs), a new feature in Windows 2000, are a near perfect match for the functions needed in an asynchronous model. They not only give simple async operations, but they also allow MSMQ to route between sites seamlessly. There is no need to write new code with QCs: the biggest drawbacks for QCs are the object and methods implementation restrictions. Here is an example of a QC:
'All parameters are in (ByVal) and there is no return value.
Public Sub ExecuteBuy(ByVal AccountID As Long)
'do work
End Sub
Note QCs and LCEs have the same interface restrictions.
Several methods are available as you strive toward the goal of "easily updateable" business logic. Business logic could be dynamically stored in a database table in some special format. The business logic could also be separated from the rest of the code in special functions or classes. Or, business logic could be isolated in a separate DLL or set of DLLs. You could even argue that business logic should be separated in special classes, within separate DLLs, with clear directions describing the update and the deployment process. We opted for the special classes, within separate DLLs, with one notable addition.
In COM, on Windows NT 4.0 or Windows 9X, the business logic component would have been created directly when an order was placed. This option would have made additions to logic or business processes difficult, without recompiling and replacing the DLL in use. In COM+, on Windows 2000, is a new set of services called COM+ Events. These services issue business tasks to multiple subscribers, from a single publisher.
LCE will allow us to write many different and separate Business Components, which all do work for a given task, or event.
LCE works much like a regular COM method call. Below is the code that publishes the event when someone clicks the Buy button.
'This method is called when the user clicks the Checkout button.
Public Sub Buy(ByVal AccountID As Long)
On Error GoTo errorHandler
If m_SendEvents Then
'send event for External Order Processing
Dim obj As FMSStore_Events.ShoppingCart
Set obj = New FMSStore_Events.ShoppingCart
obj.ExecuteBuy AccountID
Set obj = Nothing
End If
GetObjectContext.SetComplete
Exit Sub
errorHandler:
Set obj = Nothing
CtxRaiseError m_modName, "Buy"
End Sub
This method creates an instance of the event class, FMSStore_Events.ShoppingCart. Then it calls the ExecuteBuy method with the current shopping cart AccountID. But, behind the scenes, when the Event Class is created, COM+ does not actually create the component. COM+ is alerted that a new COM+ Event is about to be published. Then, on each method call of the object, COM+ fires that method to each subscriber. COM+ intercepts these object and method requests only for specially registered Event Classes.
Note Microsoft SQL Server provides a set of events (event classes) that can be used by SQL Server Profiler to monitor activity in SQL Server. An event class is an event generated within the SQL Server engine, such as the start of the execution of a stored procedure, a successful or failed connection to SQL Server, a transaction, or a lock time out.
One key advantage to using Events in COM+ is that the Event Framework is so open. You can do just about anything with events. In the case above, we have used Events to separate the business logic from the Order Process flow. Loosely coupled events can just as easily be used to instrument or monitor your component by publishing "known" events. For an example of this, look at the FMStocks_Bus.* classes in the FMStocks_Bus_w_Events folder.
Note COM+ 1.0 LCE supports two ways of firing Events: Series and Parallel. The subscribers can be called one after another or all at the same time. In either case, the publisher must wait until all subscribers have been called.
The second part of the COM+ Event Services is for subscribers. Subscribers actually do the work when the user does a Checkout. The following is the code for the subscriber example; it empties the shopping cart. This stub subscriber is shipped to show how and when the subscriber is used in the Checkout process. To be a subscriber to a COM+ Event, the Event Class interface should be implemented and registered with COM+ as an active subscriber.
The two types of Event Subscriptions are persistent and transient. Persistent subscriptions live through machine reboots and are set up through the Component Services application. Transient subscriptions require that the Event Admin Object be used to register subscriptions. These transient subscriptions do not last past a restart of the system. Transient subscriptions allow you to easily start and stop listening to events depending on external events.
Option Explicit
Implements FMSStore_Events.ShoppingCart
Private Sub ShoppingCart_ExecuteBuy(ByVal AccountID As Long)
Dim objSC As FMSStore_Bus.ShoppingCart
Set objSC = New FMSStore_Bus.ShoppingCart
'To show this is working, just empty the cart.
objSC.EmptyShoppingCart AccountID
'This is what this method really did:
'1.) verify funds via FMStocks_Bus (send email if problem)
'2.) Decrease Balance via FMSStore_Bus
'3.) Add Order to Oracle/SAP system
'4.) Delete shopping cart contents
'5.) Send email receipt
End Sub
The Product table is used for listing the store's stock. The ShoppingCart table holds the list of Product(s) that each Account has in their account. These tables and their relationships are shown in Figure 3.
Figure 3. Store-related tables
Each time action is performed to the ShoppingCart the request goes directly to the database. This way, independent of server type, the requests to the user's shopping cart are always consistent. It also means that no failure in any tier above the Data tier can cause the user's shopping to disappear. To keep failures from affecting the shopping cart, the data tier is a cluster of redundant servers. By storing the shopping cart state in the database, we can guarantee availability through the same mechanisms that already exist on the Data Tier, without adding any new hardware or physical tier.
Note During fail-over testing, we found that our database cluster recovered from server to server in less than 30 seconds. These failures only affect connections that were currently in the middle of retrieving data. All other users waited until the server was back up. After the data services have started on the other server in the cluster, users don't even know anything happened. From their point of view, the page just took an extra few seconds to get back to their browser. As far as most people on the site are concerned, there was never a problem. This allows the site to be extremely reliable—and always available.
By storing temporary user state in the database, we introduced another issue into the state management question. How long should state information exist in the database? The answer depends on the application. For demonstration purposes, we leave the shopping cart in the database until the user empties it or checks out.
An easy database cleanup method is a nightly routine that removes old data. Depending on state longevity, the process can be automated to "clean house" every few hours.
The Store has been written using the FMStocks 2000 core design pattern. We integrated ASP, Components, and database entities in the same fashion as the FMStocks 2000 core. For more information about the general design pattern of FMStocks see For More Information below.
Store design impacts results in the following ways:
Most of the visible store functionality can be seen on the product search, browse, and shopping cart pages. The shopping cart page shows cart contents. In Figure 4, the shopping cart summary page shows what products are currently in the user's shopping cart. Figure 4 also shows the current shopping cart total in the upper-right corner of the page.
Figure 4. Shopping cart page
Clicking "Proceed to Checkout" takes the user to a confirmation page that permits purchase and Checkout.
Figure 5. Checkout page
The Buy button calls the Buy method of the ShoppingCart object. The Buy method then publishes the ExecuteBuy Event to any subscribers. All of this happens very quickly.
Note Events can be marked as remote or queued. This changes the event behavior demonstrated so far. Marking your event as queued will cause your events to return almost instantaneously.
After the Event has been sent to all subscribers, the Buy Method returns the page (see Figure 6). Because the actual Order Processing might happen in an out-of-band process, this page confirms the order has been received. Then the user receives an e-mail when the order has been processed. These are courtesy implementations: it is possible that the process of fulfilling the order might take a considerable amount of time. Fulfillment may be contingent on issues such as procurement, shipping, or contacting other external systems.
Figure 6. Order confirmation
We learned some valuable lessons adding new service and functionality to an existing website. Some of those lessons are summarized below:
Scott Hernandez is a Senior Software Developer at Vertigo Software, Inc. As an MVP, he can be found roaming the Microsoft development newsgroups.
He and other Vertigo developers on FMStocks can be reached at fmstsocks@vertigosoftware.com or on the Web at http://www.vertigosoftware.com/.