Creating a private MSMQ queue in a Microsoft Cluster via a script
We are migrating to Windows 2008 R2 Standard and will be using a Microsoft Clustering (active-passive) configuration. Our application is heavily dependent on MSMQ private queues and our install creates well over 100 private queues using the following C# code.
MessageQueue.Create(".\private$\myqueue", false);
Since the install is not running inside the context of the cluster, the queues are created on the local node and not in the开发者_运维技巧 cluster.
We then tried changing the code to:
MessageQueue.Create("MYCLUSTERNAME\private$\myqueue", false);
However, you can't create private queues on a different server (in this case the cluster server context) and you receive the error "Invalid queue path name".
My two questions are: 1) Is there a way I can run the install in the cluster's context so that when creating a private queue, it would actually be creating the queue in the cluster?
2) If not, what's the best approach on creating queues in the cluster via .NET? I've read some blogs where people create a middle-man Windows service that resides inside the cluster and then their install uses interprocess communication to tell the service which queues to create. That seems like a hack, but is doable if that turns out to be the only approach.
Here is how to do it manually on the clustered instance. (Not via code)
ON THE ACTIVE NODE ONLY, Create the necessary MSMQ Queues.
a. Click Start, right click on Command prompt and click Run as administrator.
b. In the command prompt enter the following commands (Where {virtualname} is the name of the instance.)
i. SET _CLUSTER_NETWORK_HOSTNAME_={virtualname}
ii. SET _CLUSTER_NETWORK_NAME_={virtualname}
iii. Compmgmt.msc
c. Now that computer management has been started from the same command prompt as the variables, it will look like you are making changes locally, but you are actually changing them in the clustered instance.
d. Expand Services and Applications.
e. Expand Message Queuing.
f. Right Click on Private Queues and click New, Private Queue.
g. Verify that the Create in: is the virtual name.
h. In the Queue name: private$\ field put in the queue name and click the OK button.
i. Close Computer Management.
This worked on Windows 2008 R2
Same solution From Powershell (what you aren't using it yet???) I was working on this problem for a while, found this thread recently.
http://winterdom.com/2011/10/using-powershell-with-clustered-msmq
Here's a sample script which I've been using recently that will create the private queues and set permission on it. Creates on remote machines. I work with Win2k3 servers.
Invoke-Command -ScriptBlock {
$env:_CLUSTER_NETWORK_NAME_ = 'myclusterMSMQ'
Write-Host "... load the .NET Messaging assembly"
[Reflection.Assembly]::LoadWithPartialName("System.Messaging")
$environment="perf2"
$groups=@{`
"MessageRouters"="DomainName\Group";`
"CalcDaemons"="DomainName\GroupB";`
"MessageSenders"="DomainName\GroupC";`
}
function new-queue ([string] $queuepath,[bool] $transactional)
{
if (([System.Messaging.MessageQueue]::Exists($queuepath))){throw "$queuepath already exists"}
Write-Host "creating $queuepath"
[System.Messaging.MessageQueue]::Create($queuepath,$transactional)
}
function set-msmqpermission ([string] $queuepath,[string] $account, [string] $accessright)
{
if (!([System.Messaging.MessageQueue]::Exists($queuepath))){
throw "$queuepath could not be found."
}
$q=New-Object System.Messaging.MessageQueue($queuepath)
$q.SetPermissions($account,[System.Messaging.MessageQueueAccessRights]::$accessright,
[System.Messaging.AccessControlEntryType]::Set)
}
#example usage
new-queue ".\private$\$($environment)ack" $false
set-msmqpermission ".\private$\$($environment)ack" $groups.messagerouters "FullControl"
} -ComputerName "servername (or array)"
To solve your problem try setting two environment variables before running the application:
SET _CLUSTER_NETWORK_HOSTNAME_=cluster_name
SET _CLUSTER_NETWORK_NAME_=cluster_name
It worked on Windows Server 2003 R2.
For the sake of the poor souls (like me) who have spent hours scouring how to achieve this using the .NET MessageQueue, it is possible to create queues on a clustered MSMQ without Powershell:
Environment.SetEnvironmentVariable("_CLUSTER_NETWORK_HOSTNAME_", "yourclustername", EnvironmentVariableTarget.User);
Environment.SetEnvironmentVariable("_CLUSTER_NETWORK_NAME_", "yourclustername", EnvironmentVariableTarget.User);
var path = @"yourclustername\Private$\yourprivatequeuepath";
MessageQueue.Create(path, false);
Tested on server 2012.
WARNING: Take care setting environment variables as they can be hard to clear afterwards EVEN if you set them using EnvironmentVariableTarget.User. Also, it appears that it is only necessary to set the environment variables if you're trying to access a private queue in a cluster from a machine within the cluster.
If you've accidentally set the environment variables, you can clear them in the registry at HKCU\Environment. One problem that can occur is if you've run code under a different user context that has set environment variables. In one case, I was able to log in as that user and then remove them from the registry but in another case I was debugging a website under IIS and the LOCALSYSTEM account had them set. To clear them, I published a website that set the values to null. You also want to check what the env variable values are for .User, .Process and .Machine. Note that .Process-scoped changes don't take effect until the machine is restarted if the process in question is LOCALSYSTEM.
精彩评论