在高并发WCF Web服务中使用实例和单例

时间:2013-08-01 14:22:01

标签: c# wcf web-services singleton .net-4.5

我正在开发一个WCF Web服务,该服务根据string providerCode从几个数据库之一返回信息。

在最高级别,该服务会调用StaticBroker类,该类会检查providerCode并返回DataManager的相应子类,假设为MyDataManager。然后,该服务调用MyDataManager.getVehicleFetcherForStop(),它返回一个类VehicleInfoFetcher的实例,用于获取信息。

我对这一切都很陌生,而且我认为我可能错误地构建了它。这是我现在如何做的代码(简化):

Service.svc.cs

// Public-facing web service method
public string getRealtimeInfo(String stopID, string providerCode = "UK")
{
    DataManager dm = StaticBroker.Instance.dataManager(stopID);
    return dm.getUpcomingVehicleInfoNow(primaryCode);
}

StaticBroker

public sealed class StaticBroker
{    
  UKDataManager ukDataManager = null;

  // Create one instance of each data manager when the Web Service is started,
  // to save memory
  private StaticBroker()
  {
      ukDataManager = new UKDataManager();
  }

  public DataManager dataManager(string providerCode)
  {
     if (providerCode.Equals(UKDataManager.DEFAULT_PROVIDER_CODE))
        return ukDataManager;
     // else if...
  }

  // Most singleton stuff snipped out
  private static readonly StaticBroker instance = new StaticBroker();
}

UKDataManager

public class UKDataManager : DataManager
{
    public const string DEFAULT_PROVIDER_CODE = "UK";

    public string getUpcomingVehicleInfoNow(string stopID)
    {
        VehicleInfoFetcher infoFetcher;
        if ( shouldCheckDB(stopID))
            VehicleInfoFetcher infoFetcher = new DatabaseVehicleInfoFetcher("UK");
        else 
            fetcher = new UKLiveVehicleInfoFetcher();

            return fetcher.getVehicleInfo(primaryCode).Result;  // This is an async method, but we wait for the result
        }
    }
}

正如您所看到的,我有一个StaticBroker的单例,它本身只存储每种DataManager类型的一个实例。最后,在DataManagers中,创建了实际工作的类SomeVehicleFetcher的实际实例。

这是一种明智的做法吗?或者,当Web服务的并发使用率很高时,这些单身人士和共享实例是否会导致问题?我担心创建大量新实例可能会导致内存问题。正如您所看到的,我并不真正理解应用程序的生命周期/内存周期在Web服务中是如何工作的。

1 个答案:

答案 0 :(得分:3)

您正在尝试使用您不相信正确或需要的设计来解决假设性问题(“可能导致内存问题”)。此外,ADO.NET还有大量优化处理数据库连接性能。

这只是创造了更多的工作和更多的测试难题(你将如何隔离依赖于这个代理的代码?)。

请参阅反模式:

过早优化,未在此发明

修改

public interface IVehicleInfoRetriever {
    VehicleInfoResponse getVehicleInfo(string primaryCode);
}

public class DataManager<TVehicleInfoFetcher> 
    where TVehicleInfoFetcher : class, new(), IVehicleInfoRetriever 
{

    private string _providerCode;

    public DataManager() : this("UK") { }

    public DataManager(string providerCode) {
        _providerCode = providerCode;
    }

    public string getUpcomingVehicleInfoNow(string stopID)
    {
        VehicleInfoFetcher infoFetcher;
        if ( shouldCheckDB(stopID))
            VehicleInfoFetcher infoFetcher = new DatabaseVehicleInfoFetcher(_providerCode);
        else 
            fetcher = new TVehicleInfoFetcher();

            return fetcher.getVehicleInfo(primaryCode).Result;  // This is an async method, but we wait for the result
        }
    }

}

这样的东西消除了对'经纪人'的需求。

另外,你称之为'Broker'的类更像是一个工厂而且工厂已经失宠了,因为它们允许在杂草中而不是在顶部指定依赖注入,并且它们进行环境配置单元测试复杂的事业。

当然,DataManager的风格可能与您展示的有很多不同。如果是这种情况并且它们无法集中,那么我建议您调查可用的许多Inversion Of Control容器之一(AutoFac,Unity,Castle Windsor)。这些容器将根据最顶层的提供者代码的运行时值保留DataManager使用的风格逻辑。