2

I've been tasked with moving over dozens of WCF Services to a single Windows Service. I've created a Windows Service using the Windows Service template and added the the following code to ServiceHostController:

public partial class ServiceHostController : ServiceBase
{
    private List<ServiceHost> serviceHosts;

    public ServiceHostController()
    {
        InitializeComponent();
        this.ServiceName = "WCFServices";
        this.CanStop = true;
        this.AutoLog = true;
    }

    protected override void OnStart(string[] args)
    {
        if (serviceHosts != null)
        {
            foreach (var service in serviceHosts)
            {
                service.Close();
            }
        }

        InitializeServices();
        foreach (var service in serviceHosts)
        {
            service.Open();
        }
    }

    protected override void OnStop()
    {
        if (serviceHosts != null)
        {
            foreach (var service in serviceHosts)
            {
                service.Close();
            }
            serviceHosts.Close(); = null;
        }

        foreach (var service in serviceHosts)
        {
            service.Close();
        }
    }

    private void InitializeServices()
    {
        serviceHosts = new List<ServiceHost>()
        {
            new ServiceHost(typeof(WCFService1)),
            new ServiceHost(typeof(WCFService2)),
            // add dozens of services here
        };
    }
}

Besides not following the Do not repeat yourself rule here (actual code is different), is this how I should be hosting these WCF services in the Windows Service code?

5StringRyan
  • 3,604
  • 5
  • 46
  • 69
  • 3
    I prefer to host each WCF service in one windows service, not 2in1, cause finding fault, and extending services is easier in this way. – Saeed Amiri Nov 09 '11 at 19:03
  • Why a Windows Service and not IIS or WAS? – Tad Donaghe Nov 09 '11 at 20:59
  • @Terry - Quoting Murdock from Rambo First Blood Part II "I don't make the orders, I take them just like you..." From what I understand it's due to deployment machines using Win XP. – 5StringRyan Nov 09 '11 at 21:03
  • Cool. Is it also a requirement that they all have to be hosted in the same windows service? – Tad Donaghe Nov 09 '11 at 21:16
  • @SaeedAmiri you are scaring me I got about 60 services does it mean I need to have 60 windows services ? – Surjit Samra Nov 09 '11 at 22:02
  • @TerryDonaghe - Yes, they have to be hosted in the same windows service. – 5StringRyan Nov 09 '11 at 22:04
  • 60 services!!! may be you say 60 method in your services!? 60 web services is really big project, very very very big, are you sure about your architecture? – Saeed Amiri Nov 09 '11 at 22:08
  • 100%, it is in production from last 10 years up until last year it used .NET Remoting , I recently migrated it to wCF, In case you wondering what it is. It is a "Finance Back Office" which runs Payroll, Manages CRM, Manage Accountings, Banking, Investments,Valuations, Tax Filing are from top of my head. – Surjit Samra Nov 09 '11 at 22:11
  • @SSamra In this case, you shouldn't be able to handle all of them in one machine, because of huge amount of load, and in this case it's essential to distribute them, and for distributing them, first should put them in different windows services, but you can manage multiple items in one service if you want, but again I prefer to redesign my architecture. – Saeed Amiri Nov 09 '11 at 22:18
  • @SaeedAmiri , You will have 1 day to think/experiment, 1/2 day to document it and explain to your manager and team and face tough questions what you were doing in last 1.5 days , then you will be given an other 4.5 days to implement it and first thing on Monday morning you have to give demo to rest of the team Do you still want to redesign :) – Surjit Samra Nov 09 '11 at 22:41
  • @SaeedAmiri You have to assume that they know what they are doing here. Perhaps most of these services only receives one or two calls each day, or only has one or two simple operations. There's no reason that one machine can't handle them all. – Kirk Broadhurst Nov 09 '11 at 22:48
  • @SaeedAmiri amd Kirk as this is about 10 year old solution , We did not have so many services when we started, but these got added on year by year and as the market demands things gone bit outgrown. – Surjit Samra Nov 09 '11 at 22:55
  • @KirkBroadhurst Also we work on banking solution, we have lot of services, but not 60, but we have multiple server and mainframe to handle huge amount of transactions and data, but our architecture has some problems, it works fine, but should be re-factored, like every other software in the world and like SSamra's one. – Saeed Amiri Nov 09 '11 at 23:01
  • @SSamra I respect to your architecture and design and sure software which alive for 10 year should be great. I'm not saying your design has obvious problems, I just said this to `OP` to do load balancing also simple debugging and so on ... – Saeed Amiri Nov 09 '11 at 23:04
  • @HansGruber - If the services have been migrated from Remoting to Web services my guess is that the granularity is not optimal. Remoting systems invited the designer to create 'chatty' interfaces while web services are more fit to be message based. I know that it is impossible to break the interfaces in a very short time but I do think that if this is the case this will haunt you later on when trying to get performance and throughput up to par. – Emond Nov 10 '11 at 07:55
  • @HansGruber That is the situation I am in, with .Net remoting or all previous distributed technologies gave wrong impression of using components as they are live locally, hence very chatty interfaces. Also agree with Kirk Some of the services are only at particular time of day when uploading the valuations used few times in a month eg Payroll Services and some services are only used few times a Year eg Tax Filing services. – Surjit Samra Nov 10 '11 at 09:01

1 Answers1

3

Hans, you got everything right, But I will replace your InitializeServices(); with following code. It is pseudo code so you need to replace the bits :)

1) Configure your endpoints in app.config

2) Get your Service types from your Service project\assembly

  Dictionary<Type, Type> mappings = new Dictionary<Type,Type>();

   foreach (Type t in MyServiceAssembly.GetTypes())
  {
    if (t.GetInterfaces().Length > 0)
    {
      foreach (Type ti in t.GetInterfaces())

        {
          if (mapping.ContainsKey(ti))
            System.Diagnostics.Debug.WriteLine("Class {0} implements more than one interface {1}", t.FullName, ti.FullName);
          else
            mapping.Add(ti, t);

          // System.Diagnostics.Debug.WriteLine("Class {0} implements {1}", t.FullName, ti.FullName);
        }
    }
  }

4) If you want control end points from app.config Now iterate over your end points and get corresponding service implementation then create your hosts

//read your endpoints in your service startup

 List<ServiceHost> serviceHosts = new List<ServiceHost>();

     ServicesSection servicesSection = (ServicesSection)WebConfigurationManager.GetSection("system.serviceModel/services");  

    for(int i = 0;i<servicesSection.Services.Count;i++)
    {
    ServiceEndpointElement endpoint = servicesSection.Services[i].Endpoints[0];  
    string url = string.Format("net.tcp://{0}:{1}/YouNameSpace_service_Name_From_EndPoint/{2}.svc","YourHost","YourPort");
      ServiceHost serviceHost = new ServiceHost(mappings[endpoint.Contract] , new Uri(url));

              serviceHost.Open();

              mServiceHosts.Add(serviceHost);
    }

5) If you do not want to control end points from app.config then iterate over your mapping list.

//do this in your service startup

 List<ServiceHost> serviceHosts = new List<ServiceHost>();

     foreach(type t in mappings.Keys)
    {
            string url = string.Format("net.tcp://{0}:{1}/YouNameSpace_{2}.svc","YourHost","YourPort",t.name);
      ServiceHost serviceHost = new ServiceHost(mappings[t] , new Uri(url));

              serviceHost.Open();

              mServiceHosts.Add(serviceHost);
    }
Surjit Samra
  • 4,614
  • 1
  • 26
  • 36
  • I can see with step 2 that you are mapping implementation classes to interfaces that are provided my the service assembly itself, but I'm not sure why you are reading in the endpoints from the app.config file. Could you explain? – 5StringRyan Nov 10 '11 at 18:48
  • I know you gonna ask this, This is the way we control customer specific end points eg say a customer A Bespoke implementation where we are interfacing to their exisiting systems. So this is the way we switch off that end point for other customers. It give you capability what you want to expose. – Surjit Samra Nov 10 '11 at 20:27
  • While I ended up not using the functionality provided (as I don't need to worry about customer specific endpoints), I've accepted your answer. – 5StringRyan Nov 18 '11 at 18:16