Пример #1
0
        /// <summary>
        /// Allows silo config to be programmatically set.
        /// </summary>
        /// <param name="config">Configuration data for this silo & cluster.</param>
        private void SetSiloConfig(ClusterConfiguration config)
        {
            Config = config;

            if (Verbose > 0)
            {
                Config.Defaults.DefaultTraceLevel = (Logger.Severity.Verbose - 1 + Verbose);
            }


            if (!String.IsNullOrEmpty(DeploymentId))
            {
                Config.Globals.DeploymentId = DeploymentId;
            }

            if (string.IsNullOrWhiteSpace(Name))
            {
                throw new ArgumentException("SiloName not defined - cannot initialize config");
            }

            NodeConfig = Config.GetConfigurationForNode(Name);
            Type       = NodeConfig.IsPrimaryNode ? Silo.SiloType.Primary : Silo.SiloType.Secondary;

            if (TraceFilePath != null)
            {
                var traceFileName = Config.GetConfigurationForNode(Name).TraceFileName;
                if (traceFileName != null && !Path.IsPathRooted(traceFileName))
                {
                    Config.GetConfigurationForNode(Name).TraceFileName = TraceFilePath + "\\" + traceFileName;
                }
            }

            ConfigLoaded = true;
            InitializeLogger(config.GetConfigurationForNode(Name));
        }
Пример #2
0
        public override void AdjustForTest(ClusterConfiguration config)
        {
            var settings = new Dictionary <string, string>
            {
                { PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.ToString() },
                { PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString() }
            };

            config.Globals.RegisterStreamProvider <ControllableTestStreamProvider>(StreamProviderName, settings);
            config.GetConfigurationForNode("Primary");
            config.GetConfigurationForNode("Secondary_1");
            base.AdjustForTest(config);
        }
        internal static void InitSchedulerLogging()
        {
            TraceLogger.UnInitialize();
            //TraceLogger.LogConsumers.Add(new LogWriterToConsole());
            if (!Logger.TelemetryConsumers.OfType <ConsoleTelemetryConsumer>().Any())
            {
                Logger.TelemetryConsumers.Add(new ConsoleTelemetryConsumer());
            }

            var traceLevels = new[]
            {
                Tuple.Create("Scheduler", Severity.Verbose3),
                Tuple.Create("Scheduler.WorkerPoolThread", Severity.Verbose2),
            };

            TraceLogger.SetTraceLevelOverrides(new List <Tuple <string, Severity> >(traceLevels));

            var orleansConfig = new ClusterConfiguration();

            orleansConfig.StandardLoad();
            NodeConfiguration config = orleansConfig.GetConfigurationForNode("Primary");

            StatisticsCollector.Initialize(config);
            SchedulerStatisticsGroup.Init();
        }
Пример #4
0
        public static void AdjustClusterConfiguration(ClusterConfiguration config)
        {
            var settings = new Dictionary <string, string>();

            // get initial settings from configs
            ProviderConfig.WriteProperties(settings);
            EventHubConfig.WriteProperties(settings);

            // add queue balancer setting
            settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.ToString());

            // register stream provider
            config.Globals.RegisterStreamProvider <EventHubStreamProvider>(StreamProviderName, settings);
            config.Globals.RegisterStorageProvider <MemoryStorage>("PubSubStore");

            // make sure all node configs exist, for dynamic cluster queue balancer
            config.GetConfigurationForNode("Primary");
            config.GetConfigurationForNode("Secondary_1");
        }
Пример #5
0
        public override void AdjustForTest(ClusterConfiguration config)
        {
            var settings = new Dictionary <string, string>();

            // get initial settings from configs
            AdapterConfig.WriteProperties(settings);

            // add queue balancer setting
            settings.Add(PersistentStreamProviderConfig.QUEUE_BALANCER_TYPE, StreamQueueBalancerType.DynamicClusterConfigDeploymentBalancer.ToString());

            // add pub/sub settting
            settings.Add(PersistentStreamProviderConfig.STREAM_PUBSUB_TYPE, StreamPubSubType.ImplicitOnly.ToString());

            // register stream provider
            config.Globals.RegisterStreamProvider <GeneratorStreamProvider>(StreamProviderName, settings);

            // make sure all node configs exist, for dynamic cluster queue balancer
            config.GetConfigurationForNode("Primary");
            config.GetConfigurationForNode("Secondary_1");

            base.AdjustForTest(config);
        }
        public static void ClassInitialize(TestContext testContext)
        {
            hostName = Dns.GetHostName();
            logger   = TraceLogger.GetLogger("MembershipTablePluginTests", TraceLogger.LoggerType.Application);

            ClusterConfiguration cfg = new ClusterConfiguration();

            cfg.LoadFromFile("OrleansConfigurationForTesting.xml");
            TraceLogger.Initialize(cfg.GetConfigurationForNode("Primary"));

            TraceLogger.AddTraceLevelOverride("AzureTableDataManager", Severity.Verbose3);
            TraceLogger.AddTraceLevelOverride("OrleansSiloInstanceManager", Severity.Verbose3);
            TraceLogger.AddTraceLevelOverride("Storage", Severity.Verbose3);
        }
Пример #7
0
        private SiloHandle StartOrleansSilo(Silo.SiloType type, TestingSiloOptions options, int instanceCount, AppDomain shared = null)
        {
            // Load initial config settings, then apply some overrides below.
            ClusterConfiguration config = new ClusterConfiguration();

            if (options.SiloConfigFile == null)
            {
                config.StandardLoad();
            }
            else
            {
                config.LoadFromFile(options.SiloConfigFile.FullName);
            }

            int basePort = options.BasePort < 0 ? BasePort : options.BasePort;


            if (config.Globals.SeedNodes.Count > 0 && options.BasePort < 0)
            {
                config.PrimaryNode = config.Globals.SeedNodes[0];
            }
            else
            {
                config.PrimaryNode = new IPEndPoint(IPAddress.Loopback, basePort);
            }
            config.Globals.SeedNodes.Clear();
            config.Globals.SeedNodes.Add(config.PrimaryNode);

            if (!String.IsNullOrEmpty(DeploymentId))
            {
                config.Globals.DeploymentId = DeploymentId;
            }
            config.Defaults.PropagateActivityId = options.PropagateActivityId;
            if (options.LargeMessageWarningThreshold > 0)
            {
                config.Defaults.LargeMessageWarningThreshold = options.LargeMessageWarningThreshold;
            }

            config.Globals.LivenessType        = options.LivenessType;
            config.Globals.ReminderServiceType = options.ReminderServiceType;
            if (!String.IsNullOrEmpty(options.DataConnectionString))
            {
                config.Globals.DataConnectionString = options.DataConnectionString;
            }

            _livenessStabilizationTime = GetLivenessStabilizationTime(config.Globals);

            string siloName;

            switch (type)
            {
            case Silo.SiloType.Primary:
                siloName = "Primary";
                break;

            default:
                siloName = "Secondary_" + instanceCount.ToString(CultureInfo.InvariantCulture);
                break;
            }

            NodeConfiguration nodeConfig = config.GetConfigurationForNode(siloName);

            nodeConfig.HostNameOrIPAddress = "loopback";
            nodeConfig.Port = basePort + instanceCount;
            nodeConfig.DefaultTraceLevel   = config.Defaults.DefaultTraceLevel;
            nodeConfig.PropagateActivityId = config.Defaults.PropagateActivityId;
            nodeConfig.BulkMessageLimit    = config.Defaults.BulkMessageLimit;

            if (nodeConfig.ProxyGatewayEndpoint != null && nodeConfig.ProxyGatewayEndpoint.Address != null)
            {
                nodeConfig.ProxyGatewayEndpoint = new IPEndPoint(nodeConfig.ProxyGatewayEndpoint.Address, ProxyBasePort + instanceCount);
            }

            config.Globals.ExpectedClusterSize = 2;

            config.Overrides[siloName] = nodeConfig;

            AdjustForTest(config, options);

            WriteLog("Starting a new silo in app domain {0} with config {1}", siloName, config.ToString(siloName));
            AppDomain appDomain;
            Silo      silo = LoadSiloInNewAppDomain(siloName, type, config, out appDomain);

            silo.Start();

            SiloHandle retValue = new SiloHandle
            {
                Name      = siloName,
                Silo      = silo,
                Options   = options,
                Endpoint  = silo.SiloAddress.Endpoint,
                AppDomain = appDomain,
            };

            ImportGeneratedAssemblies(retValue);
            return(retValue);
        }
Пример #8
0
        internal Silo(string name, SiloType siloType, ClusterConfiguration config, ILocalDataStore keyStore)
        {
            SystemStatus.Current = SystemStatus.Creating;

            CurrentSilo = this;

            var startTime = DateTime.UtcNow;

            this.siloType = siloType;
            Name          = name;

            siloTerminatedEvent = new ManualResetEvent(false);

            OrleansConfig = config;
            globalConfig  = config.Globals;
            config.OnConfigChange("Defaults", () => nodeConfig = config.GetConfigurationForNode(name));

            if (!TraceLogger.IsInitialized)
            {
                TraceLogger.Initialize(nodeConfig);
            }

            config.OnConfigChange("Defaults/Tracing", () => TraceLogger.Initialize(nodeConfig, true), false);
            LimitManager.Initialize(nodeConfig);
            ActivationData.Init(config);
            StatisticsCollector.Initialize(nodeConfig);
            SerializationManager.Initialize(globalConfig.UseStandardSerializer);
            initTimeout = globalConfig.MaxJoinAttemptTime;
            if (Debugger.IsAttached)
            {
                initTimeout = StandardExtensions.Max(TimeSpan.FromMinutes(10), globalConfig.MaxJoinAttemptTime);
                stopTimeout = initTimeout;
            }

            IPEndPoint here       = nodeConfig.Endpoint;
            int        generation = nodeConfig.Generation;

            if (generation == 0)
            {
                generation            = SiloAddress.AllocateNewGeneration();
                nodeConfig.Generation = generation;
            }
            TraceLogger.MyIPEndPoint = here;
            logger = TraceLogger.GetLogger("Silo", TraceLogger.LoggerType.Runtime);
            logger.Info(ErrorCode.SiloInitializing, "-------------- Initializing {0} silo on {1} at {2}, gen {3} --------------", siloType, nodeConfig.DNSHostName, here, generation);
            logger.Info(ErrorCode.SiloInitConfig, "Starting silo {0} with runtime Version='{1}' Config= \n{2}", name, RuntimeVersion.Current, config.ToString(name));

            if (keyStore != null)
            {
                // Re-establish reference to shared local key store in this app domain
                LocalDataStoreInstance.LocalDataStore = keyStore;
            }
            healthCheckParticipants = new List <IHealthCheckParticipant>();

            BufferPool.InitGlobalBufferPool(globalConfig);
            PlacementStrategy.Initialize(globalConfig);

            UnobservedExceptionsHandlerClass.SetUnobservedExceptionHandler(UnobservedExceptionHandler);
            AppDomain.CurrentDomain.UnhandledException +=
                (obj, ev) => DomainUnobservedExceptionHandler(obj, (Exception)ev.ExceptionObject);

            typeManager = new GrainTypeManager(here.Address.Equals(IPAddress.Loopback));

            // Performance metrics
            siloStatistics = new SiloStatisticsManager(globalConfig, nodeConfig);
            config.OnConfigChange("Defaults/LoadShedding", () => siloStatistics.MetricsTable.NodeConfig = nodeConfig, false);

            // The scheduler
            scheduler = new OrleansTaskScheduler(globalConfig, nodeConfig);
            healthCheckParticipants.Add(scheduler);

            // Initialize the message center
            var mc = new MessageCenter(here, generation, globalConfig, siloStatistics.MetricsTable);

            if (nodeConfig.IsGatewayNode)
            {
                mc.InstallGateway(nodeConfig.ProxyGatewayEndpoint);
            }

            messageCenter = mc;

            // Now the router/directory service
            // This has to come after the message center //; note that it then gets injected back into the message center.;
            localGrainDirectory = new LocalGrainDirectory(this);

            // Now the activation directory.
            // This needs to know which router to use so that it can keep the global directory in synch with the local one.
            activationDirectory = new ActivationDirectory();

            // Now the consistent ring provider
            RingProvider = GlobalConfig.UseVirtualBucketsConsistentRing ?
                           (IConsistentRingProvider) new VirtualBucketsRingProvider(SiloAddress, GlobalConfig.NumVirtualBucketsConsistentRing)
                : new ConsistentRingProvider(SiloAddress);

            Action <Dispatcher> setDispatcher;

            catalog = new Catalog(Constants.CatalogId, SiloAddress, Name, LocalGrainDirectory, typeManager, scheduler, activationDirectory, config, out setDispatcher);
            var dispatcher = new Dispatcher(scheduler, messageCenter, catalog, config);

            setDispatcher(dispatcher);

            RuntimeClient.Current = new InsideRuntimeClient(
                dispatcher,
                catalog,
                LocalGrainDirectory,
                SiloAddress,
                config,
                RingProvider,
                typeManager);
            messageCenter.RerouteHandler       = InsideRuntimeClient.Current.RerouteMessage;
            messageCenter.SniffIncomingMessage = InsideRuntimeClient.Current.SniffIncomingMessage;
            messageCenter.ClientDropHandler    = grainIds =>
            {
                catalog.DeleteGrainsLocal(grainIds).Ignore();
                scheduler.RunOrQueueAction(() =>
                {
                    // Consider: batch delete
                    foreach (var id in grainIds)
                    {
                        LocalGrainDirectory.DeleteGrain(id).Ignore();
                    }
                }, catalog.SchedulingContext);
            };

            siloStatistics.MetricsTable.Scheduler           = scheduler;
            siloStatistics.MetricsTable.ActivationDirectory = activationDirectory;
            siloStatistics.MetricsTable.ActivationCollector = catalog.ActivationCollector;
            siloStatistics.MetricsTable.MessageCenter       = messageCenter;

            DeploymentLoadPublisher.CreateDeploymentLoadPublisher(this, globalConfig);
            PlacementDirectorsManager.CreatePlacementDirectorsManager(globalConfig);

            // Now the incoming message agents
            incomingSystemAgent = new IncomingMessageAgent(Message.Categories.System, messageCenter, activationDirectory, scheduler, dispatcher);
            incomingPingAgent   = new IncomingMessageAgent(Message.Categories.Ping, messageCenter, activationDirectory, scheduler, dispatcher);
            incomingAgent       = new IncomingMessageAgent(Message.Categories.Application, messageCenter, activationDirectory, scheduler, dispatcher);

            membershipFactory = new MembershipFactory();
            reminderFactory   = new LocalReminderServiceFactory();

            SystemStatus.Current = SystemStatus.Created;

            StringValueStatistic.FindOrCreate(StatisticNames.SILO_START_TIME,
                                              () => TraceLogger.PrintDate(startTime)); // this will help troubleshoot production deployment when looking at MDS logs.

            TestHookup = new TestHookups(this);

            logger.Info(ErrorCode.SiloInitializingFinished, "-------------- Started silo {0}, ConsistentHashCode {1:X} --------------", SiloAddress.ToLongString(), SiloAddress.GetConsistentHashCode());
        }
Пример #9
0
        internal Silo(string name, SiloType siloType, ClusterConfiguration config, ILocalDataStore keyStore)
        {
            SystemStatus.Current = SystemStatus.Creating;

            CurrentSilo = this;

            var startTime = DateTime.UtcNow;

            this.siloType = siloType;
            Name          = name;

            siloTerminatedEvent = new ManualResetEvent(false);

            OrleansConfig = config;
            globalConfig  = config.Globals;
            config.OnConfigChange("Defaults", () => nodeConfig = config.GetConfigurationForNode(name));

            if (!TraceLogger.IsInitialized)
            {
                TraceLogger.Initialize(nodeConfig);
            }

            config.OnConfigChange("Defaults/Tracing", () => TraceLogger.Initialize(nodeConfig, true), false);

            ActivationData.Init(config, nodeConfig);
            StatisticsCollector.Initialize(nodeConfig);
            SerializationManager.Initialize(globalConfig.UseStandardSerializer);
            initTimeout = globalConfig.MaxJoinAttemptTime;
            if (Debugger.IsAttached)
            {
                initTimeout = StandardExtensions.Max(TimeSpan.FromMinutes(10), globalConfig.MaxJoinAttemptTime);
                stopTimeout = initTimeout;
            }

            IPEndPoint here       = nodeConfig.Endpoint;
            int        generation = nodeConfig.Generation;

            if (generation == 0)
            {
                generation            = SiloAddress.AllocateNewGeneration();
                nodeConfig.Generation = generation;
            }
            TraceLogger.MyIPEndPoint = here;
            logger = TraceLogger.GetLogger("Silo", TraceLogger.LoggerType.Runtime);

            logger.Info(ErrorCode.SiloGcSetting, "Silo starting with GC settings: ServerGC={0} GCLatencyMode={1}", GCSettings.IsServerGC, Enum.GetName(typeof(GCLatencyMode), GCSettings.LatencyMode));
            if (!GCSettings.IsServerGC || !GCSettings.LatencyMode.Equals(GCLatencyMode.Batch))
            {
                logger.Warn(ErrorCode.SiloGcWarning, "Note: Silo not running with ServerGC turned on or with GCLatencyMode.Batch enabled - recommend checking app config : <configuration>-<runtime>-<gcServer enabled=\"true\"> and <configuration>-<runtime>-<gcConcurrent enabled=\"false\"/>");
            }

            logger.Info(ErrorCode.SiloInitializing, "-------------- Initializing {0} silo on host {1} MachineName {2} at {3}, gen {4} --------------",
                        siloType, nodeConfig.DNSHostName, Environment.MachineName, here, generation);
            logger.Info(ErrorCode.SiloInitConfig, "Starting silo {0} with runtime Version='{1}' .NET version='{2}' Is .NET 4.5={3} OS version='{4}' Config= " + Environment.NewLine + "{5}",
                        name, RuntimeVersion.Current, Environment.Version, ConfigUtilities.IsNet45OrNewer(), Environment.OSVersion, config.ToString(name));

            if (keyStore != null)
            {
                // Re-establish reference to shared local key store in this app domain
                LocalDataStoreInstance.LocalDataStore = keyStore;
            }
            healthCheckParticipants = new List <IHealthCheckParticipant>();
            allSiloProviders        = new List <IProvider>();

            BufferPool.InitGlobalBufferPool(globalConfig);
            PlacementStrategy.Initialize(globalConfig);

            UnobservedExceptionsHandlerClass.SetUnobservedExceptionHandler(UnobservedExceptionHandler);
            AppDomain.CurrentDomain.UnhandledException +=
                (obj, ev) => DomainUnobservedExceptionHandler(obj, (Exception)ev.ExceptionObject);

            grainFactory = new GrainFactory();
            typeManager  = new GrainTypeManager(here.Address.Equals(IPAddress.Loopback), grainFactory);

            // Performance metrics
            siloStatistics = new SiloStatisticsManager(globalConfig, nodeConfig);
            config.OnConfigChange("Defaults/LoadShedding", () => siloStatistics.MetricsTable.NodeConfig = nodeConfig, false);

            // The scheduler
            scheduler = new OrleansTaskScheduler(globalConfig, nodeConfig);
            healthCheckParticipants.Add(scheduler);

            // Initialize the message center
            var mc = new MessageCenter(here, generation, globalConfig, siloStatistics.MetricsTable);

            if (nodeConfig.IsGatewayNode)
            {
                mc.InstallGateway(nodeConfig.ProxyGatewayEndpoint);
            }

            messageCenter = mc;

            SiloIdentity = SiloAddress.ToLongString();

            // GrainRuntime can be created only here, after messageCenter was created.
            grainRuntime = new GrainRuntime(
                globalConfig.ServiceId,
                SiloIdentity,
                grainFactory,
                new TimerRegistry(),
                new ReminderRegistry(),
                new StreamProviderManager());


            // Now the router/directory service
            // This has to come after the message center //; note that it then gets injected back into the message center.;
            localGrainDirectory = new LocalGrainDirectory(this);

            // Now the activation directory.
            // This needs to know which router to use so that it can keep the global directory in synch with the local one.
            activationDirectory = new ActivationDirectory();

            // Now the consistent ring provider
            RingProvider = GlobalConfig.UseVirtualBucketsConsistentRing ?
                           (IConsistentRingProvider) new VirtualBucketsRingProvider(SiloAddress, GlobalConfig.NumVirtualBucketsConsistentRing)
                : new ConsistentRingProvider(SiloAddress);

            Action <Dispatcher> setDispatcher;

            catalog = new Catalog(Constants.CatalogId, SiloAddress, Name, LocalGrainDirectory, typeManager, scheduler, activationDirectory, config, grainRuntime, out setDispatcher);
            var dispatcher = new Dispatcher(scheduler, messageCenter, catalog, config);

            setDispatcher(dispatcher);

            RuntimeClient.Current = new InsideRuntimeClient(
                dispatcher,
                catalog,
                LocalGrainDirectory,
                SiloAddress,
                config,
                RingProvider,
                typeManager,
                grainFactory);
            messageCenter.RerouteHandler       = InsideRuntimeClient.Current.RerouteMessage;
            messageCenter.SniffIncomingMessage = InsideRuntimeClient.Current.SniffIncomingMessage;

            siloStatistics.MetricsTable.Scheduler           = scheduler;
            siloStatistics.MetricsTable.ActivationDirectory = activationDirectory;
            siloStatistics.MetricsTable.ActivationCollector = catalog.ActivationCollector;
            siloStatistics.MetricsTable.MessageCenter       = messageCenter;

            DeploymentLoadPublisher.CreateDeploymentLoadPublisher(this, globalConfig);
            PlacementDirectorsManager.CreatePlacementDirectorsManager(globalConfig);

            // Now the incoming message agents
            incomingSystemAgent = new IncomingMessageAgent(Message.Categories.System, messageCenter, activationDirectory, scheduler, dispatcher);
            incomingPingAgent   = new IncomingMessageAgent(Message.Categories.Ping, messageCenter, activationDirectory, scheduler, dispatcher);
            incomingAgent       = new IncomingMessageAgent(Message.Categories.Application, messageCenter, activationDirectory, scheduler, dispatcher);

            membershipFactory = new MembershipFactory();
            reminderFactory   = new LocalReminderServiceFactory();

            SystemStatus.Current = SystemStatus.Created;

            StringValueStatistic.FindOrCreate(StatisticNames.SILO_START_TIME,
                                              () => TraceLogger.PrintDate(startTime)); // this will help troubleshoot production deployment when looking at MDS logs.

            TestHookup = new TestHookups(this);

            logger.Info(ErrorCode.SiloInitializingFinished, "-------------- Started silo {0}, ConsistentHashCode {1:X} --------------", SiloAddress.ToLongString(), SiloAddress.GetConsistentHashCode());
        }
Пример #10
0
        private SiloHandle _StartOrleansSilo(Silo.SiloType type, UnitTestSiloOptions options, AppDomain shared = null)
        {
            // Load initial config settings, then apply some overrides below.
            ClusterConfiguration config = new ClusterConfiguration();

            if (options.SiloConfigFile == null)
            {
                config.StandardLoad();
            }
            else
            {
                config.LoadFromFile(options.SiloConfigFile.FullName);
            }

            int basePort = options.BasePort >= 0 ? options.BasePort : BasePort;

            if (config.Globals.SeedNodes.Count > 0 && options.BasePort < 0)
            {
                config.PrimaryNode = config.Globals.SeedNodes[0];
            }
            else
            {
                config.PrimaryNode = new IPEndPoint(IPAddress.Loopback, basePort);
            }
            config.Globals.SeedNodes.Clear();
            config.Globals.SeedNodes.Add(config.PrimaryNode);

            if (!String.IsNullOrEmpty(DeploymentId))
            {
                config.Globals.DeploymentId = DeploymentId;
            }
            config.Defaults.PropagateActivityId = options.PropagateActivityId;
            if (options.LargeMessageWarningThreshold > 0)
            {
                config.Defaults.LargeMessageWarningThreshold = options.LargeMessageWarningThreshold;
            }

            config.Globals.LivenessType = options.LivenessType;

            globalConfig = config.Globals;

            string siloName;

            switch (type)
            {
            case Silo.SiloType.Primary:
                siloName = "Primary";
                break;

            default:
                siloName = "Secondary_" + InstanceCounter.ToString(CultureInfo.InvariantCulture);
                break;
            }

            NodeConfiguration nodeConfig = config.GetConfigurationForNode(siloName);

            nodeConfig.HostNameOrIPAddress = "loopback";
            nodeConfig.Port = basePort + InstanceCounter;
            nodeConfig.DefaultTraceLevel   = config.Defaults.DefaultTraceLevel;
            nodeConfig.PropagateActivityId = config.Defaults.PropagateActivityId;
            nodeConfig.BulkMessageLimit    = config.Defaults.BulkMessageLimit;

            config.Globals.ExpectedClusterSize = 2;

            config.Overrides[siloName] = nodeConfig;

            InstanceCounter++;

            Console.WriteLine("Starting a new silo in app domain {0} with config {1}", siloName, config.ToString(siloName));
            AppDomain appDomain;
            Silo      silo = _LoadSiloInNewAppDomain(siloName, type, config, out appDomain);

            silo.Start();

            SiloHandle retValue = new SiloHandle
            {
                Name      = siloName,
                Silo      = silo,
                Options   = options,
                Endpoint  = silo.SiloAddress.Endpoint,
                AppDomain = appDomain,
            };

            return(retValue);
        }