Strategies
This section describes some issues to consider when you implement the Resource Pool pattern.
Resource Keys
A resource key identifies resource characteristics. Clients specify resource keys to indicate certain criteria when they request resources from a pool. A resource pool uses keys to discern whether any of its pooled resources match requests.
In a typical implementation, every pooled resource is identified by a resource key. The type and structure of the resource key does not matter as long as it follows these semantics:
Two resources that can be used in the same context must have equivalent resource keys. The more your resource key semantics follow this rule, the greater degree of resource recycling you will achieve. Two resources that cannot be used in the same context must have distinct resource keys. Without this rule, applications may use resources initialized for other users or data sources. This condition can cause security problems or other undefined results.
Normally, a resource key encapsulates all the initialization parameters passed to the physical resource manager or programming interface. In the case of a database connection, these usually include the data source location, user, password, and connection properties.
Resource Pool Properties
You can define configuration properties that affect how a resource pool initializes new resources and to enforce thresholds. Here are some examples of resource pool properties:
Initial size—
The initial number of resources in the pool. Priming the resource pool reduces the delay caused when an application responds to its first end-user requests. For example, a servlet can prime its connection pool during its initialization so that there is no delay when the first client request arrives.
Growth increment—
The number of resources to initialize when the pool is depleted. You can choose to allocate multiple additional resources when the pool runs out rather than allocating one resource at a time. Increasing this number results in longer delays when the pool is empty, but these delays happen less frequently. Different applications prefer different behavior.
Maximum resources—
The maximum number of resources a pool can manage. Placing a threshold on the number of resources in a pool minimizes the effect of resource leaks or too many concurrent users. Resource leaks occur when clients neglect to return resources to the pool when they finish using them. Controlling this threshold at the resource pool level results in better diagnostics when this condition occurs. These conditions may cause memory leaks or system crashes if the pool does not enforce this threshold. If no resources are available and this threshold has been reached, the resource pool can let clients wait until resources are available or reject requests for new resources outright until old resources are returned to the pool.
A resource pool implementation can encapsulate each of these properties completely. You can also provide an associated administrative facility such as a configuration file or graphical console to allow administrators to tailor these settings based on what works best in their particular environments.
Closing Resources
Be aware of resources whose close operations affect other dependent resources. For example, the JDBC specification states that closing a connection implicitly closes any related statement handle as well. Likewise, closing a statement handle implicitly closes its open result set, if any.
When you override resource close operations that carry stipulations like these, you can consider whether to break the contract that the specification dictates. If you choose to implement the specification precisely, ensure that your close operations release dependent resources as clients expect. If you choose to ignore this aspect of the specification, then pooled resources might leave dependent resources open and simply return themselves to the pool when they are closed. Applications that depend on the specification behavior may potentially leak dependent resources if they do not get closed implicitly. This sounds like a significant side-effect, but it does simplify a pooled resource's implementation. You can also argue that clients should explicitly close all resources despite what the specification allows.
Resource Pool Cleaning
You can incorporate an automated cleaning mechanism that reduces the number of resources a pool manages when its utilization decreases. For example, a resource pool is likely to create a significant number of new resources to account for the additional load that the high number of users during the workday causes. However, during the night, the load drastically decreases and most of the pool's resources sit idle but still consume client and server storage.
One strategy to alleviate this condition is to incorporate an automated cleaning routine that runs periodically, perhaps in a low-priority background thread, and closes a fraction of a pool's inactive resources. Resource Timer (137) describes a mechanism for monitoring and reacting to resource inactivity that you can employ to solve this problem.
Another cleaning issue is dealing with client code that neglects to return resources to the pool. This usually happens due to a defect in the client's own code that causes essential cleaning operations to be skipped. You can use the Resource Timer pattern to alleviate this problem as well, this time to automatically close resources after a period of inactivity.
|