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

  • 相关阅读:
    Ubuntu安装tomcat
    mongodb配置数据库文件夹,创建服务
    chrome 49 版本bug: flex父元素设置flex:1 , 子元素用height:100%无法充满父元素
    angularjs指令中的require赋值含义
    flex布局在垂直居中里,元素超过容器大小后,不能通过滚动条滚动到顶端,这是个flex的bug
    redux中的compose源码分析
    js中的reduce()函数
    redux-thunk中间件源码
    HTML, CSS. JS的各种奇淫技巧
    JS在项目中用到的AOP, 以及函数节流, 防抖, 事件总线
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/2931918.html
Copyright © 2011-2022 走看看