• WCF订阅替换轮训


    使用WCF订阅替换轮训

    之前因为某些特定岗位的人不知道是不方便还是什么的原因,所以随便做了个独立于所有系统之外的邮件审批服务,功能是那些人在邮件里给待审批单据发个“同意”就自动审批通过,大致分为3部分:第一部分每隔固定时间去邮件服务器抓一批邮件下来;第二部分分析邮件格式,如果符合就提取必须的邮件内容;第三部分提交审批流驱动进行审批。

      我一直想做个移动端APP然后废掉它算了,不过似乎领导觉得这个东西还能撑下去,总之就一时半会是不可能干掉了。

      所以,游戏之做还是得优化一下,这里就说说第一部分:

      每隔固定时间抓取然后执行存在的问题,比如说现在是每隔十分钟抓一次,处理不怎么及时,而且即使没有新邮件也会去抓一次,另外还有一个隐藏的问题,就是为什么设置10分钟,主要是邮件服务器那边还有其他的处理,需要一个回执,但是这是个单线程的服务(因为用的人很少)所以担心设置的时间短了这一批抓取的还没处理完,这里有一些无关的事都耦合上了。

      解决办法:不再去抓邮件,而是如果邮件审批服务空闲了,就去邮件服务器上注册一下,如果有了新邮件,就由邮件服务器发布任务,这样以后用的人多了还可以做分布式处理(当然,我还是倾向于不用这种方式了,因为各种客户端发出来的邮件千奇百怪,解析难保正确)。

      这里就使用WCF的订阅发布来做了,其实我觉得在没什么压力的情况下,有些消息队列也可以用这种方法简化

      下面是测试代码:

      首先是配置文件

    <service name="HotelService.PublishService">
            <endpoint address="" binding="wsDualHttpBinding" contract="HotelService.IPublishService" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>

      服务和回调契约:

    复制代码
        [ServiceContract(CallbackContract = typeof(ISubscribeCallback), Namespace = "http://www.justonlyatest.com")]
        public interface IPublishService
        {
            [OperationContract(IsOneWay = true)]
            void DoWork();
    
            [OperationContract(IsOneWay = true)]
            void Subscribe(string id);
    
            [OperationContract(IsOneWay = true)]
            void UnSubscribe(string id);
        }
    
        public interface ISubscribeCallback
        {
            [OperationContract]//(IsOneWay = true)
            void CallbackWork(string workState);
        }
    复制代码

      服务实现,注释里简单交代了下实例模型下的效果

    复制代码
      // InstanceContextMode.Single 同步通知所有订阅的客户端,可将服务作为版本服务器的客户端,同步分布式服务的版本信息
        // InstanceContextMode.PerSession 同步同一Session下的所有订阅,本例中单个客户端实例的所有订阅
        // InstanceContextMode.PerCall 由于所有请求都是独立服务实例,所以无法实现订阅
        // ConcurrencyMode.Single 回调必须是IsOneWay
        // 回调是IsOneWay时可同步通知所有订阅方,否则只能顺序通知
        [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
        public class PublishService : IPublishService
        {
            Subscribers subscribers = new Subscribers();
            public void DoWork()
            {
                string workState = "完成";
                //ISubscribeCallback callback = OperationContext.Current.GetCallbackChannel<ISubscribeCallback>();
                //callback.CallbackWork(workState);
    
                Dictionary<string, ISubscribeCallback> subscribes = subscribers.Subscribes;
                foreach (var key in subscribes.Keys)
                {
                    subscribes[key].CallbackWork(key + ":" + workState);
                }
            }
    
            public void Subscribe(string id)
            {
                ISubscribeCallback callback = OperationContext.Current.GetCallbackChannel<ISubscribeCallback>();
                subscribers.AddSubscriber(id, callback);
            }
    
            public void UnSubscribe(string id)
            {
                ISubscribeCallback callback = OperationContext.Current.GetCallbackChannel<ISubscribeCallback>();
                subscribers.RemoveSubscriber(id, callback);
            }
        }
    复制代码
    复制代码
      public class Subscribers
        {
            public Dictionary<string, ISubscribeCallback> Subscribes { get; set; }
    
            public Subscribers()
            {
                Subscribes = new Dictionary<string, ISubscribeCallback>();
            }
    
            public void AddSubscriber(string id,ISubscribeCallback callback)
            {
                if (!Subscribes.Keys.Contains(id))
                {
                    Subscribes.Add(id, callback);
                }
            }
    
            public void RemoveSubscriber(string id, ISubscribeCallback callback)
            {
                if (Subscribes.Keys.Contains(id))
                {
                    Subscribes.Remove(id);
                }
            }
        }
    复制代码

    客户端测试

    复制代码
        PublishService.PublishServiceClient client;
            string clientID;
    
            public TestSubscribe()
            {
                InstanceContext context = new InstanceContext(new CallbackSubscribe());
                client = new PublishService.PublishServiceClient(context);
    
                clientID = Guid.NewGuid().ToString();
            }
    
            private void btnTest_Click(object sender, EventArgs e)
            {
                client.DoWork();
            }
    
            private void btnRegist_Click(object sender, EventArgs e)
            {
                client.Subscribe(clientID);
            }
    
            private void btnCancellation_Click(object sender, EventArgs e)
            {
                client.UnSubscribe(clientID);
            }
    复制代码
     
     
    分类: 架构相关
  • 相关阅读:
    swift学习笔记之-析构过程
    swift学习笔记之-错误处理
    swift学习笔记之-类型转换
    swift学习笔记之-构造过程
    day43 数据库学习egon的博客 约束
    day43 数据库知识欠缺的
    day41 python【事物 】【数据库锁】
    day40 python MySQL【四】 之 【索引】【视图】【触发器】【存储过程】【函数】
    day41 mysql 学习 练习题 重要*****
    day39 python 学习 数据库学习 五个约束,数据库设计(一对一,一对多等等)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3644123.html
Copyright © 2020-2023  润新知