Azure - как устранить неполадки при развертывании

У меня есть рабочая роль, которой не удается развернуть (циклы между инициализацией и прерванным) в консоли управления. Он отлично работает в эмуляторе.

Несчастье заключается не в том, что развертывание завершается неудачей, а в том, что кажется практически невозможным выяснить, почему.

Я проверил все строки подключения, включил диагностику, проверил все мои сборки, развернул ALOT и потерял некоторые волосы.

Точка, в которой я сейчас участвую, заключается в том, что я по-прежнему добавляю код по-разному и перераспределяю, чтобы найти код, который терпит неудачу, процесс, который смехотворно медленный.

Сам работник подключается к sql azure и azure storage. У меня есть соединение с живыми конечными точками в эмуляторе без каких-либо проблем.

Кажется, что он сработает, как только я настрою StructureMap (IoC). Тем не менее, я использую почти идентичный код в своей веб-роли, и это отлично работает.

Итак, где я могу идти отсюда (кроме бутылки)?

Ответ 1

Я собираюсь начать с повторного повторения обратной связи, которую вы получили до сих пор. Самый большой убийца - это процесс Run() в WorkerRole. Если у WorkerRole возникли проблемы с запуском, вы можете обернуть код внутри этого метода с помощью try/catch и зарегистрировать его.

Если вы решите использовать встроенную диагностику, я бы рекомендовал прочитать блог Райана Данна, а также блог smarx. Оба имеют протекцию на этом основании и прекрасно выполняют документацию/обмен информацией по ходу дела. Сайт MSDN (извините, первый ответ, так что только две ссылки:)) также немного улучшился в этой теме.

Часть, которую я добавлю к этому разговору, находится в том, КАК вы следуете совету. Я не использую Intellitrace, поскольку у меня нет доступа к нему, и прибегнув к настройке удаленного рабочего стола (может быть сделано из Visual Studio) для моих ролей при ударе по стене. Если вы настроите log4net или что-то подобное, (локально для роли), вы сможете войти в систему через RDP и прочитать журналы.

Теперь, две вещи, которые мы находим наиболее часто.

  • UseDevelopmentStorage = True - это параметр по умолчанию и может создавать проблемы при развертывании. На этом уже написано немного.

  • Зависимости. Есть много вещей, которые разработчики имеют доступ к тем, которые не находятся в роли Hosted. Самый простой пример этого, IMO, - это ASP.NET MVC. Вы можете либо использовать философию "Стабильный выпуск", либо использовать что-то вроде командной строки установщика веб-платформы (там также "Лазурный боустраппер" в блоге dunnry), чтобы подготовить роль перед запуском.

Для меня ключ - это RDP, так как вы действительно можете войти в систему и посмотреть, что происходит.

UPDATE - Не могу поверить, что я забыл об этом, так как он убивает меня все время, но вам также может понадобиться настроить брандмауэр при использовании SQL Azure. В процессе dev мы часто будем разрушать и повторно развертывать наши роли вместо обновления и приводить к случайным изменениям IP-адреса. Если они не настроены в брандмауэре, где задействован SQL Azure, может возникнуть проблема.

Надеюсь, это поможет человеку.

Ответ 2

Хорошо бы вы поверили, это была недостающая сборка в роли рабочего. Мой совет любому, кто сталкивается с подобными проблемами, - это одинарная, двойная и тройная проверка всех ваших зависимостей.

Ответ Microsoft должен был использовать Intellitrace, но если вы не хотите распространять обновления для VS, вы можете использовать AsmSpy (очень мало полезности Майка Хэдлоу).

Это то, что в конечном итоге позволило мне найти, что одна из моих зависимостей в рабочей роли зависела от asp.net mvc! Этого не должно было быть, стыдно, что мне так долго приходилось искать.

В дополнение к советам по превосходству, которыми делится Майк выше, вот некоторые дополнительные, которые нужно искать:

  • Убедитесь, что вы используете конечную точку https для диагностики
  • Отсутствует сборка (просто повторить). У меня также возникла проблема с NHibernate 3.1, где сборка прокси factory не была скопирована в выходной путь (даже с копией local = true). Пришлось скопировать это вручную (NHibernate.Bytecode.Castle)

Здесь код, который я использую для записи журналов в хранилище Azure:

#region Setup diagnostics

DiagnosticMonitorConfiguration diagnosticsConfig
    = DiagnosticMonitor.GetDefaultInitialConfiguration();

// Windows event logs
diagnosticsConfig.WindowsEventLog.DataSources.Add("System!*");
diagnosticsConfig.WindowsEventLog.DataSources.Add("Application!*");
diagnosticsConfig.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Warning;
diagnosticsConfig.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);

// Windows Azure logs
diagnosticsConfig.Logs.ScheduledTransferLogLevelFilter = LogLevel.Warning;
diagnosticsConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);

DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", diagnosticsConfig);

#endregion Setup diagnostics

Вы можете настроить журналы Azure ScheduledTransferLogLevelFilter на Undefined, чтобы регистрировать все отправленные слушателям Trace.

Я использую интерфейс ILogger для ведения журнала во всем моем приложении, поэтому я просто написал тот, который назвал Trace.WriteLine, чтобы любые исключения были записаны в хранилище Azure.

Одна из проблем для меня заключалась в том, что даже после обертывания всего в огромном блоке catch try исключение, созданное во время инициализации StructureMap, было не очень полезно.

Я добавил следующий метод расширения для моего регистратора, чтобы получить внутреннее исключение. Именно это привело к тому, что я увидел недостающую проблему сборки MVC и этот классический момент ладони.

    public static string BuildExceptionMessage(this ILogger logger, Exception x)
    {
        var logException = x;
        while (logException.InnerException != null)
        {
            logException = logException.InnerException;
        }

        var errorMessage = string.Empty;

        if (HttpContext.Current != null) 
        {              
            errorMessage = Environment.NewLine + "Error in Path :" + System.Web.HttpContext.Current.Request.Path;

            // Get the QueryString along with the Virtual Path
            errorMessage += Environment.NewLine + "Raw Url :" + System.Web.HttpContext.Current.Request.RawUrl;
        }

        // Get the error message
        errorMessage += Environment.NewLine + "Message :" + logException.Message;

        // Source of the message
        errorMessage += Environment.NewLine + "Source :" + logException.Source;

        // Stack Trace of the error

        errorMessage += Environment.NewLine + "Stack Trace :" + logException.StackTrace;

        // Method where the error occurred
        errorMessage += Environment.NewLine + "TargetSite :" + logException.TargetSite;

        return errorMessage;
    }

Я надеюсь, что это поможет некоторым другим.