Статьи

Использование Amazon SimpleDB для сбора метрик использования приложений в облаке


Я работаю в команде, которая отвечает за настольное приложение для Windows, которое позволяет отображать и обрабатывать медицинские изображения.
Медицинские изображения — это то, что вы себе представляете: рентген, ультразвук, МРТ, компьютерная томография и т. Д.

Эти изображения большие — сотни мегабайт (больше для ультразвукового видео) — и в этом заключается одна из наших больших проблем: высокая производительность для пользователей во всем мире.
И многие из наших пользователей сидят в Южной Индии или Европе, в то время как наши изображения находятся в центре обработки данных на восточном побережье Америки.

Теперь, когда у нас есть роскошные большие трубы, соединяющие эти места, они неизбежно страдают от довольно высокой задержки (~ 300 мс для Индии) из-за физического расстояния между ними.
Этот уровень задержки и TCP
не очень хорошо сочетаются .

Это приводит к очень разочаровывающей скорости пропускной способности даже при наличии достаточной пропускной способности.
Улучшение этой ситуации можно свести к применению всего лишь трех методов:
  1. Переместить данные быстрее
  2. Переместить меньше данных
  3. Переместите данные, прежде чем они вам понадобятся
        Для нас возможность перенести данные до того, как они были необходимы, уже не обсуждалась. Предварительное кэширование данных изображений — это подход, который мы использовали в течение многих лет с устаревшим продуктом. Хотя он работал довольно хорошо, он был далеко не прозрачен для конечных пользователей. С некоторой регулярностью данные, которые люди ожидали получить от удаленных пользователей, не делали это своевременно, и за этим последовало большое скрежетание зубами и подача билетов в службу поддержки. Кэширование было, так сказать, четырехбуквенным словом.

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

На самом деле, эта
статья о том, как мы использовали
SimpleDB на основе облака Amazon в качестве сверхпростого средства для сбора метрик в полевых условиях производительности и использования нашего приложения.

На нашей самой ранней пилотной фазе мы отображали время загрузки и пропускную способность в строке состояния приложения, и пользователи, очевидно, могли передавать эту информацию нам (да, это было неудовлетворительно, как кажется).
И, конечно же, было в равной степени возможно регистрировать вещи на компьютере пользователя, например, с помощью Log4Net или с помощью журнала событий Windows. Но такой подход делает доступ к захваченным данным и их консолидацию немного более сложным, чем мы хотели. Поэтому, хотя это не значит, что мы не могли бы получить эти данные без облачного решения, ясно, что какой-то один централизованный захват этих данных был привлекательным вариантом.

Один из способов, которым мы могли бы получить централизованные средства для сбора этих данных, — это создать небольшую базу данных, создать для нее набор веб-сервисов и использовать ее.
Но усилия, связанные с выполнением и развертыванием, как и во многих организациях, нетривиальны, и мы стремились внедрить эту функциональность как можно скорее.

Для сравнения, Amazon SimpleDB — это просто.

Это «без схемы», поэтому нет никаких DDL для создания таблиц и так далее.
Вместо этого данные хранятся в доменах (схожих с таблицами; их нужно создавать заранее), состоящих из элементов (как строки) в виде набора атрибутов (немного похожего на столбец, но лучше воспринимаемого как имя пары-значения).

Но достаточно английского, вот немного C #, чтобы показать, насколько легко можно сохранить некоторые данные в SimpleDB.
На самом деле это может быть даже проще, так как здесь я использую асинхронный подход для ввода данных.
 
       private void LogMetricToCloud(IMetric metric)
        {
            string domain = metric.GetType().FullName;
            CreateDomainIfNeeded(domain);

            try
            {              
                PutAttributesRequest request = new PutAttributesRequest()
                    .WithDomainName(domain)
                    .WithItemName(Guid.NewGuid().ToString());

                foreach(var attribute in metric.Attributes())
                {
                    request.WithAttribute(new ReplaceableAttribute()
                        .WithName(attribute.Name)
                        .WithValue(attribute.Value));
                }

                string state = metric.GetType().FullName + ":" + metric.CSVData();
                IAsyncResult asyncResult = _db.BeginPutAttributes(request, new
AsyncCallback(SimpleDBCallBack), state);
            }
            catch (Exception e)
            {
                TryLogError(e.Message);
            }
        }

        private void SimpleDBCallBack(IAsyncResult result)
        {
            string state = result.AsyncState as string;
            try
            {
                // If there was an error during the put attributes operation it will be
thrown as part of the EndPutAttributes method.
                _db.EndPutAttributes(result);
            }
            catch (Exception e)
            {
                TryLogError(string.Format("Exception: {0}\nFailed to log: {1}", e.Message,
state));
            }
        }


Я думаю, что то, что делает код и как, самоочевидно, но это может быть просто потому, что я работал с ним.
Просто чтобы убедиться, что это ясно, вот разбивка:
  • У меня есть несколько различных классов метрики, все в соответствии с  интерфейсом IMetric 
  • У меня есть домен (думаю: таблица) для каждого вида метрики
  • В качестве конкретного примера, одна из моих метрик измеряет использование функции; особенности такие вещи, как переворачивание и маскировка изображений. Для использования функций я записываю, кто, где, когда, какой проект и какие функции они использовали.
  • Метод  LogMetricToCloud  просто перебирает все атрибуты метрики и создает запрос для сохранения этого в моем экземпляре SimpleDB.
  • Запрос выполняется асинхронно, с творчески названным   методом SimpleDBCallBack, который вызывается после завершения. Вызов здесь  EndPutAttributes  позволит нам узнать, возникли ли какие-либо проблемы с исходным запросом.

Кажется, что все это работает довольно хорошо, и я надеюсь, что в ближайшем будущем мы сможем еще больше использовать SimpleDB.
Следующим в списке для меня является реализация функциональности типа «функция переключения» для нашего приложения. Этим мы можем развить некоторые идеи, описанные в этой
замечательной статье Джеза Хамбла о базовых методах непрерывной доставки.