Exception in the constructor EnterpriseLibraryContainer.Current.GetInstance<Autoscaler>

Topics: Windows Azure Integration Pack
Oct 17, 2012 at 3:03 PM

Hi,

I have followed the next how to: https://www.windowsazure.com/en-us/develop/net/how-to-guides/autoscaling/

 I have the following exception when I call the constructor:

Autoscaler scaler = EnterpriseLibraryContainer.Current.GetInstance();
Exception:{"Activation error occured while trying to get instance of type Autoscaler, key \"\""}

 InnerException:

{"Resolution of the dependency failed, type = \"Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Autoscaler\", name = \"(none)\".\r\nException occurred while: Calling constructor Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.Configuration.LocalXmlFileRulesStore(System.String fileName, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Logging.ILogger logger, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Security.IProtectedXmlProvider protectedXmlProvider, System.Collections.Generic.IEnumerable`1[[Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.Configuration.IRuleSerializationExtension, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] extensions).\r\nException is: ArgumentException - Directory does not exist\r\nParameter name: fileName\r\n-----------------------------------------------\r\nAt the time of the exception, the container was:\r\n\r\n  Resolving Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Autoscaler,Autoscaler.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Autoscaler, (none))\r\n  Resolving parameter \"rulesStore\" of constructor Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Autoscaler(System.String dataPointsStoreStorageAccountConnectionString, System.String dataPointsTableName, System.TimeSpan ruleEvaluationRate, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.IRulesStore rulesStore, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.ServiceModel.IServiceInformationStore serviceInformationStore, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.DataPointsCollection.IDataPointsCollectorsProvider dataPointsCollectorsProvider, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.IExecutionLease executionLease, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Logging.ILogger logger, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Scaling.IServiceManagementRequestTracker tracker, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Scaling.IScaler scaler)\r\n    Resolving Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.Configuration.LocalXmlFileRulesStore,IRulesStore.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.IRulesStore, (none))\r\n    Calling constructor Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.Configuration.LocalXmlFileRulesStore(System.String fileName, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Logging.ILogger logger, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Security.IProtectedXmlProvider protectedXmlProvider, System.Collections.Generic.IEnumerable`1[[Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.Configuration.IRuleSerializationExtension, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] extensions)\r\n"}

InnerException: {"Directory does not exist\r\nParameter name: fileName"}

StackTrace:

   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides)
   at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
   at Microsoft.Practices.Unity.UnityServiceLocator.DoGetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 49

 

Oct 17, 2012 at 4:36 PM

Hi,

I have changed my config to use the services and rules files from storage. Now I don´t have this exception, but I don´t have any information in the console, and I have to put a "System.Console.Read()" for keeping the console running. Something may be wrong, so I´m posting my config file and my rules and services file. The application is a mvc webform for introduce message in queue, so I define a custom performance counter, which I increase in my MVC when I insert messages, or decrease if I delete. I´m trying to autoscale a worker role which actually do nothing. This is just for lab purpouse.

Console:

class Program
    {
        static void Main(string[] args)
        {
           Autoscaler scaler = EnterpriseLibraryContainer.Current.GetInstance<Autoscaler>();
           scaler.Start();

           System.Console.ReadKey();
        }
    }

Rules File:

<?xml version="1.0" encoding="utf-8" ?>
<rules xmlns="http://schemas.microsoft.com/practices/2011/entlib/autoscaling/rules">
  <constraintRules>
    <rule name="default" enabled="true" rank="1" description="The default constraint rule">
      <actions>
        <range min="1" max="3" target="AutoscalingApplicationRole"/>
      </actions>
    </rule>
  </constraintRules>
  <reactiveRules>
    <rule name="ScaleUpOnHighUtilization" rank="10" description="Scale up the worker role" enabled="true" >
      <when>
        <any>
          <greaterOrEqual operand="QueueSize" than="50"/>
        </any>
      </when>
      <actions>
        <scale target="AutoscalingApplicationRole" by="1"/>
      </actions>
    </rule>
    <rule name="ScaleDownOnLowUtilization" rank="10" description="Scale up the web role" enabled="true" >
      <when>
        <all>
          <less operand="QueueSize" than="50"/>
        </all>
      </when>
      <actions>
        <scale target="AutoscalingApplicationRole" by="-1"/>
      </actions>
    </rule>
  </reactiveRules>
  <operands>
    <performanceCounter alias="QueueSize"
      performanceCounterName="\MyCustomCounterCategory\Queue Size"
      source ="AutoscalingApplicationRole"
      timespan="00:05:00" aggregate="Average"/>
  </operands>
</rules> 

Services File
 
<?xml version="1.0" encoding="utf-8" ?>
<serviceModel xmlns="http://schemas.microsoft.com/practices/2011/entlib/autoscaling/serviceModel">
  <subscriptions>
    <subscription name="3-Month Free Trial"
                  certificateThumbprint="3EB34E2951033D62EA5B0ED61C84E35C1C5FD177"
                  subscriptionId="d14a60fd-a8fd-43dc-a195-cb3b771e2a95"
                  certificateStoreLocation="CurrentUser"
                  certificateStoreName="My">
      <services>
        <service dnsPrefix="jfavmtesting" slot="Production">
          <roles>
            <role alias="AutoscalingApplicationRole"
                  roleName="AutoScallingWorker"
                  wadStorageAccountName="targetstorage"/>
          </roles>
        </service>
      </services>
      <storageAccounts>
        <storageAccount alias="targetstorage"
          connectionString="DefaultEndpointsProtocol=https;AccountName=solidazurelabs2012;AccountKey=N1i0niN+b1MyAi4FNaGJKuFHElHno5rpmKniJH9fghbNNw00lfbkidOSx1iheiIwHwb426pU3S1u+AGvhvv5Tw==">
        </storageAccount>
      </storageAccounts>
    </subscription>
  </subscriptions>
</serviceModel>



APP.Config

<configuration>
    <configSections>
    <section name="autoscalingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Configuration.AutoscalingSettings, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    <section name="typeRegistrationProvidersConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.TypeRegistrationProvidersConfigurationSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>


<autoscalingConfiguration dataPointsStoreAccount="DefaultEndpointsProtocol=https;AccountName=solidazurelabs2012;AccountKey=N1i0niN+b1MyAi4FNaGJKuFHElHno5rpmKniJH9fghbNNw00lfbkidOSx1iheiIwHwb426pU3S1u+AGvhvv5Tw=="
    loggerName="System Diagnostics Logger" rulesStoreName="Blob Rules Store"
    serviceInformationStoreName="Blob Service Information Store">
    <loggers>
        <add name="System Diagnostics Logger" type="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Logging.SystemDiagnosticsLogger, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </loggers>
    <rulesStores>
        <add name="Blob Rules Store" type="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.Rules.Configuration.BlobXmlFileRulesStore, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            blobContainerName="autoscaling" blobName="rules.xml" storageAccount="DefaultEndpointsProtocol=https;AccountName=solidazurelabs2012;AccountKey=N1i0niN+b1MyAi4FNaGJKuFHElHno5rpmKniJH9fghbNNw00lfbkidOSx1iheiIwHwb426pU3S1u+AGvhvv5Tw=="
            monitoringRate="00:00:30" certificateThumbprint="3EB34E2951033D62EA5B0ED61C84E35C1C5FD177"
            certificateStoreName="My" />
    </rulesStores>
    <serviceInformationStores>
        <add name="Blob Service Information Store" type="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling.ServiceModel.Configuration.BlobXmlFileServiceInformationStore, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            blobContainerName="autoscaling" blobName="service.xml" storageAccount="DefaultEndpointsProtocol=https;AccountName=solidazurelabs2012;AccountKey=N1i0niN+b1MyAi4FNaGJKuFHElHno5rpmKniJH9fghbNNw00lfbkidOSx1iheiIwHwb426pU3S1u+AGvhvv5Tw=="
            monitoringRate="00:00:30" certificateThumbprint="3EB34E2951033D62EA5B0ED61C84E35C1C5FD177" />
    </serviceInformationStores>
    <advancedOptions>
        <serviceManagementRequestTracker trackServiceManagementRequests="false" />
        <executionLease useBlobExecutionLease="false" />
    </advancedOptions>
</autoscalingConfiguration>
<typeRegistrationProvidersConfiguration>
    <remove name="Caching" />
    <add sectionName="cachingConfiguration" name="Caching" />
    <remove name="Cryptography" />
    <add sectionName="securityCryptographyConfiguration" name="Cryptography" />
    <remove name="Exception Handling" />
    <add sectionName="exceptionHandling" name="Exception Handling" />
    <remove name="Instrumentation" />
    <add sectionName="instrumentationConfiguration" name="Instrumentation" />
    <remove name="Logging" />
    <add sectionName="loggingConfiguration" name="Logging" />
    <remove name="Policy Injection" />
    <add sectionName="policyInjection" name="Policy Injection" />
    <remove name="Security" />
    <add sectionName="securityConfiguration" name="Security" />
    <remove name="Data Access" />
    <add providerType="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSyntheticConfigSettings, Microsoft.Practices.EnterpriseLibrary.Data"
        name="Data Access" />
    <remove name="Validation" />
    <add providerType="Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidationTypeRegistrationProvider, Microsoft.Practices.EnterpriseLibrary.Validation"
        name="Validation" />
    <add sectionName="autoscalingConfiguration" name="autoscalingConfiguration" />
</typeRegistrationProvidersConfiguration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
  <system.diagnostics>
    <sources>
      <source name="Autoscaling General" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch" >
      <listeners>
        <add name="console" />
        <remove name ="Default" />
      </listeners>
      </source>
      <source name="Autoscaling Updates" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch" >
        <listeners>
          <add name="console" />
          <remove name ="Default" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="SourceSwitch" value="Verbose, Information, Warning, Error, Critical" />
    </switches>
  </system.diagnostics>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <qualifyAssembly partialName="Microsoft.Practices.EnterpriseLibrary.Data" fullName="Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <qualifyAssembly partialName="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling" fullName="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.Autoscaling, Version=5.0.1118.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </assemblyBinding>
  </runtime>
</configuration>

 

 

Editor
Oct 18, 2012 at 6:41 AM

Have you added the management certificate (.pfx) to the off premise certificate store?

What output are you seeing from the block?  It looks like you have configured a console trace listener but I don't see a shared listener defined in the config:

<system.diagnostics>    
... 
   <sharedListeners>
      <add name="console" type="System.Diagnostics.ConsoleTraceListener" />
    </sharedListeners>
... 
</system.diagnostics>

Also, I think Console.ReadKey() will block the console trace listener output.  Instead use something like:

scaler = EnterpriseLibraryContainer.Current.GetInstance<Autoscaler>();
scaler.Start();

while (true)
{
    System.Threading.Thread.Sleep(10000);
}

If you are monitoring Azure queue lengths, there is an operand already defined for that so you might not have to use performance counters.  See Defining Reactive Rules.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Oct 18, 2012 at 9:56 AM

Hi Randy,

I did what you say and it not working. But I have to say that yesterday, with the same config I had one instance scaled up. The problem with the Host Application Console is that I don´t get any message. If there is any lab or demo similar to this?

Thanks

Oct 18, 2012 at 9:58 AM

About the certificate, I had it yesterday, and I get a message a minute later than I run the Host Console APP, that one application is trying to Access to the a key, it gives me the option to Grant or Deny. I supose that it is the Access to the certificate.

Oct 18, 2012 at 6:18 PM

Hi Randy,

I do scale up one role, but I was running a worker locally and in cloud as Host Worker. I´m confused with the parameter in service file of certificate "CERTIFICATE STORE LOCATION"

I think that in cloud must be "LocalMachine", I upload the certificate though the portal. But In local I think that I have the certificate in "CurrentUser". When the role was scaled up, It was set up to "CurrentUser", so I think that the worker which did it was the local.

Can you explain me a Little bit of this?

Thanks.

Editor
Oct 18, 2012 at 11:47 PM

This article has a good description and diagram of the certificate deployment.  This describes it well:

The Autoscaling Application Block must be able to access the roles in the application that it is managing. The block reads the information that it needs to access the target application from the service information configuration. The block requires the subscription ID of the Windows Azure subscription that hosts the target application, and a management certificate that it can use to connect to the subscription. You must add these pieces of information to the service information.

So, you need access to the management certificate to scale Windows Azure.  If you are using an off premises console application (or service) then you would install the certificate in the local certificate store ("CurrentUser", "My") and if you are hosting the Autoscaling Application Block in a worker role then the certificate will have to deployed into the hosted service role.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Oct 22, 2012 at 8:36 PM

Hi Randy,

Many thanks, I finally solved on friday :D

It is amazing the behaviour. It Works perfect!!!

Oct 23, 2012 at 6:36 AM

Hello.

It works when in the console application there is a reference to WindowsAzure.StorageClient.dll file from Azure SDK 1.6. Under Azure SDK 1.7 environment there is error message: Activation error occured while trying to get instance of type Autoscaler, key "". In details we have: Could not load file or assembly 'Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040).

My Web Role is under Azure SDK 1.7. How to ensure Autoscaler to work under the current Azure environment? In my project the WindowsAzure.StorageClient.dll (Version 1.7.0.0) is already referenced. My Web Role does not work at all if the reference is changed to WindowsAzure.StorageClient.dll (Version=1.1.0.0).

Editor
Oct 23, 2012 at 11:51 AM

A binding redirect will solve the issue:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.WindowsAzure.StorageClient"
                          publicKeyToken="31bf3856ad364e35"
                          culture="neutral" />
        <bindingRedirect oldVersion="1.1.0.0"
                         newVersion="1.7.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Oct 25, 2012 at 12:41 PM

I have deployed Autoscaler in WorkerRole. The rules-store.xml and service-information-store.xml files are in Blob. The Autoscaler checks the WebRole performance counter (requests per second). The Autoscaler logs in WADLogs table are fine. In AutoscalerDatapoints table the items are created (number of instances and performance counter value). I have WebRole calls from another application so that WebRole performance counter value exceeds the threshold value. The problem is the number of WebRole instances is not changed.
If I connect to the WorkerRole instance remotely and start console application then Autoscaler ensures correct number of WebRole instances. What is wrong?
Ps. Only in one WorkerRole instance the Autoscaler is started.
The code from WorkerRole Run is below:
if ((scaler == null) && (RoleEnvironment.CurrentRoleInstance.Id.IndexOf("ServicesWorkerRole_IN_0") >= 0))
            {
                try
                {
                    Trace.WriteLine("Worker Role Autoscaler starting", "Information");
                    scaler = EnterpriseLibraryContainer.Current.GetInstance<Autoscaler>();
                    scaler.Start();
                    Trace.WriteLine("Worker Role Autoscaler is started", "Information");
                }
                catch (Exception e)
                {
                    Trace.TraceError(string.Format("Worker Role Autoscaler start issue: '{0}'", e.Message));
                }
            }

 In Logs:  Worker Role Autoscaler is started. RoleInstance=ServicesWorkerRole_IN_0

Oct 26, 2012 at 6:16 AM

I have redeployed solution without taking care about Autoscaler creating&starting only in one WorkerRole instance. Now it works: the Autoscaler ensures the correct number of WebRole instances. Is it fine to start Autoscaler on all Role instances?

Now I want to deploy Autoscaler within WebRole so that is will autoscale itself. How to create and start Autoscaler? It would be better to start it automatically during deployment and avoid manual starting. 

Editor
Oct 31, 2012 at 7:19 AM

You can start the Autoscaler on all role instances but you must enable leases so that only one Autoscaler is active at a time.  So you need to ensure that you call Stop.  From Usage Notes of Hosting the Autoscaling Application Block in a Worker Role:

If you have multiple instances of your worker role, then the Autoscaler class can use a lease on a Windows Azure blob to ensure that only a single instance of the Autoscaler can execute the autoscaling rules at any one time. See the topic "Entering Configuration Information" for more details.  The default setting is that the lease is not enabled. If you are planning to run multiple instances of the worker role that hosts the Autoscaling Application Block, you must enable the lease.  It is important to call the Stop method in the Autoscaler class when the worker stops. This ensures that the block releases its lease on the blob before the role instance stops.

If you are hosting in the same role as the application then the Start method should be called from the Run method of the role.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com