Русский
Русский
English
Статистика
Реклама

Google app engine

Из песочницы Google Apps Script переносим расписание из таблицы в календарь

22.11.2020 20:18:28 | Автор: admin

Для кого предназначена данная статья


  • Для людей, кто активно пользуется сервисом Google Calendar
  • Для людей, у которых есть файлы таблиц с расписаниями, и которые хотели бы работать с ними более продуктивно всегда иметь ближайшие мероприятия перед глазами, получать уведомления с напоминаниями на почту или push-уведомления
  • Для людей, которым хочется быстро познакомиться с Google Apps Script, понять, что это такое, и где его можно применить

Что понадобится


  • Google-аккаунт
  • Базовые знания JavaScript

1. Создаем таблицу в Google Sheets


Это можно сделать, перейдя на страницу своего Google Drive.



Рис. 1. Правый клик мышью по рабочему пространству открывает контекстное меню, где нужно выбрать "Google Таблицы" "Создать пустую таблицу"


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


  • Название мероприятия
  • Дата мероприятия
  • Время начала
  • Время конца или длительность (впрочем, это необязательно в итоге вы сможете установить какое-нибудь общее дефолтное значение длительности мероприятия, например 1 час, или вовсе сделать мероприятие, длящимся целый день)

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



Рис. 2. Таблица с расписанием


2. Создаем скрипт


2.1. Переходим в редактор скриптов


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



Рис. 3. Скрипт создается, через меню "Инструменты", в котором нужно выбрать пункт "Редактор скриптов"


Скрипты разрабатываются на языке JavaScript. Только что созданный скрипт содержит одну пустую функцию myFunction. Писать код можно в ней, но я предпочту дать ей более осмысленное имя SetCalendar.



Рис. 4. Созданный скрипт, дадим функции осмысленное имя SetCalendar


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


2.2. Разбираемся с отладкой


Часто для отладки скриптов на JavaScript мы выводим различные значения в консоль:


console.log("Hello, world!")

В Google Apps Script логировать значения следует немного иначе. Вместо объекта console следует использовать глобальный объект Logger:


function SetCalendar() {  Logger.log("Hello, world!");}

После запуска скрипта, все выведенные в лог значения можно посмотреть из меню "Вид", выбрав пункт "Журналы" или же по сочетанию клавиш Ctrl+Enter:



Рис. 5. Модальное окно с логами последнего запуска скрипта


2.3. Извлекаем информацию о мероприятиях из таблицы


Сразу небольшой кусок кода


function SetCalendar() {  //Индексы первой строки и первого столбца в таблице с данными  const rowStart = 1;  const colStart = 1;  //Количество строк и столбцов в расписании  const colsCount = 5;  const rowsCount = 67;    //Получаем объект страницы  var sheet = SpreadsheetApp.getActiveSheet();  //Извлекаем данные таблицы в указанных диапазонах  var range = sheet.getRange(rowStart, colStart, rowsCount, colsCount)  var data = range.getDisplayValues();}

Рассмотрим строку 11.


Глобальный объект SpreadsheetApp глобальный объект, содержащий методы, представляющие собой интерфейс для взаимодействия скрипта с приложением Google Sheets.


Первое, что нужно сделать получить объект, представляющий активную (открытую в данный момент) страницу документа. Для этого необходимо вызвать метод getActiveSheet.


Метод возвращает объект sheet.


Далее, нужно получить объект range он представляет собой диапазон ячеек таблицы, из которых мы будем извлекать данные. Это делается путем вызова метода getRange. В качестве параметров передаются:


  • Индекс первой строки диапазона
  • Индекс первого столбца диапазона
  • Количество извлекаемых строк
  • Количество извлекаемых столбцов

Обратите внимание! Индексация строк и столбцов начинается с 1.

Строка 15: мы получаем из выбранного выше диапазона ячеек непосредственно данные путем вызова метода getDisplayValues.


Обратите внимание! Метод getDisplayValues() отдает данные в том виде, в каком он отображается в ячейках таблицы. Например, если ячейка содержит дату, то указанный метод вернет не какое-то внутреннее представление записанной в ячейку даты, а ее представление, которое видит пользователь в ячейке.

2.4. Извлекаем данные из ячеек


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


//Константы-имена для индексов столбцов  const dateCol = 0;  const timeCol = 1;  const typeCol = 2;  const nameCol = 3;  const teacherCol = 4;

Вы можете посмотреть какие столбцы стоят в таблице под данными номерами на рисунке 2.


Объект data представляет набор ячеек с данными, которые были получены. Теперь нужно получить данные из отдельных ячеек.


  for (var i in data)  {    let row = data[i];    let classDate = row[dateCol];    let classPeriod = row[timeCol];    let classType = row[typeCol];    let className = row[nameCol];    let classTeacher = row[teacherCol];    Logger.log("[DATE] " + classDate);    Logger.log("[PERIOD] " + classPeriod);    Logger.log("[TYPE] " + classType);    Logger.log("[NAME] " + className);    Logger.log("[TEACHER] " + classTeacher);    Logger.log("============================================");  }

При использовании цикла for с переменной i по объекту data, переменная i на каждой итерации получает значение целое число, которое является индексом очередной извлеченной из таблицы строки.


Строка 3: обращение к объекту data по индексу i возвращает объект row текущую строку таблицы.


Строки 5-9: мы обращаемся к строке по индексу номеру столбца с интересующими нас данными. Например, row[dateCol] мы из текущей строки получаем дату мероприятия из столбца с индексом dateCol.


В строках 5-9 мы получили из текущей строки данные о дате занятия, времени начала и окончания, типе занятия, названии дисциплины и имени преподавателя.


В конце мы выводим полученные данные в лог, чтобы убедиться, что извлекли данные из таблицы правильно.


2.5. Работа с объединенными ячейками


В результате выполнения предыдущих шагов, мы получаем следующий скрипт


function SetCalendar() {  //Индексы первой строки и первого столбца в таблице с данными  const rowStart = 1;  const colStart = 1;  //Количество строк и столбцов в расписании  const colsCount = 5;  const rowsCount = 8;    //Получаем объект страницы  var sheet = SpreadsheetApp.getActiveSheet();  //Извлекаем данные таблицы в указанных диапазонах  var range = sheet.getRange(rowStart, colStart, rowsCount, colsCount)  var data = range.getDisplayValues();  //Константы-имена для индексов столбцов  const dateCol = 0;  const timeCol = 1;  const typeCol = 2;  const nameCol = 3;  const teacherCol = 4;  for (var i in data)  {    let row = data[i];    let classDate = row[dateCol];    let classPeriod = row[timeCol];    let classType = row[typeCol];    let className = row[nameCol];    let classTeacher = row[teacherCol];    Logger.log("[DATE] " + classDate);    Logger.log("[PERIOD] " + classPeriod);    Logger.log("[TYPE] " + classType);    Logger.log("[NAME] " + className);    Logger.log("[TEACHER] " + classTeacher);    Logger.log("============================================");  }}

Выполним скрипт и посмотрим, что было выведено в лог:



Рис. 6. Не все даты были правильно извлечены из таблицы


Из лога видно, что из первой строки данные были извлечены, а в следующих строках, которые описывают мероприятия того же дня, поле с датой оказалось пустым. Почему так происходит?


Еще раз взглянем на таблицу:



Рис. 7. Даты вписаны в объединенные ячейки


При создании таблицы, дата вписывалась только в первую строчку расписания на конкретную дату. После чего, все ячейки из столбца, относящиеся к одной дате были объединены.


Когда мы двигаемся по строкам таблицы, мы получаем дату не из всех ячеек, которые были объединены в одну, а только из первой.


Немного изменим алгоритм, чтобы корректно извлекать дату из объединенных ячеек:


  let savedDate = "";  for (var i in data)  {    let row = data[i];    let classDate = row[dateCol];        //...    if (classDate.trim() == "")    {      classDate = savedDate;    }    else    {      savedDate = classDate;    }    Logger.log("[DATE] " + classDate);    //...    Logger.log("============================================");  }

Мы вводим дополнительную переменную savedDate в ней храним последнюю прочитанную дату.


При чтении даты из текущей строки. Если прочитанная дата пустая строка, то берем дату из переменной savedDate, иначе обновляем значение переменной savedDate.


2.6. Парсим дату и время из строк


Как было отмечено выше если мы используем метод getDisplayValues(), то значения из таблицы мы получаем в виде строк и ровно так, как они отображаются в ячейках, никаких внутренних представлений данных мы не получаем.


Как будет показано далее, чтобы создать событие в Google Calendar, нужно предварительно создать два объекта класса Date: дату-время начала события, дату-время окончания события.


В рассматриваемой таблице (см. рисунок 2), мы получаем дату занятия в формате dd.mm.yyyy, и временной промежуток, когда занятие длится, в формате hh:mm-hh.mm.


Из этих двух строк, нам нужно получить два объекта Date. Такая задача не касается Google Apps Script, с этим по идее должен справиться хоть сколько-нибудь опытный программист. Поэтому я не буду подробно останавливаться на алгоритме, а лишь приведу код двух JS-функций, которые парсят дату время и возвращают дату-время начала и дату-время окончания занятия.


Поехали:


function extractTime(timeStr, dateStr){  let sepIdx = timeStr.indexOf(":");  let hoursStr = timeStr.substring(0, sepIdx);  let minsStr = timeStr.substring(sepIdx + 1);  sepIdx = dateStr.indexOf(".");  let dayStr = dateStr.substring(0, sepIdx);  let monthStr = dateStr.substring(sepIdx + 1, sepIdx + 3);  sepIdx = dateStr.indexOf(".", sepIdx + 1);  let yearStr = dateStr.substring(sepIdx + 1);  let t = new Date();  t.setHours(parseInt(hoursStr), parseInt(minsStr));  t.setYear(parseInt(yearStr));  t.setMonth(parseInt(monthStr) - 1, parseInt(dayStr));  return t;}function extractPeriod(periodStr, dateStr){  let sepIdx = periodStr.indexOf("-");  let fromStr = periodStr.substring(0, sepIdx);  let toStr = periodStr.substring(sepIdx + 1);  fromStr = fromStr.trim();  toStr = toStr.trim();  return {    from: extractTime(fromStr, dateStr),    to: extractTime(toStr, dateStr)  }}

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


2.7. Создание события в Google Calendar


Сразу небольшой листинг, пояснения будут дальше


let classTimeInfo = extractPeriod(classPeriod, classDate);let classStartTime = classTimeInfo.from;let classEndTime = classTimeInfo.to;let info = "Преподаватель: " + classTeacher + "\nТип занятия: " + classType;var event = (CalendarApp.getCalendarsByName("Учеба"))[0].createEvent(  className,  classStartTime,  classEndTime,  {    description: info  });Utilities.sleep(50);

Строки 1-6: получаем дату-время начала и окончания занятия, а также склеиваем в одну строку всю дополнительную информацию, которая будет записана в описание мероприятия в календаре.


Далее, к интерфейсу сервиса Google Calendar мы обращаемся через методы глобального объекта CalendarApp.


Посредством метода getCalendarsByName мы получаем массив календарей с указанным именем.


Получить объект-календарь можно также посредством метода getDefaultCalendar, тогда событие будет создано в основном календаре. Однако, я советую зайти в веб-версию Google Calendar и создать новый календарь, в который вы будете экспортировать мероприятия. Во-первых, вы получаете возможность скрывать события этого календаря, выделять события отдельным цветом.


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


В данном случае я создал календарь "Учеба", и собираюсь создавать события в нем. Поэтому в коде вызывается метод getCalendarsByName и в качестве параметра передается срока "Учеба".


Метод возвращает массив календарей с указанным названием, поэтому нужно взять из этого массива один элемент, в нашем случае нулевой:


(CalendarApp.getCalendarsByName("Учеба"))[0]

У объекта-календаря необходимо вызывать метод createEvent. В качестве параметров нужно передать следующее:


  • Название мероприятия (в данном случае название дисциплины)
  • Объект Data дата-время начала мероприятия
  • Объект Data дата-время окончания мероприятия
  • Необязательный параметр объект с дополнительными опциями (в данном случае я заполняю одно поле description это описание мероприятия)

Последняя строка в скрипте задержка на 50 миллисекунд. Во время разработки скрипта и отладки я обнаружил, что иногда при выполнении кода выбрасывается исключение, суть которого в том, что Google Calendar не нравятся частые обращения к сервису, и в описании исключения рекомендуется вставить задержку между вызовами методов API календаря.


3. Итоговый скрипт


Ниже приведен полный скрипт, который получился


Обратите внимание! Данный скрипт заточен под структуру таблицы, которая приведена на рисунке 2. Если вы хотите использовать этот скрипт для себя как есть, убедитесь, что ваша таблица с расписанием имеет такую же структуру, или же измените скрипт под свою таблицу.

function extractTime(timeStr, dateStr){  let sepIdx = timeStr.indexOf(":");  let hoursStr = timeStr.substring(0, sepIdx);  let minsStr = timeStr.substring(sepIdx + 1);  sepIdx = dateStr.indexOf(".");  let dayStr = dateStr.substring(0, sepIdx);  let monthStr = dateStr.substring(sepIdx + 1, sepIdx + 3);  sepIdx = dateStr.indexOf(".", sepIdx + 1);  let yearStr = dateStr.substring(sepIdx + 1);  let t = new Date();  t.setHours(parseInt(hoursStr), parseInt(minsStr));  t.setYear(parseInt(yearStr));  t.setMonth(parseInt(monthStr) - 1, parseInt(dayStr));  return t;}function extractPeriod(periodStr, dateStr){  let sepIdx = periodStr.indexOf("-");  let fromStr = periodStr.substring(0, sepIdx);  let toStr = periodStr.substring(sepIdx + 1);  fromStr = fromStr.trim();  toStr = toStr.trim();  return {    from: extractTime(fromStr, dateStr),    to: extractTime(toStr, dateStr)  }}function SetCalendar() {  //Индексы первой строки и первого столбца в таблице с данными  const rowStart = 1;  const colStart = 1;  //Количество строк и столбцов в расписании  const colsCount = 5;  const rowsCount = 8;    //Получаем объект страницы  var sheet = SpreadsheetApp.getActiveSheet();  //Извлекаем данные таблицы в указанных диапазонах  var range = sheet.getRange(rowStart, colStart, rowsCount, colsCount)  var data = range.getDisplayValues();  //Константы-имена для индексов столбцов  const dateCol = 0;  const timeCol = 1;  const typeCol = 2;  const nameCol = 3;  const teacherCol = 4;  let savedDate = "";  for (var i in data)  {    let row = data[i];    let classDate = row[dateCol];    let classPeriod = row[timeCol];    let classType = row[typeCol];    let className = row[nameCol];    let classTeacher = row[teacherCol];    if (classDate.trim() == "")    {      classDate = savedDate;    }    else    {      savedDate = classDate;    }    let classTimeInfo = extractPeriod(classPeriod, classDate);    let classStartTime = classTimeInfo.from;    let classEndTime = classTimeInfo.to;    let info = "Преподаватель: " + classTeacher + "\nТип занятия: " + classType;    var event = (CalendarApp.getCalendarsByName("Учеба"))[0].createEvent    (      className,      classStartTime,      classEndTime,      {        description: info      }    );    Utilities.sleep(50);  }}

4. Немножко скриншотов




Что можно улучшить


  • Некоторые значения в коде я просто захардкодил например, индексы начала таблицы, размеры таблицы, количество строк (количество мероприятий). Теоретически, можно покопаться в API Google Sheets для Google Apps Script и придумать, как выцеплять нужные координаты ячеек автоматически;
  • Я никогда плотно не изучал JavaScript, могут быть различные стилистические и прочие недостатки в коде, возможно тот же парсинг даты-времени можно сделать красивее и элегантнее.

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


Что читать дальше


Подробнее..
Категории: Javascript , Google app engine , Google apps

Перевод Как использовать GraphQL Federation для инкрементальной миграции с монолита (Python) на микросервисы (Go)

26.05.2021 16:17:30 | Автор: admin
Или как поменять фундамент старого дома, чтобы он не обвалился



Лет 10 назад мы выбрали 2-ю версию Python для разработки нашей обучающей платформы с монолитной архитектурой. Но с тех пор индустрия существенно изменилась. Python 2 был официально похоронен 1 января 2020 года. В предыдущей статье мы объясняли, почему решили отказаться от миграции на Python 3.

Каждый месяц нашей платформой пользуются миллионы людей.

Мы пошли на определённый риск, когда решили переписать наш бэкенд на Go и изменить архитектуру.

Язык Go мы выбрали по нескольким причинам:

  1. Высокая скорость компиляции.
  2. Экономия оперативной памяти.
  3. Достаточно широкий выбор IDE с поддержкой Go.

Но мы применили подход, который позволил минимизировать риск.

GraphQL Federation

Мы решили построить нашу новую архитектуру вокруг GraphQL Apollo Federation. GraphQL был создан разработчиками Facebook как альтернатива REST API. Федерация это построение единого шлюза для нескольких сервисов. Каждый сервис может иметь свою GraphQL-схему. Общий шлюз объединяет их схемы, генерирует единое API и позволяет выполнять запросы для нескольких сервисов одновременно.

Прежде чем, пойдём дальше, хотелось бы особо отметить следующее:

  1. В отличие от REST API, у каждого GraphQL-сервера есть собственная типизированная схема данных. Она позволяет получить любые комбинации именно тех данных с произвольными полями, которые вам нужны.

  2. Шлюз REST API позволяет отправить запрос только одному бэкенд-сервису; шлюз GraphQL генерирует план запросов для произвольного количества бэкенд-сервисов и позволяет вернуть выборки из них в одном общем ответе.

Итак, включив шлюз GraphQL в нашу систему, получим примерно такую картину:


URL картинки: https://lh6.googleusercontent.com/6GBj9z5WVnQnhqI19oNTRncw0LYDJM4U7FpWeGxVMaZlP46IAIcKfYZKTtHcl-bDFomedAoxSa9pFo6pdhL2daxyWNX2ZKVQIgqIIBWHxnXEouzcQhO9_mdf1tODwtti5OEOOFeb

Шлюз (он же сервис graphql-gateway) отвечает за создание плана запросов и отправки GraphQL-запросов другим нашим сервисам не только монолиту. Наши сервисы, написанные на Go, имеют свои собственные GraphQL-схемы. Для формирования ответов на запросы мы используем gqlgen (это GraphQL-библиотека для Go).

Так как GraphQL Federation предоставляет общую GraphQL-схему, а шлюз объединяет все отдельные схемы сервисов в одну, наш монолит будет взаимодействовать с ним так же, как и любой другой сервис. Это принципиальный момент.

Далее пойдёт речь о том, как мы кастомизировали сервер Apollo GraphQL, чтобы безопасно перелезть с нашего монолита (Python) на микросервисную архитектуру (Go).

Side-by-side тестирование


GraphQL мыслит наборами объектов и полей определённых типов. Код, который знает, что делать с входящим запросом, как и какие данные извлечь из полей, называется распознавателем (resolver).

Рассмотрим процесс миграции на примере типа данных для assignments:

123 type Assignment {createdDate: Time.}

Понятно, что в реальности у нас гораздо больше полей, но для каждого поля всё будет выглядеть аналогично.

Допустим, мы хотим, чтобы это поле из монолита было представлено и в нашем новом сервисе, написанном на Go. Как мы можем быть уверены, что новый сервис по запросу вернёт те же данные, что и монолит? Для этого используем подход, аналогичный библиотеке Scientist: запрашиваем данные и у монолита, и у нового сервиса, но затем сравниваем результаты и возвращаем только один из них.

Шаг 1: Режим manual


Когда пользователь запрашивает значение поля createdDate, наш GraphQL-шлюз обращается сначала к монолиту (который, напоминаю, написан на Python).


На первом шаге нам нужно обеспечить возможность добавления поля в новый сервис assignments, уже написанный на Go. В файле с расширением .graphql должен лежать следующий код распознавателя (resolver):

12345 extend type Assignment key(fields: id) {id: ID! externalcreatedDate: Time @migrate(from: python, state: manual)}

Здесь мы используем Федерацию, чтобы сказать, что сервис добавляет поле createdDate к типу Assignment. Доступ к полю происходит по id. Мы также добавляем секретный ингредиент директиву migrate. Мы написали код, который понимает эти директивы и создаёт несколько схем, которые GraphQL-шлюз будет использовать при принятии решения о маршрутизации запроса.

В режиме manual запрос будет адресован только коду монолита. Мы должны предусмотреть эту возможность при разработке нового сервиса. Чтобы получить значение поля createdDate, мы по-прежнему можем обращаться к монолиту напрямую (в режиме primary), а можем запрашивать у GraphQL-шлюза схему в режиме manual. Оба варианта должны работать.

Шаг 2: Режим side-by-side


После того, как мы написали код распознавателя (resolver) для поля createdDate, мы переключаем его в режим side-by-side:

12345 extend type Assignment key(fields: id) {id: ID! externalcreatedDate: Time @migrate(from: python, state: side-by-side)}

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

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

В процессе тестирования мы получаем вот такие отчёты.


Эту картинку при вёрстке попытайся увеличить как-то без сильной потери качества.

В них акцент сделан на случаи, когда в работе монолита и нового сервиса обнаруживаются расхождения.

Поначалу мы часто сталкивались с такими случаями. Со временем мы научились выявлять такого рода проблемы, оценивать их на критичность и при необходимости устранять.

При работе с нашими dev-серверами мы используем инструменты, которые выделяют различия цветом. Так легче анализировать проблемы и тестировать их решения.

А что по мутациям?


Возможно, у вас возник вопрос: если мы запускаем одинаковую логику и в Python, и в Go, что произойдет с кодом, который изменяет данные, а не просто запрашивает их? В терминах GraphQL это называется мутациями (mutation).

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

Шаг 2.5: Режим сanary


Если у нас есть поле или мутация, которые успешно дожили до стадии продакшна, мы включаем режим canary (канареечный деплой).

12345 extend type Assignment key(fields: id) {id: ID! externalcreatedDate: Time @migrate(from: python, state: canary)}

Поля и мутации в режиме canary будут добавлены в сервис Go для небольшого процента наших пользователей. Кроме того, канареечную схему тестируют и внутренние пользователи платформы. Это достаточно безопасный способ тестирования сложных изменений. Мы можем быстро отключить канареечную схему, если что-то не работает должным образом.

Мы используем только одну канареечную схему за раз. На практике не так много полей и мутаций одновременно находятся в канареечном режиме. Так что, я думаю, проблем не будет и дальше. Это хороший компромисс, потому что схема довольно велика (более 5000 полей), а экземпляры шлюза должны хранить в памяти три схемы primary, manual и canary.

Шаг 3: Режим migrated


На этом шаге поле createdDate должно перейти в режим migrated:

12345 extend type Assignment key(fields: id) {id: ID! externalcreatedDate: Time @migrate(from: python, state: migrated)}

В этом режиме GraphQL-шлюз отправляет запросы только новому сервису, написанному на Go. Но в любой момент мы можем посмотреть, как обработает то же запрос монолит. Так намного легче делать деплой и откатывать изменения, если что-то пойдёт не так.

Шаг 4: Завершение миграции


После успешного деплоя нам больше не нужен код монолита для этого поля, и мы удаляем из кода распознавателя (resolver) директиву @migrate:

12345 extend type Assignment key(fields: id) {id: ID! externalcreatedDate: Time}

С этого момента выражение Assignment.createdDate шлюз будет воспринимать как получение значения поля из нового сервиса, написанного на Go.

Вот такая она инкрементальная миграция!

И как далеко шагнули мы?


Мы завершили работу над нашей инфраструктурой side-by-side тестирования только в этом году. Это позволило нам безопасно, медленно, но верно переписать кучу кода на Go. В течение года мы поддерживали высокую доступность платформы на фоне роста объёма трафика в нашей системе. На момент написания этой статьи ~ 40% наших полей GraphQL вынесены в сервисы Go. Так что, описанный нами подход хорошо зарекомендовал себя в процессе миграции.

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

P.S. Стив Коффман делал доклад на эту тему (на Google Open Source Live). Вы можете посмотреть запись этого выступления на YouTube (или просто глянуть презентацию).



Облачные серверы от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Твоя первая игра на Godot Engine

02.12.2020 18:09:40 | Автор: admin

1. Предисловие

Здравствуй, в данной статье я хочу в максимально сжатой форме познакомить тебя с основами создания простых 2d платформеров на движке Godot. Иногда мы будем останавливаться на некоторых важных моментах, а иногда пропускать ненужную тебе на начальном уровне информацию.

2.Стартуем!

Думаю установить сам движок не составит труда. После установки открываем его и нажимаем на кнопку новый проект.

Создание проекта.Создание проекта.

В выплывшем окошке введи название проекта и выбери его расположение в файловой системе. В пункте отрисовщик выбираем OpenGL ES 3.0, у нас нет нужды использовать более старую версию opengl, т.к ее обычно применяют при создании браузерных игр.

3.Знакомство с интерфейсом

2D сцена в Godot Engine.2D сцена в Godot Engine.

Итак, мы создали твой первый проект! Отличное начало, на сегодня хватит. Ладно, а если серьезно, то изучать интерфейс программы, особенно на первых парах, очень важно. Перед тобой открылась интересная картина с пустой 3d сценой, но она нам сегодня не понадобится, поэтому переходим в вкладку 2d. Кнопка находится сверху посередине. Стало немного проще, не правда ли? Ну, а теперь перейдем к самому интерфейсу программы (его кстати можно настроить под себя, перетащив какие-то элементы левой кнопкой мыши, но пока лучше оставит все как есть).

4.Работа с файлами через Godot

Не очень удобно каждый раз лазить в проводник, чтобы достать какие-то файлы, согласен? Для этого в Godot существует отдельное окошко, оно находится в левом нижнем углу редактора.

Проводник в Godot Engine.Проводник в Godot Engine.

Пока что там пусто, но это потому, что мы еще ничего не добавили. Так давай сделаем это! Ссылку на архив я прикрепил в конце поста, скачивай его и наслаждайся халявными спрайтами для игры (сразу говорю, они не мои). Если конечно у тебя заготовлена своя графика, то милости прошу.Итак, выделяем все нужные нам файлы и переносим их в окошечко. Вжух и они скопировались в движок! Но на этом магия не заканчивается! Здесь можно делать все то, что ты делаешь в обычном проводнике! Одним словом, полная свобода действий.

Но давай пока оставим эту часть экрана в покое и перейдем к более серьезным вещам.

5.Работа со сценами

Создание новых сцен.Создание новых сцен.

Посмотри в верхний левый угол редактора. Здесь есть вкладка, которая называется Сцена. Давай добавим твою первую сцену! Делается это просто, тебе нужно либо нажать на плюсик, либо ввести сочетание клавиш ctrl + A. Перед тобой выплыло меню, в поиске которого нужно ввести заветное слово Node. Мы давай это будет наша основная сцена, назовем ее World, но название в принципе неважно. Чтобы переименовать сцену нужно лишь дважды щелкнуть на нее левой кнопкой мыши. Теперь давай добавим на сцену игрока!

Многие просто добавляют объект Sprite, но это большая ошибка! Так делать нельзя! Запомни это раз и навсегда! Мы с тобой, как продвинутые пользователи добавим не Sprite, а KinematicBody2D.

Теперь древо твоего проекта выглядит так:

Добавляем игрока.Добавляем игрока.

Как ты наверное успел заметить, напротив нашего KinematicBode2D висит какой-то желты значок. Что он тут забыл? Дело в том, что наш объект пока что не имеет форму, вот Godot и ругается. Но прежде чем добавить форму нашему игроку, давай добавим его спрайт( И не забудь заменить название KinrmaticBode2D на Player ). Для этого нажми один раз правой кнопкой мыши на нашего Player и сочетанием клавиш ctrl + A добавь объект Sprite. Потом опять нажми на Игрока и добавь объект CollisionShape2D. У тебя должна быть примерно такая картина:

Добавляем в спрайт и границы игрока.Добавляем в спрайт и границы игрока.

Если все так, едем дальше. Теперь зададим картинку спрайта нашего персонажа. Выбираем объект Sprite, а потом перетаскиваем из моего архива картинку Player.png( или твою картинку) в раздел Texture. Если картинка импортировалась с сжатым качеством, просто нажми на нее, и в Godot в верхнем левом углу перейди в вкладку Импорт, там в разделе Flags убери галочку с пункта Filter и нажми Переимпортировать. Если не помогло, то просто перезапусти Godot.

Итак, мы добавили спрайт игрока, но выглядит это немного странно.

Добавляем текстуру спрайта игрока.Добавляем текстуру спрайта игрока.

Что же делать? Без паники, все поправимо в пару кликов. В левой части панели Инспектор выбираем параметр Hframes, и подгоняем его по размерам ( у меня это 25). Ну что, поменялась картинка?

Устанавливаем границы спрайта.Устанавливаем границы спрайта.

Супер, едем дальше! Ты еще не забыл про CollisionShape2D? Выделяй его и в пункте Shape выбирай Новый RectangleShape2D. Теперь изменяй его под размер персонажа. У меня получилось так:

CollisionShape2d.CollisionShape2d.

6.Отдельные сцены в Godot

Это все конечно классно,но хорошим тоном в Godot является создание отдельных сцен для объектов. Поэтому нам нужно сделать так, чтобы объект Player был отдельной сценой. Но не создавать же нам все заново? Нет, для этого в движке предусмотрена отдельная функция.Нажмите на Player правой кнопкой мыши и выберете Сохранить ветку,как ветку.

Создание сцены из ветки.Создание сцены из ветки.

Теперь Player это отдельная сцена, отлично!Чтобы перейти на сцену игрока достаточно нажать на иконку:

Перейдем на сцену игрока и приступим к очень интересному занятию программированию.

7. Скрипт игрока, GDscript

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

Создать скрипт.Создать скрипт.

После этого выплывет такая табличка:

Скрипт для игрока.Скрипт для игрока.

Нажимаем Создать и у нас открывается встроенный редактор кода в Godot.Теперь начинается более сложная часть туториала, поэтому слушай внимательнее.Пока что наш персонаж просто стоит на сцене и ничего не делает, это слишком скучно. Ну так давай сделаем управление персонажем!Что нам для этого понадобится? Нам нужен скрипт, который будет обрабатывать нажатия клавиш с клавиатуры, двигать персонажа, проигрывать анимацию. Но давай пойдем по порядку и начнем с самого простого управления.

Простое управление.Простое управление.

Пишем вот такой код, не волнуйся сейчас все объясню. Первая строчка объявляет Godot, что мы используем объект KinematicBody2D. Ее создал сам движок. На 3 и 4 строчке мы задаем две константы, отвечающие за ускорение и максимальную скорость. Они нужны для плавного перемещения персонажа по сцене. На 6 строчке объявляем переменную для вектора перемещения. После этого на 8 строчке создаем функцию physicsprocess, это системная функция движка. Она нужна, чтобы привязать к персонажу физику. В нашем случае - это физика перемещения и сила гравитации. 9 строчка отвечает за управление по оси X. Метод Input помогает нам считывать те самые кнопки для управления (стрелка влево и стрелка вправо). После на 11 строчке мы проверяем была ли нажата какая-то кнопка. Потом мы перемещаемся влево или вправо.

Как ты заметил, мы прибавляем к координате игрока произведение направления по координате на ускорение и на какую-то delta. Вопрос, что такое delta? Delta показывает сколько времени (в секундах, тип float) прошло с момента отрисовки прошлого кадра.Зачем это сделано? Если мы не будем привязывать передвижение игрока ко времени, то оно автоматически привязывается к частоте процессора. На крутых компьютерах или телефонах разница незаметна, но запустив приложение на старом пк или телефоне, ты все поймешь. Поэтому всегда привязывай передвижение к delta!

Потом в строке 13 мы используем какой-то clamp. Опять неразбериха! Все просто, clamp, как можно догадаться из названия, сжимает значение переменной. Сделано это для оптимизации и плавности движения.Ну и в последней строке мы просто запускаем передвижение нашего игрока. Не так уж все и сложно!

8. Первый запуск.

Вот сделали мы все это с тобой, а где результат? Ну так давай поскорее запустим с тобой первую демку! Все очень просто, нажми клавишу F5, после этого выплывет окно, которое скажет тебе, что основания сцена не выбрана. В нашем случае основная сцена World.tscn. Выбираем ее и снова жмем F5. Должно появиться что-то такое:

Окно демки.Окно демки.

В верхнем левом углу можно заметить маленькую часть нашего персонажа. Давай приведем все в порядок. Для этого сначала закрое окошко демки и перейдем в настройки проекта. Чтобы это сделать, в левой верхней части нажми на Проект, а в выплывшем окне нажми Настройки проекта. Здесь переходим в вкладку Window и ставим разрешение на 320x180. Почему такое маленькое? Все просто, мы с тобой задали разрешение экрана в самой сцене, для платформера такие размеры идеальны. А для экрана самой демки нужно задать нормальное разрешение. Это можно сделать в пунктах Test Width и Test Height. Я задам его в формате 1280x720. Спустимся пониже и в пункте Mode ставим 2d, а в Aspect ставим keep. Для красоты предлагаю обратно перейти на сцену и передвинуть персонажа в середину экрана. Делается это легко, просто зажми персонажа левой кнопкой мыши и начни перетаскивать. Теперь все приготовления закончены,можно запускать демку.

Красота, правда? Попробуй передвигать персонажа стрелками на клавиатур. Получилось? Да, но персонаж будто скользит по экрану и не может остановиться. Не волнуйся, скоро мы это исправим. Однако сейчас наш персонаж как бы висит в воздухе, это ней есть хорошо. Давай сделаем землю для нашего игрока!

9.Tilemaps

Что такое Tilemap? Тайлы это плитки, вместе образующие сетку тайлов. Чаще всего они принимают форму квадратов. Как же их добавить в наш платформер? Очень просто, для начала выбери объект World(нашу основную сцену), нажми клавиши ctrl + A и выбери TileMap.

Теперь в этом окошке выбири Tile Set и нажми Новый TileSet.Снова нажми на TileSet, должно получиться ка-то так:

Добавляем анимацию.Добавляем анимацию.

Давай добавим спрайт для нашего tilemap, для этого нажми на плюс снизу и выбери tile.png.

Следующий шаг будет довольно сложным, поэтому слушай внимательно.Итак, в вкладке Регион полостью выделяем нашу картинку, в вкалдке snap options ставим step по x и y на 16. Такие же действия повторяем в вкладках столкновение, перекрытие, навигация, битовая маска. А последней мы остановимся поподробней.

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

Задаем границы тайла.Задаем границы тайла.

Отлично, сохраняем все и переходим обратно на сцену. Еще рах кликаем на Tilemap и в раздеел Cell меняем size на 16x16.Теперь можно делать уровень!

Создаем простой уровень.Создаем простой уровень.

Вот как у меня получилось. Супер, но на нашего игрока до сих пор не действует гравитация, давай это исправим. Для этого перейдем в скрипт player и введем там такой код.

Константы для прыжка и гравитации.Константы для прыжка и гравитации.

Здесь к существующим переменным мы добавляем friction, gravity, jumpforce, airresistance. Названия говорят сами за себя, поэтому объяснять за что они отвечают я не буду.

Реализация прыжка и гравитации.Реализация прыжка и гравитации.

Следом идет сама сила гравитации. Мы прибавляем к motion.y силу тяжести, умноженную на delta. Это действие заставляет нашего игрока падать вниз, если под ним ничего нет. После этого скрипт обрабатывает нажатия на кнопки, характерные для прыжка (стрелочка вверх). И заставляет игрока падать вниз, когда он уже прыгнул.

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

Как выглядит при запуске.Как выглядит при запуске.

10.Анимации

Простые анимации в Godot сделать очень легко. Для этого перейдем на сцену player и добавим туда AnimationPlayer. Жмем на кнопку анимация, далее жмем новый и вводим название анимации. Сделаю анимацию для бега и назову ее Run.Чтобы добавить новый кадр для анимации нужно перейти в sprite.

Добавляем кадры в анимацию.Добавляем кадры в анимацию.

Напротив пункта frame есть клчик,если нажать на него, то кадр из спрайта добавиться в анимацию. Постепенно увеличиваем frame от 0 до 8 и ключиком добавляем кадр в анимацию. Вот как в итоге это должно выглядеть:

Создаем анимацию из кадров.Создаем анимацию из кадров.

Тоже самое повторяем для других анимаций, просто меняя номер кадра. В итоге у тебя будет несколько анимаций для прыжка, ходьбы, и анимация idle. Теперь все это нужно добавить в код.Переходим в код player и вносим некоторые изменения:

Добавляем переменные для анимации.Добавляем переменные для анимации.

Добавляем две переменные sprite и player. Но ты заметил, они какие-то странные. Почему в начале стоит слово onready, что за странное значение этой переменной? Сейчас все объясню. Переменные типа onready нужны для взаимодействий с другими объектами на сцене. В данном случае мы подключаем их для воспроизведения анимации и получения спрайта игрока.

Анимация при ходьбе.Анимация при ходьбе.

На 16-ой строчке мы проигрываем анимацию ходьбы. Однако здесь еще появилась какая-то странная 22 строчка, что она делает? Она зеркально отражает анимацию игрока в зависимости от того, куда он идет. А на 24 строке мы говорим, что если игрок стоит, то проигрывать нужно анимацию idle.

Анимация прыжка.Анимация прыжка.

На 22 строчке мы проигрываем анимацию прыжка, если игрок не на земле. Вот собственно и все изменения в коде.

Заключение

Если ты все правильно делал, то у тебя должен получиться простой платформер. Что делать дальше? Да все что угодно! Улучшай свои навыки в использовании движка, создавай свои собственные игры изучай новые фишки. А этом я вынужден с тобой проститься, надеюсь ты хорошо провел время и научился чему-то новому.

Вот все материалы для этого туториала:

Подробнее..

Перевод Почему бессерверная революция зашла в тупик

19.10.2020 22:04:09 | Автор: admin

Ключевые моменты


  • Вот уже несколько лет нам обещают, что бессерверные вычисления (serverless) откроют новую эпоху без конкретной ОС для выполнения приложений. Нам говорили, что такая структура решит множество проблем масштабируемости. На самом деле всё иначе.
  • Хотя многие рассматривают бессерверную технологию как новую идею, её корни можно проследить вплоть до 2006 года, когда появились Zimki PaaS и Google App Engine в обоих случаях используется бессерверная архитектура.
  • Есть четыре причины, по которым бессерверная революция зашла в тупик: от ограниченной поддержки языков программирования до проблем с производительностью.
  • Бессерверные вычисления не так уж бесполезны. Отнюдь нет. Однако их не следует рассматривать как прямую замену серверов. Для некоторых приложений они могут быть удобным инструментом.

Сервер мёртв, да здравствует сервер!


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

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

Некоторые из обещаний для бессерверных моделей, несомненно, были реализованы, но не все. Далеко не все.

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

Что обещали адепты бессерверных вычислений


Прежде чем перейти к проблемам бессерверных вычислений, давайте посмотрим, что они должны были обеспечить. Обещания бессерверной революции были многочисленными и порой очень амбициозными.

Для тех, кто не знаком с термином, вот краткое определение. Бессерверные вычисления определяют архитектуру, в которой приложения (или части приложений) выполняются по требованию в средах выполнения, которые обычно размещаются удалённо. Кроме того, бессерверные системы можно захостить у себя. В течение нескольких последних лет создание устойчивых бессерверных систем было главной заботой системных администраторов и SaaS-компаний, поскольку (как утверждается) эта архитектура предлагает несколько ключевых преимуществ по сравнению с традиционной клиент-серверной моделью:

  1. Бессерверные модели не требуют, чтобы пользователи поддерживали собственные операционные системы или даже создавали приложения, совместимые с определёнными ОС. Вместо этого разработчики создают общий код, загружают его в бессерверную платформу и наблюдают за его выполнением.
  2. Ресурсы в бессерверных фреймворках обычно оплачиваются по минутам (или даже секундам). Это означает, что клиенты платят только за то время, когда они фактически выполняют код. Это выгодно отличается от традиционной облачной VM, где машина большую часть времени простаивает, но за неё приходится платить.
  3. Проблема масштабируемости также решалась. Ресурсы в бессерверных фреймворках назначаются динамически, так что система легко справляется с внезапными всплесками спроса.

Короче говоря, бессерверные модели обеспечивают гибкие, дешёвые, масштабируемые решения. Удивительно, что мы не додумались до этой идеи раньше.

Это действительно новая идея?


На самом деле идея не нова. Концепция, позволяющая пользователям платить только за то время, когда код фактически запускается, существует с тех пор, как она была введена в рамках Zimki PaaS в 2006 году, и примерно в то же время Google App Engine предложил очень похожее решение.

На самом деле то, что мы сейчас называем бессерверной моделью, старше многих технологий, которые сейчас называют нативными облачными, и которые обеспечивают почти то же самое. Как уже отмечалось, бессерверные модели по сути являются лишь продолжением бизнес-модели SaaS, которая существует уже несколько десятилетий.

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

Так к чему вся эта шумиха? Что ж, поскольку скорость проникновения интернета в развивающиеся страны продолжает стремительно расти, одновременно растёт спрос на вычислительные ресурсы. Например, во многих странах с быстро растущими секторами электронной коммерции просто нет вычислительной инфраструктуры для приложений на этих платформах. Вот тут-то и появляются платные бессерверные платформы.

Проблемы бессерверных моделей


Загвоздка в том, что у бессерверных моделей есть проблемы. Не поймите меня неправильно: я не говорю, что они плохи сами по себе или не обеспечивают существенной ценности для некоторых компаний в некоторых обстоятельствах. Но главное утверждение революции что бессерверная архитектура быстро заменит традиционную никогда не реализуется.

Вот почему.

Ограниченная поддержка языков программирования


Большинство бессерверных платформ позволяют запускать только те приложения, которые написаны на определённых языках. Это серьёзно ограничивает гибкость и адаптивность этих систем.

Считается, что бессерверные платформы поддерживают большинство основных языков. AWS Lambda и Azure Functions также предоставляют оболочку для запуска приложений и функций на неподдерживаемых языках, хотя это часто сопряжено с затратами на производительность. Так что для большинства организаций обычно это ограничение не имеет большого значения. Но вот в чём дело. Предполагается, что одно из преимуществ бессерверных моделей в том, что малоизвестные, редко используемые программы можно использовать дешевле, поскольку вы платите только за время их выполнения. А малоизвестные, редко используемые программы часто пишутся на малоизвестных, редко используемых языках программирования.

Это подрывает одно из ключевых преимуществ бессерверной модели.

Привязка к вендору


Вторая проблема с бессерверными платформами или, по крайней мере, с тем, как они реализуются в настоящее время, заключается в том, что они обычно не похожи друг на друга на операционном уровне. Практически нет стандартизации в части написания функций, деплоя и управления. Это означает, что миграция функций с одной платформы на другую занимает чрезвычайно много времени.

Самая трудная часть перехода на бессерверную модель это не вычислительные функции, которые обычно представляют собой просто фрагменты кода, а то, как приложения связаны с подключёнными системами, такими как хранилище объектов, управление идентификацией и очереди. Функции можно переместить, но остальную часть приложения нет. Это полная противоположность обещанным дешёвым и гибким платформам.

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

Производительность


Вычислительную производительность бессерверных платформ трудно измерить, отчасти потому, что вендоры стремятся сохранить информацию в тайне. Большинство утверждает, что функции на удалённых, бессерверных платформах работают так же быстро, как и на внутренних серверах, за исключением нескольких неизбежных проблем с задержкой.

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

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

Другой подход заключается в том, чтобы обеспечить регулярное выполнение критически важных для производительности программ, чтобы они оставались свежими. Этот второй подход, конечно, немного противоречит утверждению, что бессерверные платформы более экономичны, потому что вы платите только за время работы ваших программ. Облачные провайдеры внедрили новые способы сокращения холодных запусков, но многие из них требуют масштабирования до одного (scale to one), что подрывает первоначальную ценность FaaS.

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

Вы не можете запускать целые приложения


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

Точнее, это нецелесообразно с точки зрения затрат. Ваш успешный монолит, вероятно, не стоит превращать в набор из четырёх десятков функций, связанных восемью шлюзами, сорока очередями и дюжиной экземпляров БД. По этой причине serverless лучше подходит для новых разработок. Практически ни одно существующее приложение (архитектуру) нельзя перенести. Вы можете мигрировать, но придётся начинать с нуля.

Это означает, что в подавляющем большинстве случаев бессерверные платформы используются в качестве дополнения к внутренним серверам для выполнения задач, требующих больших вычислений. Это очень сильно отличает их от двух других форм облачных технологий контейнеров и виртуальных машин, которые предлагают целостный способ выполнения удалённых вычислений. Это иллюстрирует одну из трудностей перехода от микросервисов к бессерверным системам.

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

Да здравствует революция?


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

Книга Site Reliability Workbook практическое применение

08.09.2020 12:21:09 | Автор: admin
image Привет, Хаброжители! Книга Site Reliability Engineering спровоцировала бурную дискуссию. Что сегодня понимается под эксплуатацией и почему столь фундаментальную важность имеют вопросы надежности? Теперь инженеры Google, участвовавшие в создании этого бестселлера, предлагают перейти от теории к практике Site Reliability Workbook покажет, как принципы и практика SRE воплощаются в вашем продакшене Опыт специалистов Google дополнен кейсами пользователей Google Cloud Platform. Представители Evernote, The Home Depot, The New York Times и других компаний описывают свой боевой опыт, рассказывают, какие практики у них прижились, а какие нет. Эта книга поможет адаптировать SRE к реалиям вашей собственной практики, независимо от размеров вашей компании. Вы научитесь:

  • обеспечивать надёжность сервисов в облаках и средах, которые вы не полностью контролируете;
  • применять различные методы создания, запуска и мониторинга сервисов, ориентируясь на SLO;
  • трансформировать команды админов в SRE-инженеров;
  • внедрять методы запуска SRE с чистого листа и на базе существующих систем. Бетси Бейер, Нейл Ричард Мёрфи, Дэвид Рензин, Кент Кавахара и Стивен Торн занимаются обеспечением надежности систем Google.

Управление системой мониторинга


Ваша система мониторинга так же важна, как и любая другая служба, которую вы используете. Поэтому к мониторингу следует относиться с должным вниманием.

Рассматривайте свою конфигурацию как код

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

Мы также настоятельно рекомендуем рассматривать конфигурацию мониторинга как код (подробнее о конфигурации в главе 14). Система мониторинга, которая поддерживает настройку с использованием оформленных описаний целей и функций, предпочтительнее систем, предоставляющих только веб-интерфейсы или API в стиле CRUD (http://personeltest.ru/away/bit.ly/1G4WdV1). Данный подход к конфигурации является стандартным для многих бинарных файлов с открытым исходным кодом, которые только читают файл конфигурации. Некоторые сторонние решения, такие как grafanalib (http://personeltest.ru/away/bit.ly/2so5Wrx), поддерживают этот подход для компонентов, которые традиционно настраиваются с помощью пользовательского интерфейса.

Поощряйте согласованность

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

Правильное решение зависит от типа вашей организации. Со временем подход Google эволюционировал в направлении сведения всех наработок в единой платформе, работающей в виде централизованного сервиса. Это хорошее для нас решение, и для этого есть несколько причин. Единая инфраструктура позволяет инженерам быстрее и проще переходить из одной команды в другую и облегчает совместную работу во время отладки. Кроме того, есть централизованный сервис по выводу информации (dashboarding service), где панели мониторинга каждой команды открыты и доступны. Если вы хорошо понимаете информацию, предоставленную другой командой, то можете быстрее исправить как свои проблемы, так и проблемы других команд.

По возможности сделайте покрытие базовым мониторингом как можно более простым. Если все ваши сервисы экспортируют согласованный набор базовых показателей, вы можете автоматически собирать эти показатели по всей организации и предоставлять согласованный набор панелей мониторинга. Этот подход означает, что для любого нового компонента, который вы запускаете автоматически, предусмотрен базовый мониторинг. Таким образом, многие команды в вашей компании даже не инженерные смогут использовать данные мониторинга.

Предпочтите слабые связи

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

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

В мире открытого кода разделение функциональности на отдельные компоненты становится популярным. Десять лет назад системы мониторинга, такие как Zabbix (http://personeltest.ru/aways/www.zabbix.com/), объединяли все функции в один компонент. Современное проектирование обычно предполагает разделение сбора и выполнения правил (с помощью таких решений, как, например, сервер Prometheus (http://personeltest.ru/aways/prometheus.io/)), хранения долгосрочных временных рядов (InfluxDB, www.influxdata.com), агрегирования предупреждений (Alertmanager, bit.ly/2soB22b) и создания панелей мониторинга (Grafana, grafana.com).

На момент написания этой книги существует как минимум два популярных открытых стандарта, позволяющих оснащать программное обеспечение необходимыми инструментами и предоставлять метрики:

  • statsd демон сбора метрик, изначально написанный Etsy, теперь перенесен на большинство языков программирования;
  • Prometheus решение для мониторинга с открытым исходным кодом с гибкой моделью данных, поддержкой меток для метрик и весьма качественно реализованной функциональностью гистограмм. Другие системы теперь постепенно перенимают формат Prometheus и стандартизируются как OpenMetrics (http://personeltest.ru/aways/openmetrics.io/).

Отдельная система информационных панелей, использующая несколько источников данных, обеспечивает централизованный и унифицированный обзор вашего сервиса. Компания Google недавно ощутила это преимущество на практике: наша устаревшая система мониторинга (Borgmon1) объединяла информационные панели в той же конфигурации, что и правила оповещения. При переходе на новую систему (Monarch, youtu.be/LlvJdK1xsl4) мы решили перенести информационные панели в отдельный сервис (Viceroy, bit.ly/2sqRwad). Viceroy не был компонентом Borgmon или Monarch, поэтому у Monarch было меньше функциональных требований. Поскольку пользователи могут задействовать Viceroy для отображения графиков, основанных на данных из обеих систем мониторинга, они смогли постепенно перейти с Borgmon на Monarch.

Осмысленные метрики

В главе 5 рассказывается о том, как с помощью показателей уровня качества обслуживания (SLI) отслеживать угрозы бюджету ошибок и оповещать об их возникновении. Метрики SLI это первые метрики, которые стоит проверять при срабатывании оповещений, основанных на целевых показателях уровня качества обслуживания (SLO). Эти метрики должны отображаться на информационной панели вашего сервиса, в идеале на его первой странице.

При расследовании причин нарушения SLO вы, скорее всего, не получите достаточно информации от панелей SLO. Эти панели показывают, что нарушения есть, но о причинах, приведших к ним, вы вряд ли узнаете. Какие еще данные следует отобразить на панели мониторинга?

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

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

  • мониторинг версии бинарного файла;
  • мониторинг флагов командной строки, особенно когда вы используете эти флаги для включения и отключения функций сервиса;
  • если данные конфигурации передаются в сервис динамически, мониторинг версии этой динамической конфигурации.

Если для какого-либо из этих компонентов системы контроля версий нет, вам необходимо отслеживать, когда была выполнена последняя сборка или упаковка данного компонента.

Когда вы пытаетесь соотнести возникающие проблемы сервиса с развертыванием, гораздо проще взглянуть на какую-либо диаграмму или панель, на которую есть ссылка в оповещении, чем перелистывать журналы CI/CD постфактум.

Зависимости

Даже если ваш сервис не изменился, может измениться любая из его зависимостей. Поэтому вам также необходимо отслеживать ответы, поступающие от прямых зависимостей.

Разумно экспортировать размер запроса и ответа в байтах, время отклика и коды ответа для каждой зависимости. При выборе метрики для графика помните об этих четырех золотых сигналах (см. раздел Четыре золотых сигнала главы 6 книги Site Reliability Engineering).
Можно использовать в метриках дополнительные метки, чтобы разделить их по коду ответа, имени метода RPC (удаленного вызова процедур) и имени вызываемого сервиса.

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

Встречаются зависимости, предлагающие очень ограниченный API, где вся функциональность доступна через один RPC-метод, называющийся Get, Query или столь же неинформативно, а фактическая команда указывается в качестве аргументов этого метода. Подход с единой точкой доступа к инструментам в клиентской библиотеке не работает при таком типе зависимости: вы будете наблюдать большую вариативность в задержке и некий процент ошибок, который может как указывать, так и не указывать на то, что какая-то часть этого мутного API полностью отвалилась. Если эта зависимость является критической, хороший мониторинг для нее можно реализовать следующими способами.

  • Экспортируйте отдельные метрики, разработанные специально для этой зависимости, где для получения действительного сигнала будет выполняться распаковка полученных запросов.
  • Попросите владельцев зависимости переписать ее так, чтобы экспортировался расширенный API, поддерживающий разделение функций между отдельными сервисами и методами RPC.

Уровень загруженности

Желательно контролировать и отслеживать использование всех ресурсов, с помощью которых работает сервис. У некоторых ресурсов есть жесткие ограничения, которые вы не можете превысить. Например, выделенный для вашего приложения размер ОЗУ, жесткого диска или квота на ЦП. Другие ресурсы, такие как дескрипторы открытых файлов, активные потоки в любых пулах потоков, время ожидания в очередях или объем записанных журналов, могут не иметь четкого жесткого ограничения, но все же требуют управления.

В зависимости от используемого языка программирования вам нужно отслеживать некоторые дополнительные ресурсы:

  • в Java размер кучи и метапространства (http://personeltest.ru/away/bit.ly/2J9g3Ha), а также более конкретные показатели в зависимости от используемого типа сборки мусора;
  • в Go количество горутин.

Сами языки программирования предоставляют различную поддержку для отслеживания этих ресурсов.

В дополнение к оповещению о значительных событиях, как описано в главе 5, вам также может понадобиться настроить оповещения, которые срабатывают при приближении к критическому истощению определенных ресурсов. Это полезно, например, в следующих ситуациях:

  • когда у ресурса имеется жесткий лимит;
  • когда при превышении порога использования происходит снижение производительности.

Мониторинг необходим для всех ресурсов, даже для тех, которыми сервис хорошо управляет. Эти метрики жизненно важны при планировании ресурсов и возможностей.

Состояние выдаваемого трафика

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

  • Следите за всеми кодами ответов для HTTP-трафика, учитывая даже те, которые из-за возможного некорректного поведения клиента не являются поводом для выдачи оповещений.
  • Если вы применяете к своим пользователям ограничения количества запросов в единицу времени или квоты, следите за количеством запросов, отклоненных из-за отсутствия квоты.

Графики этих данных могут вам помочь определить, когда во время производственного изменения заметно меняется объем ошибок.

Реализация целевых метрик

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

Тестирование логики оповещения


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

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

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

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

  1. Бинарные файлы. Убедитесь, что у экспортируемых метрических переменных, как и ожидалось, при определенных условиях меняются значения.
  2. Инфраструктура мониторинга. Убедитесь, что исполнение правил дает ожидаемые результаты, а конкретные условия ожидаемые оповещения.
  3. Диспетчер оповещений. Проверьте, что сгенерированные оповещения направляются в заранее определенное на основе значений меток место назначения.

image

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

Итоги главы

Поскольку SR-инженеры должны отвечать за надежность производственных систем, от этих специалистов часто требуется глубокое понимание системы мониторинга и ее функций и тесное взаимодействие с ней. Без этих данных SRE могут не знать, где искать и как определить ненормальное поведение системы или как найти информацию, которая им нужна во время чрезвычайной ситуации.

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

Обязательно соберите метрики, которые служат конкретной цели. Это такие цели, как, например, улучшение планирования пропускной способности, отладка или выдача сообщений о возникающих проблемах.

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

Более подробно с книгой можно ознакомиться на сайте издательства
Оглавление
Отрывок

Для Хаброжителей скидка 25% по купону Google

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Подробнее..

Обзор на курс специализации от Coursera Cloud Architecture with Google Cloud

19.11.2020 22:10:01 | Автор: admin

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


В специализацию входят следующие курсы:


  • Google Cloud Platform Fundamentals: Core Infrastructure
  • Essential Google Cloud Infrastructure: Foundation
  • Essential Google Cloud Infrastructure: Core Services
  • Elastic Google Cloud Infrastructure: Scaling and Automation
  • Reliable Google Cloud Infrastructure: Design and Process
  • Architecting with Google Kubernetes Engine: Foundations
  • Preparing for the Google Cloud Professional Cloud Architect Exam

Да, последний курс посвящен к защите сертификации от Google. Сертификация стоит 200 долларов, больше информации можно найти здесь.



Начнем с самих курсов. Если перед вами стоит цель только ознакомиться, как работает Google Cloud Platform (GCP), что такое облачные вычисления, архитектура вычислении GCP, как устроена сеть, на какие Зоны и Регионы делятся, политика безопасности, как контролировать бюджет и как устроена оплата сервисов GCP, то можно ограничиться лишь первым курсом Google Cloud Platform Fundamentals: Core Infrastructure. Или если на днях вам предстоит проект, где придется столкнуться с GCP, и вам нужно понять, что и как там работает, разобраться в интерфейсе и в базовых командах, то также можете остановиться лишь на первом курсе.


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


Google Cloud Platform Fundamentals: Core Infrastructure


В данном курсе, можно получить информацию по всем частям GCP, и даже получить практический опыт через лабораторные работы. Лабораторные работы проходят через платформу QwikLabs, где вам выдадут временный студенческий аккаунт, и необходимо выполнить задание в зависимости от изучаемой темы. Система настроена так, что она проверяет прогресс выполняемой работы, и по завершению проекта, можно сразу же видеть и результат, и оценку за лабораторную работу. Не нужно ждать, пока другие сокурсники проверят твою работу, как в других курсах на Coursera. Это ускоряет обучение на курсе, и можно пройти курс с любой скоростью. За QwikLabs жирный плюс курсу.


Данный курс рассматривает такие темы как:


  • Иерархия ресурсов в GCP, что такое проект, как структурировать их;
  • Идентификация и права доступа, рассматривают различные сценарии;
  • Способы взаимодействия с GCP, веб консоль, мобильное приложение, API, и командная строка внутри браузера;
  • Агрегатор (Marketplace) готовых решении (Wordpress, Jira, LAMP и тд);
  • Виртуальная машина (Compute Engine);
  • Приватная виртуальная облачная сесть;
  • Хранение данных в облаке;
  • Контейнеры и Kubernetes;
  • Запуск клиентских приложении в облаке (App Engine);
  • Инфраструктура как код (Deployment Manager);
  • Мониторинг;
  • Big Data, Machine Learning в облаке.

Несколько важных заметок, которые сделал для себя.


Compute Engines



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


Главная разница между IaaS и PaaS в том, что в IaaS платишь за резервирование ресурсов (2 ядра, 512 Гб SSD и тд.), а в PaaS платишь только за использованные ресурсы.


App Engine поддерживает следующие языки программирования: Java, Go, PHP, Ruby, Python, .NET, Node.js. Если есть необходимость использовать другой язык программирования или версию языка, можно выбрать Flexible App Engine.


Хранение данных в Облаке



Здесь можно увидеть какие системы хранения данных есть.


Cloud Storage система для хранения файлов, например как картинки. Есть несколько классов данного хранилища, от Multi-Region для часто используемых файлов, так и Coldline, для файлов бэкапа например, которые требуются не так часто для чтения.
Cloud SQL это MySQL/PostgreSQL база данных как сервис в облаке GCP.
Cloud Spanner решает те же проблемы, что и Cloud SQL, но если вам нужно иметь возможность масштабирования.
Cloud Datastore NoSQL документоориентированная хранилище данных, с SQL синтаксисом и поддержкой транзакции. Рекомендуют использовать как базу данных для приложении.
BigQuery это уже OLAP хранилище, удобно сливать туда данные, как из других облачных хранилищ, так и из внешних систем, и строить аналитику на данной платформе.


Прочее


Помимо серверов, и хранилищ данных, GCP предлагает множество решении, например Kubernetes Engine если у вас микросервисная архитектура, Deployment Manager если вам нужно настроить CI систему.


Также на курсе можно получить большую порцию полезной информации, как работает сеть в GCP, и как это масштабируется. Как создать Приватную облачную виртуальную сеть (VPC), как выдавать доступы, как разворачивать в разных регионах и объединять их в одну сеть.


Рассказывают и показывают различные кейсы, как принимать трафик из вне, как настроить балансировщик, и какие инструменты нужно использовать, и какой трафик монетизируется.
По монетизации, они создали калькулятор, где можно выбрать необходимый профиль работы системы, и увидеть стоимость. Плюс, сама платформа дает скидки в зависимости от профиля нагрузки и работы.


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


И по каждому пункту можно получить практический опыт на курсе. Протыкать и просмотреть каждый пункт.


Заключение


Как вы могли заметить по статье, саму специализацию я не рекомендую к прохождению, так как курсы дублируют информацию. Но самый первый курс довольно не плох. Курс рассчитан на 16 часов. Новичкам курс также подойдет, так как не требует особых навыков для прохождения.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru