エクスポート (0) 印刷
すべて展開

How to: Use CloudFx to Send and Receive Uni- and Multicast Messages with the Service Bus

This topic describes the simplest method of sending to and receiving both unicast and multicast-style messages through a Service Bus topic in Windows Azure using the Cloud Application Framework and Extensions (CloudFx) library. The sample application uses a Service Bus topic to create several subscriptions that listen for both multicast messages (messages intended for a group of recipients) and also unicast messages (messages intended only for a single recipient).

For a short example that demonstrates sending and receiving a basic message in CloudFx using a Service Bus topic, see How to: Use CloudFx to Send and Receive Messages with a Service Bus Topic and Subscription.

note
This topic assumes that you have Visual Studio 2010 SP1 or later and have already installed the NuGet package manager Visual Studio extension. If you have not done so, download and install the NuGet extension.

note
In addition, graphics at the end of the topic that display the Service Bus topic and subscription structure are screenshots of the Service Bus Explorer tool, which you are free to download and use.

Configure the Project for the .NET 4.0 Target Framework

  1. Open Visual Studio running as an administrator, which is required to use the Service Bus .NET libraries.

  2. Create a new console application.

  3. Right-click the new project in the solution and choose Properties. In the properties tab, confirm that the Target Framework is set to .NET 4.0 and not any other Target Framework, as shown in the following graphic.

    Visual Studio のターゲット変更ダイアログ。
    note
    If you do need to change your target framework, depending on your configuration Visual Studio may need to close the project and then reload it.

  4. In the Solution Explorer, download the NuGet packages and add them into your project by right-clicking the project and choosing Manage NuGet Packages… as shown in the following graphic.

    VS での NuGet パッケージの要求。
  5. In the NuGet search text box, type “CloudFx” and press ENTER. When the CloudFx package appears, click Install, accept the prompts that follow, and then close the dialog when it has finished.

    現在の CloudFX Nuget ビュー。

Add the Code

  1. Add the following using statements to the top of the program file.

    #region Using references
    using System.Reactive;
    using Microsoft.Experience.CloudFx.Framework;
    using Microsoft.Experience.CloudFx.Framework.Configuration;
    using Microsoft.Experience.CloudFx.Framework.Messaging;
    #endregion
    
    
  2. Just after the namespace declaration and just prior to the first class, insert the following code, which declares the InstructionMessage message type that the sample program sends and receives.

    note
    Objects of these types are serializable by default because their property values are intrinsic types. If you use this model to create messages with different and custom types, remember they must be serializable.

    // Simple message used for the example.
    public class InstructionMessage
    {
      public int MessageId { get; set; }
      public string CommandText { get; set; }
    }
    
    
  3. Enter the following empty try/catch/finally code block in the Main method. All sample code is placed inside the try code block.

    try
    {
    
    }
    catch (Exception ex)
    {
      Console.ForegroundColor = ConsoleColor.Red;
      Console.Write(ex.GetDetails());
    }
    finally
    {
      Console.ResetColor();
    }
    Console.Read();
    
    
    
  4. Locate the <ServiceBusConfiguration> element in your project’s application configuration file (app.config). This code example requires your issuer secret and service namespace.

    note
    The following code requires your Service Bus Default Issuer (the default value is owner), Service Bus Default Key, and your service namespace. For information about how to create a service namespace, see Create a Service Namespace. For information about how to obtain your Default Key for a particular namespace, see Obtain the Default Credentials for the Namespace.

    In the <ServiceBusConfiguration> element, put your Service Bus namespace in the defaultNamespace attribute, your Service Bus Default Key in the defaultIssuerSecret attribute.

    Then uncomment the defaultTopic added configuration element, and place CloudFxTopicSample into the topicPath attribute.

    <ServiceBusConfiguration 
      defaultEndpoint="defaultTopic" 
      defaultNamespace="<Service Bus namespace goes here>"
      defaultIssuerName="owner" 
      defaultIssuerSecret="<default key goes here">
    <add   
      name="defaultTopic" 
      endpointType="Topic" 
      topicPath="CloudFxTopicSample"/>
    
    
  5. As the first added code to the try block inside the Main method, add the following code to create a new ServiceBusPublishSubscribeChannel for the endpoint you just configured in the preceding step.

    The following code loads the application configuration file for the sample, and locates the Service Bus configuration data that you added in the preceding step.

    // Retrieve Service Bus endpoint configuration.  CloudApplicationConfiguration 
    // recognizes the execution environment and decides whether to use web/app.config 
    // or ServiceConfiguration.cscfg to retrieve the application configuration.
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine("Retrieving Service Bus configuration...");
    var serviceBusConfig = 
      CloudApplicationConfiguration.Current.GetSection<ServiceBusConfigurationSection>(
        ServiceBusConfigurationSection.SectionName
      );
    
    
  6. Just after the configuration loading call in the preceding step, add the following empty using code block. This code creates the the ServiceBusPublishSubscribeChannel that – because it creates and manages the underlying topic and subscriptions, must be disposed after it has finished its work. You can call Dispose directly, or use the channel in a using code block, as this sample does.

    Console.WriteLine("Creating the Service Bus channel, and topic endpoint...");
    // Create the publish/subscribe channel from the configuration. The pub/sub channel 
    // must be disposed to recycle communication and storage resources. This sample uses 
    // a "using" code block to invoke Dispose on the channel. 
    // In this case the default endpoint is a Service Bus Topic named the value of "topicPath"
    // in the configuration file.
    using (var pubSubChannel =
      new ServiceBusPublishSubscribeChannel(serviceBusConfig.Endpoints.Get(serviceBusConfig.DefaultEndpoint))
    )
    {
    }
    
    
    
  7. Inside the using code block, add the following code to create a subscription for the topic, each one with a filter to list for either multicast messages or messages destined for only that subscription.

    // Create subscriptions for each type of observer. Each one established a subscriber
    // that filters for the "To" property
    CreateSubscriptionForService(pubSubChannel, "Payment");
    CreateSubscriptionForService(pubSubChannel, "Order Management");
    CreateSubscriptionForService(pubSubChannel, "Inventory Management");
    CreateSubscriptionForService(pubSubChannel, "Fraud Detection");
    
    
    Important重要
    Now, of course, your code does not compile because the CreateSubscriptionForService method included in the preceding step does not have an implementation. In Visual Studio, right-click the CreateSubscriptionForService method and choose Generate…. A new CreateSubscriptionForService method is generated for you and your code compiles when you press CTRL+SHFT+B. OR you can create a stub method yourself.

  8. Underneath the subscription creation code from the preceding step in the try block, add the following code to create some sample messages that have as the CommandText property the strings necessary to indicate what kind of message they are.

    // Create sample messages to be sent to participating "services".
    var allServiceMsg = new InstructionMessage { MessageId = 3, CommandText = "New Order Notification" };
    var paymentServiceMsg = new InstructionMessage { MessageId = 1, CommandText = "Reserve Funds" };
    var inventoryService = new InstructionMessage { MessageId = 2, CommandText = "Reserve Inventory" };
    
    
  9. Following the preceding code, add this code block that creates the RoutingMessageContext types necessary to enable the subscription filters to receive a copy of the message that they are designed to receive.

    // Create routing context objects which will tell the publish/subscribe channel where to route messages.
    // "multicast": a copy of each message is sent to all subscribers.
    var allServiceRoutingCtx = new RoutingMessageContext { To = "*" };
    // "unicast": a message is routed only to the "Payment" subscriber.
    var paymentServiceRoutingCtx = new RoutingMessageContext { To = "Payment" };
    // "unicast": a message is routed only to the "Inventory Management" subscriber.
    var inventoryServiceRoutingCtx = new RoutingMessageContext { To = "Inventory Management" };
    
    
  10. In the try block underneath the code added by the preceding step, add the following code. This code calls the Publish method, provides the messages meant to be sent to all subscriptions (the “multicast” message in the first case, and two unicast messages in the second case), and passes the appropriate RoutingMessageContext object to enable CloudFx to instruct Service Bus to route the message to the appropriate listener.

    Console.WriteLine("Sending a multicast message...");
    // Send a multicast message. 
    pubSubChannel.Publish(allServiceMsg, allServiceRoutingCtx);
    
    Console.WriteLine("Sending a unicast message...");
    // Send an unicast message to individual services.
    pubSubChannel.Publish(paymentServiceMsg, paymentServiceRoutingCtx);
    pubSubChannel.Publish(inventoryService, inventoryServiceRoutingCtx);
    
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine("Disposing of all resources....");
    
    
  11. Replace your CreateSubscriptionForService method with the following code. Although the code is commented, it’s important to see that the code:

    • Creates a System.Reactive-based observer object to listen for messages on a topic.

    • Creates a filter for the subscription to listen only for messages at the service endpoint and the service name.

    • Creates a subscription for the Service Bus topic that associates the observer and filter with messages sent to that topic.

    // Creates an observer to subscribe to the topic where the "To" value is either 
    // the specified "serviceName" or the "*" character, meaning that if a message 
    // is sent to "*" then it is a multicast message.
    private static void CreateSubscriptionForService(
    IPublishSubscribeChannel pubSubChannel, 
    string serviceName
    )
    {
    // Create an observer comprised of a custom action which is
    // invoked for every incoming message.
    var messageObserver = Observer.Create<InstructionMessage>(msg =>
    {
      Console.ResetColor();
      Console.WriteLine(
        "{0} service received message ID {1} \"{2}\"", 
        serviceName, 
        msg.MessageId, 
        msg.CommandText);
    });
    
    // Compose a filter which looks at the To property of the incoming message 
    // and compares it against the specified service name (for unicast messages)
    // or a special reserved value "*" which indicates a multicast message.
    var filter = FilterExpressions.GroupOr(
      FilterExpressions.MatchTo(serviceName), 
      FilterExpressions.MatchTo("*")
    );
    
    Console.WriteLine("Subscribing to multicast messages or messages where 'To' == '{0}'", serviceName);
    // Register the message observer with publish/subscribe channel. 
    // This creates all Service Bus resources (subscriptions and receivers) and 
    // start listening to the incoming messages.
    pubSubChannel.Subscribe(serviceName.Replace(" ", "_"), messageObserver, filter);
    }
    
    

Execute the code

  1. The output during the program should look something like the following.

    サンプル アプリケーションの実行。
  2. If you leave the application open, and then use the Service Bus Explorer tool to view the created Service Bus resources, you may see something similar to the following graphic:

    フィルターを使用するスタブの表示。

    If you expand the visual tree to investigate the filters set on the subscriptions, you may see something like the following graphic, which receives messages with the To: value of “Inventory Management” or all messages sent with the To: value of ‘*’.

    フィルターを使用するスタブの表示。

This is the entire code file used to create this sample.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

#region Using references
using System.Reactive;
using Microsoft.Experience.CloudFx.Framework;
using Microsoft.Experience.CloudFx.Framework.Configuration;
using Microsoft.Experience.CloudFx.Framework.Messaging;
#endregion

namespace UniMulticastExample
{
  // Simple message used for the example.
  public class InstructionMessage
  {
    public int MessageId { get; set; }
    public string CommandText { get; set; }
  }

  class Program
  {
    static void Main(string[] args)
    {
      try
      {
        // Retrieve Service Bus endpoint configuration.  CloudApplicationConfiguration 
        // recognizes the execution environment and decides whether to use web/app.config 
        // or ServiceConfiguration.cscfg to retrieve the application configuration.
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Retrieving Service Bus configuration...");
        var serviceBusConfig =
          CloudApplicationConfiguration.Current.GetSection<ServiceBusConfigurationSection>(
            ServiceBusConfigurationSection.SectionName
          );


        Console.WriteLine("Creating the Service Bus channel, and topic endpoint...");
        // Create the publish/subscribe channel from the configuration. The pub/sub channel 
        // must be disposed to recycle communication and storage resources. This sample uses 
        // a "using" code block to invoke Dispose on the channel. 
        // In this case the default endpoint is a Service Bus Topic named the value of "topicPath"
        // in the configuration file.
        using (var pubSubChannel =
          new ServiceBusPublishSubscribeChannel(serviceBusConfig.Endpoints.Get(serviceBusConfig.DefaultEndpoint))
        )
        {
          // Create subscriptions for each type of observer. Each one established a subscriber
          // that filters for the "To" property
          CreateSubscriptionForService(pubSubChannel, "Payment");
          CreateSubscriptionForService(pubSubChannel, "Order Management");
          CreateSubscriptionForService(pubSubChannel, "Inventory Management");
          CreateSubscriptionForService(pubSubChannel, "Fraud Detection");

          // Create sample messages to be sent to participating "services".
          var allServiceMsg = new InstructionMessage { MessageId = 3, CommandText = "New Order Notification" };
          var paymentServiceMsg = new InstructionMessage { MessageId = 1, CommandText = "Reserve Funds" };
          var inventoryService = new InstructionMessage { MessageId = 2, CommandText = "Reserve Inventory" };

          // Create routing context objects which will tell the publish/subscribe channel where to route messages.
          // "multicast": a copy of each message is sent to all subscribers.
          var allServiceRoutingCtx = new RoutingMessageContext { To = "*" };
          // "unicast": a message is routed only to the "Payment" subscriber.
          var paymentServiceRoutingCtx = new RoutingMessageContext { To = "Payment" };
          // "unicast": a message is routed only to the "Inventory Management" subscriber.
          var inventoryServiceRoutingCtx = new RoutingMessageContext { To = "Inventory Management" };

          Console.WriteLine("Sending a multicast message...");
          // Send a multicast message. 
          pubSubChannel.Publish(allServiceMsg, allServiceRoutingCtx);

          Console.WriteLine("Sending a unicast message...");
          // Send an unicast message to individual services.
          pubSubChannel.Publish(paymentServiceMsg, paymentServiceRoutingCtx);
          pubSubChannel.Publish(inventoryService, inventoryServiceRoutingCtx);

          Console.ForegroundColor = ConsoleColor.Red;
          Console.WriteLine("Disposing of all resources....");
        }
      }
      catch (Exception ex)
      {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.Write(ex.GetDetails());
      }
      finally
      {
        Console.ResetColor();
      }
      Console.Read();
    }

    // Creates an observer to subscribe to the topic where the "To" value is either 
    // the specified "serviceName" or the "*" character, meaning that if a message 
    // is sent to "*" then it is a multicast message.
    private static void CreateSubscriptionForService(
    IPublishSubscribeChannel pubSubChannel,
    string serviceName
    )
    {
      // Create an observer comprised of a custom action which is
      // invoked for every incoming message.
      var messageObserver = Observer.Create<InstructionMessage>(msg =>
      {
        Console.ResetColor();
        Console.WriteLine(
          "{0} service received message ID {1} \"{2}\"",
          serviceName,
          msg.MessageId,
          msg.CommandText);
      });

      // Compose a filter which looks at the To property of the incoming message 
      // and compares it against the specified service name (for unicast messages)
      // or a special reserved value "*" which indicates a multicast message.
      var filter = FilterExpressions.GroupOr(
        FilterExpressions.MatchTo(serviceName),
        FilterExpressions.MatchTo("*")
      );

      Console.WriteLine("Subscribing to multicast messages or messages where 'To' == '{0}'", serviceName);
      // Register the message observer with publish/subscribe channel. 
      // This creates all Service Bus resources (subscriptions and receivers) and 
      // start listening to the incoming messages.
      pubSubChannel.Subscribe(serviceName.Replace(" ", "_"), messageObserver, filter);

    }
  }
}



ビルド日:

2013-10-23

コミュニティの追加

表示:
© 2015 Microsoft