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);

        }
复制代码
 
 
分类:  架构相关

你可能感兴趣的:(WCF)