• 在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

  • 相关阅读:
    HDU5470 Typewriter SAM 动态规划 单调队列
    BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树
    Codeforces 235C Cyclical Quest 字符串 SAM KMP
    HDU4622 Reincarnation 字符串 SAM
    Codeforces 452E Three strings 字符串 SAM
    BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 字符串 SAM
    2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他
    2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs
    2018牛客网暑假ACM多校训练赛(第三场)D Encrypted String Matching 多项式 FFT
    UOJ#310 【UNR #2】黎明前的巧克力 FWT 多项式
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1629990.html
Copyright © 2020-2023  润新知