none
MSMQ and WCF (client and service on different machines)

    Question

  • Hi.

     

    We are in the process of designing portion of the new system and we are discussing solutions for the following problem (.NET 3.0, Windows Server 2003 on both machines):

     

    - WCF Service runs on machine 1 (WCF service hosted by a Windows Service)

    - client runs on machine 2

    - for the communication between client and service we use MSMQ binding

     

    Based on the documentation, MSMQ Queue has to be on the same machine where WCF service is running (machine 1).

     

    So, what happens when machine 1 (one that runs the service and the queue) is down?

     

    Is it possible to configure MSMQ infrastructure so that messages would be queued on machine 2 (where the user is pumping the messages) so that once the machine 1 is up and running, those messages would be “pushed” to queue on machine 1, where WCF would continue processing them?

     

    Thanks for any your help in advance.

     

    P.

     

    Wednesday, November 07, 2007 1:25 PM

All replies

  • What you're asking for is built in. Each client has a local queue that it writes to in the event the remote queue is down. When the service comes back online, MSMQ takes care of forwarding the messages to the remote queue.
     
    Wednesday, November 07, 2007 1:33 PM
  • Thanks a lot.

    Wednesday, November 07, 2007 6:47 PM
  • Hi Will.

     

    So, MSMQ needs to be installed on client's machine (one sending a message)? If yes, is there any special configuration required for this to be anabled.

     

    Thanks,

     

    P.

    Wednesday, November 07, 2007 6:49 PM
  • Yes, MSMQ needs to be on the client. The queue you create for the service to listen to and the client to send messages to needs to cannot be a private queue (since private queues are only accessible on that specific machine). So, make sure its a public queue.

     

    With a public queue make sure permissions are set up correctly (use domain accounts, not machine accounts).

    Wednesday, November 07, 2007 6:57 PM
  • Hi Jarrod.

     

    Again, thanks for your help. It would be great If you would be so kind to provide some additional steps in order to make, what you are talking about, work. We are extremely pressed with the deadlines and I just have hard time finding time to dig through the documentation to understand what would I have to do here.

     

    This is my setup:

     

    - Sender Machine

                - should call WCF service on “receiver” machine using MSMQ

     

    - Receiver Machine

                - hosts a WCF service (binding through the public queue on receiver machine)

     

    - Sender and Receiver Machine

                - are part of the same domain

                - have Windows 2003

                - have Message Queuing 3.0 installed

                - have .NET 3.0 installed

     

    So, can you please outline the steps that one should go about configuring MSMQ (on both machines) and configuring endpoints on a WCF service user and on a WCF service so that the following scenario would work:

     

                - if receiver machine is of line, the sender machine would be able to continue sending messages that would be picked up by a service once the receiver machine is up and running.

     

    Again, and as always, thanks in advance for you help.

     

    P.

     

    Thursday, November 08, 2007 2:03 PM
  • Sure, but it will take me about 8 more hours to get you something. I don't have access to a public queue right now to give you something workable and be able to unit test it myself.

    Are you using the service configuration editor? It makes configurations like this much easier. Your config file will look something like this once you have created your queue and know the service machine's name. You will be using a public queue tied into active directory - per the WCF docs: 
    When MSMQ is installed with Active Directory integration, the machine must be part of a Windows Domain. The Active Directory is used to publish queues for discovery. Such queues are called public queues. When addressing a queue, the queue can be resolved using Active Directory. This is similar to how DNS is used to resolve the IP address of a network name. The UseActiveDirectory property in NetMsmqBinding is a Boolean indicating whether the queued channel must use Active Directory to resolve the queue URI. By default it is set to false. If the UseActiveDirectory property is set to true, then queued channel uses Active Directory to convert the net.msmq:// URI to format name.

    The security is set to none in the example, below - you'll need to rework that I believe. Like I said, trying to display some of this from memory and can't get a working one running due to limitations of where I am at the moment. 


    Oh, you don't have to do anything to make the client hold onto the messages and resend on a connectivity issue...from the MSMQ FAQ at http://www.microsoft.com/windowsserver2003/techinfo/overview/msmqfaq.mspx



    Where does Message Queuing store messages?


    A.

    Message Queuing stores messages in multiple 4 megabyte (MB) files in the MSMQ\Storage folder. In MSMQ 3.0, you can specify the location of this folder from within the MSMQ plug-in to the Microsoft Management Console (MMC). Messages destined for remote computers are kept in the same files that are used to store local messages. The Message Queuing service dynamically manages the storage for local as well as outgoing messages, while transmission to other computers is pending.




    <system.serviceModel>

      <client>

        <endpoint address="net.msmq://hostmachinename/queuename"

          binding="netMsmqBinding" bindingConfiguration="MQBinding"

          contract="IMyContract"

          name="MyService"/>

      </client>

      <bindings>

        <netMsmqBinding>

          <binding name="MQBinding" useActiveDirectory="true">

            <security mode="None">

              <transport msmqAuthenticationMode="None" />

              <message clientCredentialType="None" />

            </security>

          </binding>

        </netMsmqBinding>

      </bindings>

      <services>

        <service behaviorConfiguration="Mex" name="MyService">

          <endpoint address="net.msmq://hostmachinename/queuename" binding="netMsmqBinding" bindingConfiguration="MQBinding" name="NetMsmqMessageEndPoint" contract="IMyContract"/>

          <host>

            <baseAddresses>

              <add baseAddress="net.msmq://hostmachinename/queuename"/>

            </baseAddresses>

          </host>

        </service>

      </services>

    </system.serviceModel>


    Thursday, November 08, 2007 3:18 PM
  • Hi Jarrod.

     

    Before anything, thanks for you reply. Yes, I am using WCF configuration and I understand what you are suggesting in regards to required configuration; the sender application can leave in the binding the address of the receiver machine and the MSMQ would take care of it, correct?

     

    My problem is related to required MSMQ configuration on the sender and on the received machines. If you could, when you get the chance, provide some instructions about the steps that would be required to configure them on both machines, so that the original scenario that I have posted would work, that would be very very appreciated.

     

    Thanks,

     

    P.

     

     

    Thursday, November 08, 2007 7:15 PM
  • Yes, the sending machine's config points to the queue on the receiving machine. MSMQ will resolve the queue via Active Directory and the message will be sent to the receiving machine.

    There isn't much to it, it just took me about 10 minutes to set this up.
    Receiving machine....
    1) Created a public queue in the MMC MSMQ Snap-In.
    2) Configured my service to point to the correct queue "net.msmq://localhost/WCFQueue" (notice, no /private/"
    3) I added a netMsmqBinding, changed "Use Active Directory" to true. Left security with the defaults.
    4) Started up my service that was hosted in a console app.

    Now, how is your service hosted? Is it running in a Windows Service? Self hosted .NET app? IIS?
    If its a Windows Service, make sure the service is running under an account that has access to send/receive/peek, etc on the queue you created.

    On the client machine, make sure your client (or users who are using the client app) have access to the queue on the receiving machine.

    I didn't even configure MSMQ on the client machine (sender)(it has to be installed but you don't have to create the queue).
    I just specified the computers name  "net.msmq://AMENHOTEP/WCFQueue".



    Friday, November 09, 2007 3:27 AM
  • Thanks Jarrod.

     

    Windows Service is hosting the WCF service and I will make sure to follow the steps you outlined. I guess it will be a busy weekend ...

     

    P.

    Friday, November 09, 2007 12:54 PM
  •  

    Jarrod: great content! We have been fighting with using MSMQ with WCF as it seemed a natural for a logging service I was writting. This service will be hosted on a Windows 2K3 server and clients are all across the enerprise

    so we really like the idea of MSMQ but what a pain  to work with!.

     

    It seems that a private queue can only be used if the service is on the same machine so we MUST use a public queue so

    as such I defined a piblic queue on severXXX called MYQueue and gave "everyone" Full Control as I am just trying to make this work. My config file for my Console (taking baby steps) host looks like: (actually the code I used is a sample from Michele Bustamante's excellent book)

     

    <services>

    <service name="Messaging.MessagingService" behaviorConfiguration="serviceBehavior">

    <host>

    <baseAddresses>

    <add baseAddress="http://localhost:8000/MessagingService"/>

    </baseAddresses>

    </host>

    <endpoint address="net.msmq://localhost/MyQueue" contract="Messaging.IMessagingService" binding="netMsmqBinding" bindingConfiguration="netMsmq"/>

    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />

    </service>

    </services>

    <behaviors>

    <serviceBehaviors>

    <behavior name="serviceBehavior">

    <serviceMetadata httpGetEnabled="true"/>

    </behavior>

    </serviceBehaviors>

    </behaviors>

    <bindings>

    <netMsmqBinding>

    <binding name="netMsmq" exactlyOnce="false" useActiveDirectory="True">

    <security mode="None" />

    </binding>

    </netMsmqBinding>

    </bindings>

    </system.serviceModel>

     

    So I believe that I have all the right stuff and my test contract and service code is simple:

     

    public interface IMessagingService

    {

    [OperationContract(IsOneWay=true)]

    void SendMessage(string message);

    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

    public class MessagingService : IMessagingService

    {

    #region IMessagingService Members

    public void SendMessage(string message)

    {

    Console.WriteLine(String.Format("Received message: '{0}'", message));

    }

     

    I start the console app and then configure my test client to access it:

     

    <system.serviceModel>

    <bindings>

    <netMsmqBinding>

    <binding name="netMsmq" >

    <security mode="None" />

    </binding>

    </netMsmqBinding>

    </bindings>

    <client>

    <endpoint address="net.msmq://devweb01/MyQueue"

    binding="netMsmqBinding" bindingConfiguration="netMsmq"

    contract="WinClient.localhost.IMessagingService" name="netMsmq" />

    </client>

    </system.serviceModel>

     

    my code looks like:

    using (localhost.MessagingServiceClient proxy = new WinClient.localhost.MessagingServiceClient())

    {

    proxy.SendMessage(string.Format("Message {0} from client", m_counter++));

    }

     

    when I run the client, the call to the service seems to work as there are no exceptions but I the server method is never called. The really strange part is that there NOTHING in any of the client or server queues.

     

    The other troublin thing is that I can host the service on a Windows XP machine using a private queue and things work fine.

     

    Hope there are answers to these little issues as we would love to use MSMQ.

    Friday, February 22, 2008 4:34 PM
  • actually you can send a message to a remote private queue using WCF, the url should look like this: net.msmq://{machine-name}/private/{queue-name} (without the $ after the private word)

    AD only acts as a kind DNS resolver with public queue, so if you want to access remote private queues with System.Messaging or from unmanaged code all you got to do is use the queue full name, which looks kinda like this
    FormatName:DIRECT=OS:{machine-name}\Private$\{queue-name}



    Wednesday, January 21, 2009 1:29 PM
  •   Try to use public queue on machine 1  (you should install MSMQ with AD support), so when machine 1 is down, queue will be available
    • Proposed as answer by GSerjo Thursday, January 22, 2009 1:57 PM
    Wednesday, January 21, 2009 5:45 PM