Запуск собственного кода в Azure

#azure

#azure

Вопрос:

Я пытаюсь запустить исполняемый файл на C в Azure. У меня много рабочих ролей, и они постоянно проверяют очередь заданий. Если в очереди есть задание, рабочая роль запускает экземпляр исполняемого файла C как процесс в соответствии с аргументами командной строки, хранящимися в классе заданий. Исполняемый файл C обычно создает некоторые файлы журнала. Я не знаю, как получить доступ к этим созданным файлам. Какова логика, стоящая за этим? Где хранятся созданные файлы? Кто-нибудь может мне объяснить? Я новичок в Azure и C #.

Еще одна проблема заключается в том, что всем рабочим экземплярам исполняемого файла C необходимо прочитать файл данных. Как я могу распространить этот требуемый файл?

Ответ №1:

Во-первых, поймите, что в Windows Azure ваша рабочая роль просто выполняется в среде Windows 2008 Server (либо SP2, либо R2). При развертывании вашего приложения вы также должны развернуть исполняемый файл на C (или извлечь его из хранилища больших двоичных объектов, но это немного сложнее). Чтобы узнать, где находится ваше приложение на диске, вызовите Environment.GetEnvironmentVariable("RoleRoot") — это возвращает путь. Обычно ваше приложение находится в папке с именем AppRoot в корневом каталоге роли. Вы бы нашли там свой исполняемый файл на C.

Далее вы захотите, чтобы ваше приложение записывало свои файлы в выходной каталог, указанный вами в командной строке. Вы можете настроить хранилище на своей локальной виртуальной машине с помощью свойств вашей роли. Посмотрите на вкладку «Локальное хранилище» и настройте именованную область локального хранилища:

введите описание изображения здесь

Теперь вы можете получить путь к этой области хранения в коде и передать его в качестве аргумента командной строки:

 var outputStorage = RoleEnvironment.GetLocalResource("MyLocalStorage");
var outputFile = Path.Combine(outputStorage.RootPath, "myoutput.txt");
var cmdline = String.Format("--output {0}", outputFile);
  

Вот пример запуска вашего myapp.exe процесс с аргументами командной строки:

 var appRoot = Path.Combine(Environment.GetEnvironmentVariable("RoleRoot")
              @"", @"approot");

var myProcess = new Process()
{
   StartInfo = new ProcessStartInfo(Path.Combine(appRoot, @"myapp.exe"), cmdline)
   {
      CreateNoWindow = false,
      UseShellExecute = false,
      WorkingDirectory = appRoot
   }
};
myProcess.WaitForExit();
  

Обычно для CreateNoWindow устанавливается значение true, но его легче отлаживать, если вы можете видеть окно командной оболочки.

И последнее: как только ваше приложение завершит создание файла, вы захотите либо:

  • Обработайте его и удалите (он не находится в надежном месте, поэтому в конечном итоге он исчезнет)
  • Измените свое хранилище на использование облачного диска (долговременное хранилище)
  • Скопируйте ваш файл в большой двоичный объект (долговременное хранилище)

В рабочей среде вам потребуется добавить обработку исключений, и вы можете перенаправить stdout и stderr для записи. Но этого примера кода должно быть достаточно, чтобы вы начали.

УПС — еще одна «еще одна вещь»: при добавлении вашего ‘myapp.exe ‘ для вашего проекта обязательно перейдите в его свойства и установите для параметра «Копировать в выходной каталог» значение «Копировать всегда» — в противном случае ваш myapp.exe файл не попадет в Windows Azure, и вы будете удивляться, почему что-то не работает.

РЕДАКТИРОВАТЬ: Передача результатов в большой двоичный объект — краткий пример

Сначала настройте учетную запись хранилища и добавьте в настройки своей роли. Допустим, вы назвали его «AzureStorage» — теперь настройте его в коде, получите ссылку на контейнер больших двоичных объектов, получите ссылку на большой двоичный объект внутри этого контейнера, а затем выполните загрузку файла в большой двоичный объект:

         CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("AzureStorage");
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer outputfiles = blobClient.GetContainerReference("outputfiles");
        outputfiles.CreateIfNotExist();

        var blobname =  "myoutput.txt";
        var blob = outputfiles.GetBlobReference(blobname);
        blob.UploadFile(outputFile);
  

Комментарии:

1. Спасибо. Можете ли вы также объяснить мне, как собирать созданные файлы из локального хранилища? Каждый рабочий может скопировать созданный файл в большой двоичный объект. Затем какая-либо другая рабочая роль или клиентское приложение могут получить доступ к этому двоичному объекту, верно?

2. Смотрите обновленный ответ для краткого примера переноса выходного файла в большой двоичный объект. Опять же, вам понадобится обработка исключений и т.д. Я рекомендую загрузить учебный комплект для платформы Windows Azure, чтобы получить более подробную информацию — там есть отличные учебные пособия и практические лабораторные работы.

3. это отличный ответ, и я многому научился из этой темы; но единственная проблема, с которой я в настоящее время сталкиваюсь, заключается в создании выходного файла. в ответе Дэвида предполагается наличие флага «—output» для указания выходного файла. что, если флага нет? есть альтернатива использованию process.standardoutput также для получения выходных данных в виде потока, но я предпочитаю использовать операторы перенаправления командного вывода «>», «>>» и т.д., Если это возможно. итак, вопрос в следующем: возможно ли использование оператора cmd? спасибо за дополнительную информацию.

Ответ №2:

На территории Azure не следует выполнять запись в файловую систему. Вы должны написать в SQL Azure, хранилище таблиц или, скорее всего, в данном случае хранилище больших двоичных объектов (в принципе, я думаю, вы должны думать о хранилище больших двоичных объектов как о старой файловой системе)

Это потому, что:

  1. У вас может быть запущено несколько экземпляров, и в конечном итоге у вас будут разные файлы на разных экземплярах (которые являются просто виртуальными машинами)

  2. Ваш экземпляр потенциально может быть перемещен в любой момент, и вы потеряете информацию о файловой системе, поскольку она не является частью вашего пакета развертывания.

Использование одного из трех вариантов хранилища предоставит доступ ко всем вашим экземплярам к центральному хранилищу, которое будет сохраняться при повторном развертывании.

Комментарии:

1. На самом деле это не так. У вас есть как недолговечное, так и долговременное файловое хранилище для записи. Смотрите мой ответ (через мгновение) для получения более подробной информации.

2. надежное хранилище файлов — это хранилище больших двоичных объектов?

3. Да — примерно за 10 строк кода вы можете смонтировать том NTFS в качестве облачного диска. Выглядит точно так же, как буква диска вашего приложения.

4. Но полностью согласен с локальным файловым хранилищем — оно отлично подходит для временного хранения. В примере, который я показал выше, идея заключалась бы в том, чтобы позволить приложению генерировать выходные данные, а затем что-то делать с этим выводом (копировать его в большой двоичный объект, обрабатывать / анализировать его, что угодно) и не рассчитывать на то, что он навсегда останется в локальном хранилище. Я часто использую локальное хранилище для обработки / вывода — это очень удобно и позволяет многим сторонним приложениям работать без изменений.