As an administrator of an enterprise installation of Symantec Client Management Suite and Server Management Suite, often I want to spread load over time. Having 10,000 machines check in with a full software inventory at the same time is not exactly good for the performance of either my Notification Servers or our WAN!
In that particular situation (Software Inventory) in NS v6, Altiris provided us with a tool to spread the load randomly: The AeXRunControl, and it worked really well. It spread the load out over the week or the month as you set it up. There were only three issues that I had with AeXRunControl: 1) They syntax was cryptic, 2) The uninitiated saw that "Software Inventory" was running every day (even though you were simply running the RunControl and it only actually ran once a month), and 3) I had no easy way of determining which day a particular PC would report in.
This led me to seek a method that solved these issues. It needed to be: 1) Simple to understand, 2) Not falsely run null tasks, and 3) Be deterministic as to which day a particular PC ran.
I came up with two solutions, one very simple, but restrictive as to the increments I could randomize to, and one more complex and more flexible. Both will be discussed herein.
Keep it Simple-Skip the Math
One attribute that I immediately seized upon to randomize computers was the GUID. The Globally Unique Identifier is generated, at random, by the system. By design, the GUID is random. By it's nature, and the number of possible GUIDs available, it virtually guarantees lack of duplication of GUIDs, but to achieve this, a fairly sophisticated algorithm is used by SQL server to generate new GUIDs, and to ensure that those generated are incredibly random.
So, great, we've got an attribute that's random...how do we use it to spread load out...
First, create a filter (works with collections in V6 too). You need to create a "Raw SQL" filter (make sure you have Platform SP3 in place before doing this, as there's a bug in pre-SP3 that makes these painfully slow to work with):
select
[_ResourceGuid] AS [Guid]
from
[Inv_AeX_AC_Identification]
where cast([_ResourceGuid] as nvarchar(50)) like '0%'
This SQL will return all of your computers that have GUIDs starting with a zero. Repeat this process for 1-9 and A-F, and voila. You have filters that will break down all of your computers into 16 fairly even chunks. Want to run half your computers on Tuesdays and half on Thursdays: Apply 0-7 to Tuesday, and 8-F on Thursday. Simple and effective. If you're like me and have multiple sites, the sites will be load-shared too, so if you have 2,000 computers in a site, only 1,000 of them will be run on Tuesday and 1,000 on Thursdays (more or less...there will be variations, but only a few percent).
So...how does this stack up to the criteria I laid out before:
1) Simple to understand: The SQL here is pretty clean and easy to understand. If you simply understand what a GUID is, you can figure it out
2) Not falsely run tasks: I can set things like SW audit to simply run on the day I want it (or ASAP thereafter), and not have to run a check task every day
3) Deterministic: By simply looking at the filters, or in the Resource Manger looking at the "Filter Summary", I can see which one a PC's in, and it doesn't change
The only issue here is that I have a fixed number of breakdowns: 16...how do you fix that: Now you need to do some math...sorry.
Do the Math
Alright, so we had something simple, and we got 16 breakdowns with very little effort. 80% of the time, that's just fine...but what about that other 20% of the time when you really want to spread out load. For example, if you want to break your computers down so that 5% of them run on the 1st-4th Monday-Friday? Enter the humble "modulo" operator, one of the least used arithmetic operators!
The modulo operator (%) is simple. It divides one integer by another, and returns the remainder. So if I do a "Select 125 % 3", it will return a 2 (125/3 = 41 remainder 2). This is the key to getting nice breakdowns to a specified number of gradiations:
DECLARE @NumberOfCategories INT
DECLARE @CurrentCategory INT
SET @NumberOfCategories = 20
SET @CurrentCategory = 0
SELECT
_resourceguid AS guid
,mod = ABS(CAST(_resourceguid AS varbinary) % @NumberOfCategories)
FROM
dbo.Inv_AeX_AC_Identification
WHERE
ABS(CAST(_resourceguid AS varbinary) % @NumberOfCategories) = @CurrentCategory
At the top of this SQL, set your @NumberOfCategories to be the number you want to break down, then the @CurrentCategory to be each of the possible (in this case 0,1,2...19). Now you will get, in this case, 1/20 of all your PCs, similarly broken down completely randomly, including breakdowns within sites etc.
So...how again does this stack up to the criteria I laid out before:
1) Simple to understand: The SQL here is a bit more complex. You need to understand both GUIDs and the modulo operator to really get this one. Maybe put some comments in.
2) Not falsely run tasks: I can set things like SW audit to simply run on the day I want it (or ASAP thereafter), and not have to run a check task every day
3) Deterministic: By simply looking at the filters, or in the Resource Manger looking at the "Filter Summary", I can see which one a PC's in, and it doesn't change
Conclusion
So, I've provided two pretty simple ways to break down your PCs randomly, allowing you to spread load for intensive processes, while at the same time being able to accurately predict when particular PCs are going to report in with results. Try it out, I'll bet you'll find more and more reasons to use this functionality in the future.