What Makes Server-Based Development Different?

Even if you agree that server-based development is the " next big thing" in software development, you might still wonder why server-based development deserves its own book. You aren't alone. When I first thought about server-based development as a book topic, I had to define exactly what I meant by it. My criterion for what qualifies as server-based development made it clear to me that server-based programs really are different. Recall my definition: a server program is one in which the user interface does not exist or is separate from or incidental to the function of the program. In the case of Windows 2000 Server, programs are created for an operating system that is closely related to a standard desktop operating system, using the same development tools. Let's take a look at how server-based programs differ from other programs and how their differences are handled.

The Server Is Unattended

Think about the kinds of events that our programs deal with every day:

  • A modem dials out and is unable to connect to the computer that it dials.
  • The file system tries to write to a sector on the disk and does so only after a number of retries.
  • A hardware device fails to initialize properly.
  • A user tries but fails to log on to the system several dozen times.
  • A resource error occurs. (For example, a file is opened by a different system exclusively, memory or disk space is not available, or a record in a database is locked.)

Now think about how server applications are used. Often you will not find the servers near the users, but rather locked away in wiring closets or in a computer room. Unlike users of desktop systems, users of server-based systems are isolated. If you have ever been involved in technical support, you can well imagine the conversations you have with the users of server-based systems when an error occurs:

"Technical support, may I help you?"
"My ServerTron 2000 has stopped working."
"Do you know who was on the system when it failed?"
"No."
"Do you know when it failed?"
"No."
"Was there any error message when it happened ?"
"No one was around ”we just noticed that it was not working this morning. The system was locked up."
"Please hold on "

Obviously, we need a better way to track what is going on with a server application. I have learned from hard experience that even when a user is directly in front of a machine, getting a coherent explanation of what happened when a system failure occurred is often impossible . For server applications, the user is not a potential source of information.

In addition to the lack of user feedback regarding failures, server-based systems do not provide the chance to gather information about impending failures from users sitting at their keyboards. How many times have you decided that a computer is in an unstable state and restarted the computer at a convenient time? Isolated from the actual computer on which the server application is running, the user is less likely to see signs of impending disaster.

The solution to the problems of tracking and user isolation is event logging, which is covered in Chapter 5. The Win32 API (application programming interface) provides functions to log system warnings, events, and errors. For years , programmers have used proprietary log file formats to record system activity. This system is better than nothing, but it is still a challenge to get the kind of systemwide view of activity that is sometimes required to diagnose difficult problems.

Logging events is one thing; making that information available is another. What makes event logging difficult also makes it difficult for logged information to go where it will do some good. The Win32 API provides some functions that can make information available to people away from the keyboard. Messaging API (MAPI) and Telephony API (TAPI), both covered in detail in Chapter 7, aid the server developer by keeping an administrator aware of the state of the system. MAPI allows the system to use an e-mail system. Depending on the problem, MAPI sends a message alerting an administrator. For more immediate errors, TAPI allows a system to page an administrator regarding the problem. This kind of exception reporting allows a system administrator to be on top of system problems without being physically present.

Resource Leaks Are Hidden Bugs

Imagine a moderately loaded server application. Now further imagine a memory leak that causes the system to allocate 1024 bytes and not release them each time the system performs a particular operation 10 times an hour . The numbers add up quickly. Do the math: 10 KB per hour times 24 hours times 7 days equals 1.68 MB of leaked memory allocations in a week. Run this software for a couple of months, and at best the machine will be thrashing; at worst it will simply stop working. If instead you have a traditional client application, 10 KB per hour times an 8-hour work day equals an 80-KB leak of memory over the course of a day. This leakage probably isn't a showstopper, but it is surely a result of sloppy programming.

The same rule applies to system objects such as file handles, database locks, and semaphores: add a little to a little, and soon you have a big pile. Errors that in conventional systems might simply inconvenience a single user can in a server-based system stop the work of dozens or even hundreds of people. For example, resource leaks introduced by changes in a Windows NT Service Pack in the Active Server Page DLL required Microsoft to post a "hot fix" not long after the release of the service pack. The root of the problem was that Microsoft Internet Information Server (IIS) would slowly leak memory, eventually degrading performance. The details are reported in the Microsoft Knowledge Base article Q165335. The interesting point about the article is the claim, "It may take a long time for you to notice these performance problems, depending on how often the Active Server Pages are accessed." This key characteristic ”the resource leak is not apparent for a long time ”makes server-based development different from other types of development.

Microsoft Knowledge Base article Q150934 offers advice on creating a performance monitor log to troubleshoot resource leakage. (We don't cover this topic explicitly in this book.) Using all available tools to discover such resource leaks is required to ensure that a server application will run unattended for long periods of time. Other options for uncovering resource leakage during the development phase include bracketing resource allocations and deallocations with increments and decrements of resource usage variables that allow you to determine whether all resources are freed.

Additional programming methods, such as using C++ constructors and destructors for resource allocation and deallocation, can reduce resource leakage. C++ constructors and destructors still require that allocation and deallocation be coded properly, but properly used classes can ensure that all resources are freed when objects go out of scope. This technique is addressed in the Chapter 8 coverage of the ODBC API. Many Win32 APIs are natural fits for the constructor/destructor model. Some resources are allocated in a constructor, used by the methods of a class, and deallocated in a destructor (called when a stack-based instance of the class goes out of scope or when a heap-based instance is destroyed ). This is not a perfect method and should be augmented by structured exception handling, which is another method that can reduce resource leakage.

Structured exception handling is useful for situations in which an instance of a class is created on the heap using the new operator. If you allocate memory on the heap and an unexpected situation occurs, you might not delete the instance of the class previously allocated. In these cases (and really for any dynamically allocated resource), you can use try-catch and try-finally blocks to ensure that the resources are freed. This method is covered in later examples.

Multitasking Is Essential

Unlike programming for environments such as MS-DOS, server-based development demands multitasking. More than most other applications, server-based applications must be able to perform more than one task at a time, with very rare exceptions. In a traditional client-based application, an application commonly begins performing a task, displays the hourglass, and continues the task until completion. In a server application, refusing to respond to clients while performing a task is rarely acceptable.

We have come a long way since the MS-DOS/Windows 3.x days, when effective multitasking was simply not an option, or at least not a simple option. Many years ago my company developed an application in C++ for MS-DOS that needed to handle many activities at the same time: react to the user at the keyboard, redraw a high-resolution display, and, most important, respond to an outside device, in this case a box that received radio messages. The radio messages needed to be acknowledged within one-tenth of a second. Our first thought was to put a check for data on the serial port in the keyboard routine (polling while waiting for a keystroke) and sprinkle polling calls throughout the screen redraw routine. This was dismissed almost immediately because we could not guarantee that the acknowledgment would be sent in less than one-tenth of a second. Missing an acknowledgment would cause multiple copies of each message to be sent, making the system work harder than it had to.

The solution in the MS-DOS environment was to install an interrupt handler or two. Interrupts are designed to allow a program (called an interrupt service routine, or ISR) to be called asynchronously. They are commonly tied to hardware events; in this case, the event was the arrival of a character on the serial port, called a timer tick. The purpose of the first ISR was to enable us to use interrupt-driven serial communication. In this way, we could be sure that no information would be dropped because subsequent information overwrote it in the communications buffer. This serial communication placed all messages in a globally accessible queue. One problem was solved : messages were no longer missed because they were not received in time from the serial port. The next problem was acknowledging the messages. This might have been possible within the serial communications handler, but we did not want to make that ISR take too much time.

We solved the second problem by installing an additional ISR that occurred 18.2  times a second. During this ISR, we quickly sent an acknowledgment to the radio box, marked the record in the global queue as acknowledged, and returned from the interrupt. Finally, about once a minute (but not very strictly timed), we sent the messages received to a database. This was not done during any ISR since that can be a lengthy process (lengthy by ISR standards ”perhaps a few seconds).

One of the lessons I learned during this process was that the globally accessible queue needed to be protected from multiple competing processes. Eventually, the solution was to move to a double-buffered queue and create a global flag that indicated when the queue was in use. In fact, guarding against data corruption was a bit more complicated than I can describe here, but suffice it to say that this sort of grungy multitasking was not elegant.

Windows 3.x provided a sort of multitasking called cooperative multitasking. While cooperative multitasking was better than nothing, it was not all that much better. Win32 provides support for preemptive multitasking, closer to the interrupt handling of the MS-DOS system mentioned in the previous paragraphs. In addition to preemptive multitasking among multiple applications, a single application can have multiple threads of execution, simply called threads. Win32 multitasking support goes far beyond just supporting threads; it implements synchronization objects that can help threads stay out of one another's way. These API features will be covered more fully in Chapter 2, and examples of multitasking can be found throughout the book.



Inside Server-Based Applications
Inside Server-Based Applications (DV-MPS General)
ISBN: 1572318171
EAN: 2147483647
Year: 1999
Pages: 91

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net