zoukankan      html  css  js  c++  java
  • 在WCF中使用消息队列

    在一些大型的解决方案中,假设我们的服务没有办法一直在线,或者因为这样那样的原因宕机了,有没有什么办法让客户端的影响最小化呢?答案是可以通过消息队列的方式,哪怕服务是没有在线的,客户端依然可以继续操作。

    1. 首先来学习一些消息队列的基础知识

    消息队列默认是没有安装的,可以通过下面的方式进行安装

    image

    2. 通过一个小程序来演示一下如何发送和接受消息

    image

            static void SendMessage() {
                Message msg = new Message("这是我的一个消息");
    
                string queueName = @".\Private$\SampleQueue";
                MessageQueue mq = null;
    
                if (!MessageQueue.Exists(queueName))
                    mq = MessageQueue.Create(queueName);
                else
                    mq = new MessageQueue(queueName);
    
                mq.Formatter = new XmlMessageFormatter(new[] { "System.String" });
    
                mq.Send(msg, "测试消息");
    
                Console.WriteLine("消息发送成功");
            }

    然后,我们就可以看到这个消息了(通过mmc控制台)

    [注意]xp和vista或者win 7都属于桌面操作系统,它们只支持私有队列。如果是服务器操作系统的话,则还支持公共队列。

    image

    image image

    image image

    下面看看如何读取队列中的消息

     static void ReadMessage() {
                string queueName = @".\Private$\SampleQueue";
                MessageQueue mq = new MessageQueue(queueName);
                mq.Formatter = new XmlMessageFormatter(new[] { "System.String" });
                Message msg = mq.Receive();
                Console.WriteLine(msg.Label);
                Console.WriteLine(msg.Body.ToString());
                
            }

    image

    上面是一个很简单的例子,演示了如何发送和接收消息。

    下面用一个例子来讲解WCF中如何利用消息队列来实现异步的服务。

    1. 创建契约

    using System;
    using System.ServiceModel;
    using System.Runtime.Serialization;
    
    namespace Contracts
    {
        [ServiceContract]
        public interface IMSMQService
        {
            [OperationContract(IsOneWay = true)]
            void PlaceOrder(OrderEntry entry);
        }
    
        [DataContract]
        public class OrderEntry {
            [DataMember]
            public int OrderID { get; set; }
            [DataMember]
            public DateTime OrderDate { get; set; }
            [DataMember]
            public int Quantity { get; set; }
            [DataMember]        
            public int UnitPrice { get; set; }
    
            public override string ToString()
            {
                return string.Format(
                    "ID:{0}\tDate:{1}\tQuantity:{2}\tUnitPrice:{3}\t",
                    OrderID,
                    OrderDate,
                    Quantity,
                    UnitPrice);
            }
        }
    
        
    }
    

    2. 实现服务

    using System;
    
    namespace Services
    {
        public class MSMQOrderService:Contracts.IMSMQService
        {
            #region IMSMQService 成员
    
            public void PlaceOrder(Contracts.OrderEntry entry)
            {
                Console.WriteLine("收到订单:{0}", entry);
            }
    
            #endregion
        }
    }
    

    3. 创建宿主

    using System;
    using System.ServiceModel;
    
    
    namespace Host
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (ServiceHost host =
                    new ServiceHost(
                        typeof(Services.MSMQOrderService),
                        new Uri("net.msmq://localhost/Private/SampleQueue")
                        ))
                {
    
                    NetMsmqBinding binding = new NetMsmqBinding(NetMsmqSecurityMode.None);
                    binding.ExactlyOnce = false;
                    binding.Durable = true;
    
                    host.AddServiceEndpoint(
                        typeof(Contracts.IMSMQService).FullName,
                        binding,
                        "");
    
                    host.Open();
                    Console.WriteLine("服务器已经准备好");
                    Console.Read();
    
                }
    
            }
        }
    }
    

    4. 创建客户端

    using System;
    using System.ServiceModel;
    
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                NetMsmqBinding binding = new NetMsmqBinding(NetMsmqSecurityMode.None);
                binding.ExactlyOnce = false;
                binding.Durable = true;
    
    
                ChannelFactory<Contracts.IMSMQService> channel =
                    new ChannelFactory<Contracts.IMSMQService>(
                        binding, new EndpointAddress("net.msmq://localhost/Private/SampleQueue"));
    
                Contracts.IMSMQService client =
                    channel.CreateChannel();
    
                client.PlaceOrder(
                    new Contracts.OrderEntry()
                    {
                        OrderID = 1,
                        OrderDate = DateTime.Now,
                        UnitPrice = 10,
                        Quantity = 10
                    });
    
                Console.WriteLine("发送了一个订单");
                Console.Read();
    
            }
        }
    }
    

    5. 测试

    image

    image

    很好,我们看到消息发送到了服务器端。但,如果仅仅是这样,那么使用消息队列有什么优势呢?

    我们现在不启动服务端,而仅仅启动客户端。看看是否可以发出订单

    image

    我们发现,虽然服务没有开启来,但是却依然可以发出订单。那么这个订单到哪里去了呢。原来是被存放到了队列中。如下图所示

    image

    image

    然后,我们再去开服务宿主程序。

    image

    宿主程序会自动读取消息队列中的消息,并自动进行处理。此时再次去查看队列的话,就会发现已经没有消息了

    image

  • 相关阅读:
    48. Rotate Image
    47. Permutations II
    46. Permutations
    45. Jump Game II
    44. Wildcard Matching
    43. Multiply Strings
    42. Trapping Rain Water
    41. First Missing Positive
    40. Combination Sum II
    39. Combination Sum
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1629990.html
Copyright © 2011-2022 走看看