Server Administration

Like any server app, game servers require periodic monitoring and maintenance. Servers need to generate log files and require tools to manage their execution life cycle (startup/shutdown). Additionally, game servers might require mechanisms for game watching, kick/ban functionality, and remote management.

Logging

Logging is a very important aspect of any server app, especially for game servers. Every app needs at least an error log and a debugging log. Additionally, you might want chat logs (to see what those users are saying about you), game history logs, connection/access logs, or other game-specific logging. JDK 1.4 includes a new logging API in the java.util.logging package. However, it is new on the scene, and many programmers are reluctant to ditch what has become the de facto standard for logging APIs, Log4J. Log4J began life in 1999 as a project as part of IBM's Alphaworks initiative and thrived there for a couple of years before being taken on as part of the Apache Jakarta Project (). Log4J is highly configurable, easy to use, and efficient. Our examples use Log4J, but admittedly with only a very basic configuration. It is equally important to generate logs from game clients. Usually, you will not want to see the data, but it is invaluable during testing. Even after deployment, if a user is having trouble, you can have that user send in his or her log file to help you diagnose the problem. Depending on your distribution mechanism, you might be constrained in the size of your client app. In this case, the Log4J library might be too large, and you will want to search out a smaller alternative. Whichever API you choose, it is important to log just the right amount of data. Too much will clutter your log files, making them difficult to read and hogging loads of disk space. Too little will leave you guessing when debugging.

Startup/Shutdown

Because the server must be running continuously, you need to accommodate starting and stopping the server automatically at system startup and shutdown. On UNIX-based platforms (Linux, Solaris, and so on) this is accomplished using a startup script. contains an example of an init.d script for Debian GNU/Linux, but it should work with a bit of modification on other Linux distributions and UNIX systems.

Listing 6.13 init.d Script

#! /bin/sh PATH=/usr/local/gameserver/bin:/usr/local/java/bin:/usr/local/sbin:
/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/local/gameserver/bin/server.sh NAME=gameserver DESC=" Multi-player GameServer"
test -x $DAEMON || exit 0
set -e case "$1" in
 start)
 echo -n "Starting $DESC: $NAME"
 start-stop-daemon --start --quiet --exec $DAEMON
 echo "."
 ;;
 stop)
 echo -n "Stopping $DESC: $NAME "
 start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid
 rm /var/run/$NAME.pid
 echo "."
 ;;
 *)
 N=/etc/init.d/$NAME
 echo "Usage: $N {start|stop}" >&2
 exit 1
 ;;
esac exit 0

The script is based on the init.d skeleton, found in /etc/init.d/skeleton on Debian systems. In addition to the init script, you need a way to drop the process ID (pid) into the /var/run/gameserver.pid file every time the server is started. This can be accomplished with a bit of Perl that parses the pid from the output of the ps command. For Windows systems, the same result is achieved by making the server app into an NT service. A number of tools can be used for adapting a Java app into a service. One is at , but a quick Google search for Java Windows service will turn up many other options.

Java Shutdown Hooks

As of JDK 1.3, Java has had the capability to add what is called a shutdown hook. A shutdown hook enables you to register a Runnable object to be activated when the VM is terminated. This allows for a clean shutdown of the server app; it can save game state, gracefully disconnect users, close database connections or other open resources, and finally exit. The paper "Revelations on Java Signal Handling and Termination" (IBM DeveloperWorks, , January 2002) is an excellent resource in which author Chris White discusses shutdown hooks and signal handling in general.

Server Admin Consoles

An additional tool for monitoring and debugging your game server is an administration console. Administrative consoles can be either local or remote. A local console is implemented like RPSConsoleEventReader, reading commands from STDIN and turning that input into events. A remote console is a modified GameClient, similar to RPSClient, with either a command line or graphical UI. In either case, the admin console sends GameEvents to GameControllers like any other client. The difference is that you first require users to be authenticated against the list of administrators and possibly remote IP addresses. The admin client might speak to the normal GameController or to a special AdminController that divides that functionality into a separate class. An AdminController could provide a number of features to administrators, such as server performance monitoring, game watching, log viewing, and remote shutdown/restart. For additional security, you might want to listen on another port for administrative access and then set up appropriate firewall rules to limit access to that port. The GameServer can then be configured with an additional ServerSocketChannel on that port and have it bound to the main selector.

Game Watching

Game watching and monitoring is the act of spying on a game while it is in progress. This can be invaluable for troubleshooting and analyzing player behavior. Implementing this feature involves a slightly modified GameClient that takes actions for both players from the server and takes no game input from the user. Also, the GameController needs to be enhanced to allow admin clients to attach to a game and start receiving all events for that game. A small change to the sendEvent() and sendBroadcastEvent() methods could first check for the existence of an attached spy and send extra copies of all events for that game to the spy.