简体   繁体   English

一个WCF服务的更改应更新同一WCF服务的其他实例的相同更改

[英]Change in one WCF service should update the same change in other instances of the same WCF services

I have multiple instances of the same WCF service hosted. 我托管了同一WCF服务的多个实例。 If there is a change in one of the service instance then it should be notified/updated in other services too. 如果服务实例之一发生更改,则也应在其他服务中通知/更新它。 I implemented the solution such that the WCF service acts as both client and server with the DuplexChannelFactory. 我实现了该解决方案,以使WCF服务在DuplexChannelFactory中既充当客户端又充当服务器。 But in order to do that the service needs to register its peers and I am doing that in the constructor of the service. 但是为了做到这一点,服务需要注册其对等体,而我正在服务的构造函数中进行此操作。 This is leading to deadlock, since it is never going to get out initializing each other. 这将导致死锁,因为它永远不会互相初始化。 How is this sort of logic can be implemented in WCF service? 在WCF服务中如何实现这种逻辑?

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Timers;
using WcfServiceLibrary.PeerServiceReference;

namespace WcfServiceLibrary
{
    public interface IHeartbeat
    {
        bool Pulse();
        void Ping();
    }

    [ServiceContract(CallbackContract = typeof(INotifications))]
    public interface ISubscription : IHeartbeat, INotifications
    {
        [OperationContract(IsOneWay = true)]
        void Subscribe(string ServiceName);
        [OperationContract(IsOneWay = true)]
        void Unsubscribe(string ServiceName);
    }

    [ServiceContract]
    public interface INotifications
    {
        [OperationContract(IsOneWay = true)]
        void UpdateData(int newValue);
    }

    [ServiceContract]
    public interface IUserService
    {
        [OperationContract(IsOneWay = true)]
        void MethodThatWillChangeData(int value);
    }
    public class ObservableService : IUserService, ISubscription
    {
        private static Dictionary<string, ISubscription> _Peers = new Dictionary<string, ISubscription>();
        private int ClientAge;
        private string ServiceName { get; }
        private Timer _timer = new Timer() { Interval = 5000 };
        private IWriter _writer;
        public ObservableService() : this(new ConsoleWriter())
        {

        }
        public ObservableService(IWriter writer)
        {
            _writer = writer;
            _writer.WriteLine("Initiating construction...");
            ServiceName = ConfigurationManager.AppSettings["ServiceName"];
            _timer.Elapsed += Timer_Elapsed;
            _timer.Start();
            var PeerServersList = ConfigurationManager.AppSettings["PeerServers"].Split(';');
            var callback = new InstanceContext(this);
            foreach (var peer in PeerServersList)
            {
                try
                {
                    var dualBinding = new WSDualHttpBinding();
                    var address = new EndpointAddress(peer);
                    var PeerServiceFactory = new DuplexChannelFactory<ISubscription>(callback, dualBinding);
                    var PeerService = PeerServiceFactory.CreateChannel(address);
                    PeerService.Subscribe(ServiceName);
                }
                catch (Exception ex)
                {
                    //TODO handle the exception
                }
            }
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _writer.WriteLine("Pinging the data");
            this.Ping();
        }

        public void MethodThatWillChangeData(int newValue)
        {
            _writer.WriteLine($"MethodThatWillChangeData with {newValue}");
            var PreviousClientAge = ClientAge;
            ClientAge = newValue;
            foreach (var peer in _Peers)
            {
                _writer.WriteLine($"Calling update on the client {peer.Key}");
                peer.Value.UpdateData(newValue);
            }
        }

        public void Ping()
        {
            var test = _Peers.Keys.ToList();
            for (int i = _Peers.Count - 1; i >= 0; i--)
            {
                try
                {
                    _writer.WriteLine($"Checking the pulse of {test[i]}");
                    _Peers[test[i]].Pulse();
                }
                catch (Exception)
                {
                    _Peers.Remove(test[i]);
                }
            }
        }

        public bool Pulse()
        {
            _writer.WriteLine($"Pulse requested...");
            return true;
        }

        public void UpdateData(int newValue)
        {
            _writer.WriteLine($"Updating the data to {newValue} from {ClientAge}");
            ClientAge = newValue;
        }

        public void Unsubscribe(string ServiceName)
        {
            if (_Peers.Keys.Contains(ServiceName))
            {
                _Peers.Remove(ServiceName);
            }
        }

        public void Subscribe(string ServiceName)
        {
            if (!_Peers.Keys.Contains(ServiceName))
            {
                _writer.WriteLine($"Registering {ServiceName}...");
                _Peers.Add(ServiceName, OperationContext.Current.GetCallbackChannel<ISubscription>());
            }
        }
    }
}

I would have a single separate WCF service that manages whatever data you're trying to keep synchronised across your services and have each service communicate with that. 我将有一个单独的WCF服务,该服务可以管理您要在服务之间保持同步的任何数据,并使每个服务都与之通信。

Alternatively, you keep your data in a database so any change is automatically reflected across the services. 另外,您也可以将数据保存在数据库中,以便所有更改都会自动反映在服务中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM