Custom Resolver FAQ: Registration Lifetimes and Refresh
As PeerChannel and the .NET Framework continue to gain traction and popularity, we are starting to receive a number of questions about how to use various parts of this exciting technology. Some of our most common questions center around the use of the Custom Resolver Service. Note that a discussion of whether or not to implement a Custom Resolver will be in a upcoming blog entry - we will assume for now that your particular scenario requires the use of a Custom Resolver (for example, if your application runs on Windows Server 2003).
Here are the two main questions I will be answering in this entry:
1) What are Registration Lifetimes? What are they used for?
2) What is the purpose of the Refresh operation? When do I call it?
So let's start with the basics and tackle these questions. A reminder that when we refer to a node, we are talking about a single application endpoint and a mesh refers to a connected groups of nodes.
Registration Record: Each node in the mesh publishes their endpoint information to the resolver service through the Register operation. The resolver service stores this information as a registration record. This registration record contains a unique identifier (RegistrationID), endpoint information (PeerNodeAddress), and expiration time (DateTime).
Why An Expiration Time? Ideally, when each node leaves the mesh, it will call the Unregister operation, which will cause the resolver service to remove the registration entry. However, it may not be unusal for a node to shut down or become inaccessible before calling Unregister. (For example, the node may be connectly wirelessly and go out of range). In this case, the resolver service needs some way of being able to purge stale and invalid registration records. Having an expiration time for each registration record allows the resolver service to indentify these stale records and remove them to keep the registration records clean.
Why Do I Care About Stale Records? There are two reasons why having stale registration records at your resolver service is a bad idea. First, stale records may result in unnessary failed connections. If a node trying to connect to a mesh receives stale connection information from the resolver service, it will take longer, sometimes MUCH longer to connect to the mesh. But it doesn't end there. The second reason why stale records are bad is that they take up memory. Since registrationIDs are typically generated every time a node is created or recreated, it is possible for a node entering and leaving the mesh multiple times to leave several stale registration records. Without an efficient process to remove registrations records, it is inevitable that eventually that the size of the cache used to store registration data will overflow and crash your resolver service. So removing these records is important.
When Do I Remove Stale Records? The default implementation of CustomResolverService class has the CleanupInterval property. This property (a TimeSpan object) tells the resolver service to go through and delete stale records every time CleanupInterval passes. This should be set to a time equal or greater than the RefreshInterval set on the service (more on that later). If you are using the default implementation of the custom resolver service, all you need to do is set this property and you're good to go. Otherwise, if you are implementing your own resolver service, you have a couple choices:
1) Periodic maintenance: Do what we did! Set a timer to go off every so often and go through your data store to delete old records.
2) Passive Deletion: Instead of actively hunting for stale records at intervals, you may want to delete records when your service is already performing another function. This may potentially slow down response time to requests from the resolver clients, but it has the benefits of doing away with a timer and may be more efficient if you don't expect many nodes to leave ungracefully.
How Do I Make Sure Good Records Don't Get Deleted? This is the purpose of the Refresh operation. Nodes publishing information at the resolver service need to call Refresh periodically to ensure that the expiration time on their records is extended. When the resolver service receives a Refresh request, it should look up the record and extend the expiration time. As long as the expiration time stays in the future, the resolver service will not delete the record.
How Do I Know When To Call Refresh? The RegisterResponseInfo and RefreshResponseInfo objects are sent back to the node in response to a Refresh and Register operations, as well as Update (the response to a Update is the same as the response to a Register). These objects contain a TimeSpan property called RegistrationLifetime, which indicates to the node how much time it has before it needs to call Refresh. So if the resolver service responds to a node's Register request with a RegistrationLifetime of 2 minutes, that node needs to call Refresh in under 2 minutes to ensure that the record stays fresh. Of course, the node should keep in mind that there may be a small amount of latency between the node and the resolver service, so it may be a good idea to send a Refresh a tad under the time given by the RegistrationLifetime. Naturally, the resolver service is not forced to delete a registration record the instant it goes stale (this would not scale well), but it must guarantee that registration records are held for the time given by RegistrationLifetime.
Summary:
- Registration records shouldn't last forever - let the default implementation delete them for you, or write your own maintenance function
- To identify stale records, the default implementation marks each record with an expiration time. Custom implementation should do something similar
- In order to avoid having a registration record deleted, a node must call Refresh before the registration record's expiration time.
- The RegistrationLifetime value, sent by the resolver service, tells a node how much time it has to call Refresh before the registration record expires.
And there you have it! Please comment below or contact us if you have any questions about this or any other Custom Resolver Service feature. -Jonathan
Comments
- Anonymous
March 21, 2011
"Custom implementation should do something similar" How can I do that in the custom implementation?