<style>
.reveal {
font-size: 24px;
}
.reveal code {
font-size: 20px;
line-height: initial;
/* word-wrap: break-word; */
}
.reveal section img {
background: none;
border: none;
box-shadow: none;
max-height: 400px;
/* height: 400px; */
}
/* .reveal ul li { padding: 10px 0px; } */
.reveal .speaker-notes {
font-size: 10px;
}
.two-column-layout {
display: flex;
align-items: center; /* Aligns children (including img) vertically in the center */
justify-content: center; /* Horizontally centers the content (optional) */
}
.two-column-layout > div {
flex: 1; /* Assigns equal width to each column */
padding: 10px; /* Optional: adds some spacing inside each column */ */
}
/* Optional: additional styling for the image and text */
.two-column-layout img {
width: 100%; /* Makes the image responsive */
height: auto; /* Maintains aspect ratio */
}
.preserve-lines {
white-space: pre-wrap; /* or pre-wrap */
}
.preserve-lines li {
margin: -15px;
/* line-height: 0.5; */
/* line-height: initial; */
}
</style>
Note:
Миш, посмотри вот на это, вдруг пригодится - про апи и сервисы https://hackmd.io/eEE8YfbZTtqyn340GBz9pQ?both
и вот про тестирование от Миши Трофимова https://hackmd.io/2UgzOd77SCmVay0_TDguNw
вот еще материал, который можно добавить как ссылку для прочтения и ссылаться на него https://12factor.net Очень толково про всякие штуки которые DS без SE бэкграунда могут не знать
Решили, что в каждом уроке будем давать:
1) BigData
2) Работу с командой
### Темы
- Сравнение монолитной архитектуры и микросервисов
- Взаимодействие между сервисами: синхронное и асинхронное, использование message broker и HTTP
- Сериализация данных
- Вспомогательные сервисы: логирование, мониторинг, service discovery, балансировщики и масштабирование(скейлинг), нагрузочное тестирование
- Тестирование сервисов
### Результаты
7. Понимание разработческих особенностей деплоя моделей, умение коммуницировать с разрабами на одном языке, чтобы дать внятное задание на деплой конкретной модели или задеплоить ее самому - в более простых вариантах. Студенты научатся выбирать между монолитной архитектурой и микросервисами, понимать как организовать взаимодействие между сервисами.
---
## Основы проектирования сервисов
Note:
Всем привет! Меня зовут миша свешников и сегодня мы будем изучать основы проектирования сервисов
Для начала Давайте поймем, зачем это нужно знать млопс специалисту.
Допустим, после прошлого урока вы выбрали онлайн сервинг модели через вебсервис.
Если вы работаете в большой компании, то вам придется взаимодействовать с обычными разработчиками или девопсами которые будут внедрять ваш сервис.
А если вы работаете в компании небольшой, то скорее всего вам самим придется и писать сервис и внедрять его тоже. Этот обзорный урок про сервисы как раз и нужен чтобы вы могли это сделать или хотя бы говорили с девопсами на одном языке.
---
### План урока
* Монолит и микросервисы
* Вебсервисы
* Протоколы взаимодействия
* Вспомогательные компоненты
Note:
Итак, современные ит системы состоят из множества взаимодействующих компонентов, а наша задача как млопс инженера встроить в эту сложную систему мл модель.
в этом уроке мы разберем два подхода к архитектуре системы, разберемся с базовыми понятиями из мира вебсервисов, узнаем про различные протоколы взаимодействия, а так же посмотрим на дополнительные компоненты для построения сложных систем.
---
## Кейс

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

/ это типа шестеренки))))))
Note:
Простейшим способом внедрения было бы просто добавить кусочек логики в уже существующий бэкенд магазина. При условии что весь магазин является одним сервисом, такой подход называется монолитным.
В любом случае в сервисе будут разные компоненты, отвечающие за разные куски бизнес логики, напирмер биллинг, срм, какой-нибудь сревис с логистикой. Но они все живут в рамках одного процесса и дергают друг друга напрямую если им нужно. Сюда же мы можем добавить нашу логику с рекомендациями, которую например будет дергать компонент отвечающий за отрисовку страницы товара (САША мб ты знаешь что-то менее абстрактоное что дергает рекомендашки?)
Альтернативой к монолитному подходу является микросервисный подход - в таком случае система состоит из множества отдельных сервисов, которые взаимодействуют друг с другом.
Теперь каждый компонент с бизнес логикой живет в отдельном процессе и может вызывать логику соседних компонентов отправляя в них веб-запросы.
---
### Монолитный подход:
Традиционная архитектура, где все приложение представляет собой единый процесс.
#### Плюсы:
- Единая кодовая база
- Простота разработки и тестирования
- Проще масштабирование для небольших проектов
- Единая среда исполнения для всех компонентов
#### Минусы:
- Сложность поддержания
- Частые пересборки
- Ограничения масштабирования
Note:
Итак, монолитный подход это традиционная архитектура, где все приложение представляет собой единый процесс. Весь код находится в одной кодовой базе, и приложение разворачивается и работает как единое целое.
Давайте поймем какие у такого подхода плюсы и минусы. Начнем с плюсов. Поскольку все компоненты в одном месте, разработка и отладка будут сильно проще - все разворачивается по одной кнопке.
Так же если приложение небольшое, то его проще масштабировать вертикально (то есть просто запускать на более мощных железках). Так же поскольку все крутится в одном процессе, у всех компонентов совпадает среды исполнения (потому что это одна и та же среда исполнения) и не нужно следить чтобы версии библиотек не расходились.
Теперь минусы. С ростом размера проекта поддержание и изменение кода может стать сложным и затратным. На любое изменение в любом из компонентов нужно целиком перезапускать тестирование всего приложение, его сборку и выкат в прод. А так же при росте проекта масштабирование может быть сложным из-за необходимости масштабировать всё приложение, даже если только один компонент требует больших ресурсов. Ну и в целом вертикальное масштабирование довольно быстро упрется в физические пределы.
---
### Микросервисный подход:
Архитектурный стиль, где приложение состоит из множества небольших автономных сервисов, каждый из которых выполняет свою определенную функцию.
#### Плюсы:
- Легкость масштабирования
- Гибкость и независимость
#### Минусы:
- Сложность управления
- Сложность тестирования системы в целом
Note:
Микросервисный подход это архитектурный стиль, где приложение состоит из множества небольших автономных сервисов, каждый из которых выполняет свою определенную функцию. Каждый сервис запущен независимо и общается с другими посредством API.
Плюсы и минусы тут такие же как у монолита, только все наоборот. Микросервисы лучше масштабируются, поскольку подход позволяет масштабировать только необходимые сервисы, а не всё приложение целиком. Кроме того, поскольку компоненты уже общаются друг с другом через веб-запросы, их можно разносить на разные железки, то есть масштабировать горизонтально, в том числе динамически.
Ну и каждый сервис может быть разработан, протестирован и обновлен отдельно, что облегчает и ускоряет работу над изменением функционала.
За это мы платим необходимостью управлять сразу множеством сервисов, и это может повлечь за собой сложности с конфигурированием и обеспечением взаимодействия разных компонентов. Ну и так же усложняется тестирование - из-за большого количества взаимосвязанных сервисов придется писать более сложные интеграционные тесты.
---
### Что выбрать?
Монолит:
* Маленькая команда
* Быстрая разработка/прототипирование
* Простота версионирования и отладки
* Низкие требования к масштабированию
Микросервисы:
* Распределенная команда
* Гибкость в выборе технологий
* Изоляция ошибок и отказоустойчивость
* Независимое развертывание и CI/CD
* Высокие требования к масштабируемости
Note:
Выбор между монолитным и микросервисным подхода зависит от специфики проекта. Монолит может быть проще для начала, но микросервисы обеспечивают гибкость и масштабируемость.
Если у вас небольшая команда, вы хотите разрабатывать быстро или что-то прототипировать, вам нужна простота версионирования кода и отладки, а так же у вас нет высоких требований к масштабируемости, то монолит это ваш вариант.
Если у вас команда побольше и распределенная, вам нужна гибкость в выборе технологий, изоляция ошибок и отказоустойчивость, у вас хорошо настроено развертывание и cicd, либо у вас высокие требования к масштабируемости - смотрите в сторону микросервисов.
---
### Что выбрать для мл?

(только верхний кусок)
<p>
<img src="https://hackmd.io/_uploads/Hy9EeriNT.png" alt="image" width="300" height="auto">
<img src="https://hackmd.io/_uploads/r1Wru-Bua.png" alt="image" width="300" height="auto">
<img src="https://hackmd.io/_uploads/BJwmlrj4T.png" alt="image" width="300" height="auto">
</p>
(на картинках 1 3 названия убрать, сделать названия текстом Batch, Online, Embedded)
<!--



/ связать с 4 лекцией про способы сервинга моделей
/ Саша: думаю можно дать совет про то, когда какой подход лучше, например, такой картинкой. Это будет пример, который привяжет эту диллемму к реальным кейсам. Не знаю куда батч, если он куда-то тут должен попасть.
/ вариант - взять две картинки (рест, стриминг) из предыдущего урока. Тогда что-то сделать с первым абзацем (на отдельный слайд, а вот этот слайд только про мл)
/ проверить, что во всех частях мы говорим сначала не про мл, а потом про мл
-->
Note:
Давайте теперь вспомним, что в нашем кейсе в конце концов должна запускаться МЛ модель. Как мы помним из 4 урока, у нас есть 3 способа сервить модель.
В случае батча модель обычно работает в отдельной среде и в самом приложении будет только логика загрузки результатов, которая уже не содержит мл специфики, поэтому тут рекомендации не отличаются от стандартных.
В случае онлайн сервинга чаще всего удобнее иметь отдельный сервис с моделью, даже если остальная часть в монолите, потому что релизный цикл будет разным у мл и не мл частей. Не мл часть обновляется когда пофиксили какой-то баг или добавили новую фичу, а мл часть надо обновлять когда старая модель устарела, при чем код может вообще не меняться. Ну и кроме того, может потребоваться менять среду исполнения, то есть набор и версии библиотек, так как важно запускать модель в окружении аналогичном тому, в котором она обучалась. А в большой команде часто бывает что у всех немного разные окружения.
В случае ембедед сервинга такая классификация не особо применима потому что у нас вообще может не быть сервисов, но по сути само приложение аналогично монолиту.
---
## Веб сервисы
<img src="https://hackmd.io/_uploads/HyfZifsda.png" width=300>

* Сервис - это приложение, с которым можно взаимодействовать посредством обмена сообщениями заранее определенного формата.
* В случае вебсервисов этими сообщениями являются веб запросы, которые отправляются на какой-то URL.
* Список методов сервиса и формат запросов к ним называются интерфейсом или API (Application Programming Interface).

Note:
Хорошо, теперь вернемся к нашему примеру. Мы решили выделить наш алгоритм в отдельный сервис, чтобы в будущем, когда он станет моделью, нам было проще его обновлять. Давайте подробнее разберем что же такое сервис
Сервис - это приложение, с которым можно взаимодействовать посредством обмена сообщениями заранее определенного формата.
В случае вебсервисов этими сообщениями являются веб запросы, которые отправляются на какой-то URL.
Сервис предоставляет некоторый API или интерфейс, то есть список методов и формат запросов к ним.
В случае вебсервисов методы могут называться эндпоинтами или ресурсами, они входят в урл после адреса самого сервиса. Формат запросов задается некоторым протоколом.
---
#### Протоколы
Протокол - набор правил для общения приложений
Транспортный уровень: TCP, UDP
Уровень приложения:
* HTTP(s) + REST
* grpc
* Soap
* GraphQL
* AMQP, MQTT etc
Note:
Протокол - это набор правил и соглашений, которые определяют, как устройства или приложения обмениваются данными между собой. Они устанавливают формат сообщений, последовательность действий для установления и завершения соединения, а также обработку ошибок и контроль за передачей информации.
Соединением и передачей данных занимаются протоколы транспортного уровеня, такие как TCP или UDP. В случае вебсервисов обычно используется TCP как более надежный.
Нас же интересуют протоколы уровня приложенения, которые определяют как выглядит запрос.
Начнем конечно с http - это самый базовый протокол для передачи данных в интернете - когда вы ходите по сайтам и смотрите мемы скорее всего используется именно он или его секьюрная версия https.
Поверх http придумали архитектурный стиль REST (или Representational State Transfer). Его часто путают с голым http и говорят "рест-сервис", хотя по факту реста там нет. Рестфул сервисы должны использовать правильные http методы для определенных действий, а так же строить названия эндпоинтов по определенным правилам.
Есть и другие протоколы, такие как
grpc - это оптимизированный протокол придуманный гуглом, о нем мы еще поговорим далее.
SOAP - уже слегка устаревашая технология, по сути отличается тем что вместо jsonов кидается xmlками
GraphQL - более модный и молодежный протокол, который позволяет клиенту управлять содержимым ответа - буквально в запросе перечисляются поля, которые должен вернуть сервер, включая вложенные.
И есть еще AMQP, MQTT и другие - протоколы для очередей сообщений. Определяют скорее как работают сами очереди, контент сообщений может быть любой, например json
---
#### HTTP

* Методы: GET, POST, PUT, DELETE и другие
* Параметры:
* path (/api/projects/<project_id>/do_smth)
* query (/do_smth?value=1)
* body
* headers
* Коды состояния: 200+, 400+, 500 ...
* Нет стейта - запросы обрабатываются независимо
* Библиотеки: FastAPI, Flask, Django, urllib, requests
Note:
Давайте разберем http протокол, во-первых потому что он самый базовый, а во-вторых потому что для простейшего сервинга мл моделей его хватит.
Итак, клиент посылает серверу запрос на какой-то из эндпоинт
Из чего вообще состоит запрос?
Во-первых, запрос имеет один из HTTP методов.
Эндпоинт может поддерживать разные методы и иметь разную логику для каждого, точнее это будет считаться разными эндпоинтами
HTTP предоставляет методы GET, POST, PUT, DELETE и некоторые другие. Метод определяет тип операции, которую клиент хочет выполнить на сервере. Например, GET обычно используется для получения данных, POST - для отправки данных на сервер.
В запросе так же можно передавать какие-то параметры. Это может быть часть пути, так называемые path параметры. Выглядит как-то так. Это могут быть квери параметры, кей-велью пары которые указываются после вопросительного знака в урле.
Так же есть само тело запроса, куда можно положить любые данные, часто используется form data или json
Еще есть заголовки или хедеры, это пары ключ-значение, куда обычно кладут метаданные запроса. Они могут содержать информацию о формате передаваемых данных, аутентификации, кешировании и других аспектах, влияющих на обработку запроса или ответа.
После того как сервер обработает запрос, он возвращает клиенту ответ или респонс. Для сообщения о результате выполнения запроса http использует коды состояния.
200+ коды означают успешный запрос, 400+ - клиентскую ошибку (неправильный запрос, нет доступа и тд). знаменитый 404 код говорит что клиент обратился к несуществующему эндпоинту
500й код означает ошибку на сервере
так же есть 100е информационные коды и 300 для редиректов, но вы вряд ли с ними столкнетесь. Подробнее про коды будет в конспекте
Ответ так же содержит хедеры и тело в котором может возвращаться результат обработки запроса.
Последнее, что важно сказать - HTTP является протоколом без состояния (stateless), что означает, что каждый запрос обрабатывается независимо от предыдущих запросов. Для сохранения состояния между запросами может использоваться механизм сессий или передача данных через заголовки.
Для написания вебсервисов на питоне используются такие библиотеки как фастапи, фласк и джанго. для клиентов используются стандартная урллиб или реквестс
<!--
#### REST (хочу убрать)
- часто путают с чистым хттп
- Набор [правил](http://www.restapitutorial.ru/lessons/whatisrest.html#uniform-interface), которые позволяют разного рода системам обмениваться данными и масштабировать приложение.
/ добавить основные правила
- Используется HTTP протокол для обмена данными по сети
- Ресурс - это объект, к которому можно получить доступ по URL
/ в мл не спользуется, достаточно хттп
/ картинка как про хттп но другая
Если при проектировании правила REST соблюдены - такой протокол называется *RESTful*
Note
/ про путаницу в терминологии
REST является скорее архитектурным стилем для построения распределенных систем. REST определяет набор ограничений и правил для построения веб-сервисов, которые могут взаимодействовать друг с другом.
Он подчеркивает использование ресурсов (например, URL) и операций с ними (через HTTP методы) для управления состоянием и обмена данными между клиентом и сервером.
ресурс - это любая информация или объект, к которому можно получить доступ по уникальному идентификатору (URI) через интернет. Этот идентификатор предоставляет клиентам возможность взаимодействовать с ресурсами через различные HTTP методы.
Ресурсы могут представлять собой различные объекты или данные, такие как пользователи, заказы, товары, изображения и т. д. Каждый ресурс имеет свой уникальный адрес (URI), который позволяет клиентам выполнять операции с этим ресурсом, такие как чтение, создание, обновление или удаление, используя соответствующие методы HTTP (GET, POST, PUT, DELETE).
Например, веб-страница, изображение, данные о пользователе или товаре - это всё ресурсы, доступные по определенным URL, и клиенты могут обращаться к ним, чтобы получать нужную информацию или выполнять определенные операции в рамках архитектуры RESTful API.
-->
---
#### Когда использовать HTTP? / Плюсы и минусы
Плюсы
* Широкая распространенность
* Человекочитаемые данные
* Простота отладки
* Гибкость
Минусы
* Гибкость
* Неоптимальная сериализация
Note:
Когда стоит использовать http? В большинстве простых случаев его будет достаточно. Так как http широко распространен, он поддерживается во всех языках, для него существуют много вспомогательных инструментов, таких как сваггер например и самое важное, почти все умеют с ним работать.
Среди других плюсов - человекочитаемые данных (хотя тут зависит от вас), простота отладки опять же за счет широкого инструментария и гибкость - можно наворотить чего вам только захочется.
Но гибкость так же может сыграть с вами злую шутку, ведь раз вы можете наворотить что вам только захочется, это может сделать и ваш коллега, с сервисом которого вам нужно интегрироваться. Впрочем это как раз решается рестом.
Но более важный минус это то что http не поддерживает бинарные данные, то есть запросы нужно дополнительно кодировать в текстовый формат.
---
#### gRPC
Основан на **RPC** - вызове удаленного кода на других машинах.
<!---->

<!--
syntax = "proto3";
package grpc;
message Request {
string userId = 1;
}
message Response {
repeated string itemIds = 1;
}
service Recommendations {
rpc GetRecommendations (Request) returns (Response);
}
-->

<!--
class RecommendationsServicer(object):
"""Missing associated documentation comment in .proto file."""
def GetRecommendations(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
-->

* Написать .proto файл, описывающий интерфейс сервиса
* Скомпилировать его в исходный код на нужном языке
* Имплементировать сгенерированный интерфейс
Note:
Данные недостатки учтены в **gRPC(Google Remote Procedure Call)**
Он основан на **RPC** или remote procedure call. Это класс технологий для вызова функций в другом адресном пространстве, например на удаленных узлах. То есть мы как бы маскируем удаленный вызов под вызов локальной функции.
Чтобы использовать grpc, сначала вам нужно будет написать специальный прото файл, в котором будет описан интерфейс вашего сервиса, то есть список методов и модели для запросов и ответов каждого из них.
Потом вам нужно скомпилировать этот прото файл, на выходе вы получите исходники на питоне с классами для запросов и ответов и абстрактным классом самого сервиса. Вам останется только импортировать все это добро и заимплементить абстрактные методы.
После этого стандартными средствами grpc вы можете запустить сервер со своей логикой и дергать его этим же сгенерированным кодом клиента. Код клиента кстати можно сгенерировать и для другого языка.
---
#### Когда использовать gRPC
**Плюсы:**
* Генерация кода клиента и сервера для разных язков
* Бинарный формат данных **Protobuf**
* Протокол HTTP 2 - потоковая передача данных
Минусы:
* Сложнее разрабатывать
* Нечитаемые запросы
Note:
Когда же стоит использовать жрпц? если вам нужна производительность и ваш интерфейс стабилен, жрпц будет хорошим вариантом.
вот его плюсы
во-первых, Генерация кода стандартными средствами. Используется компилятор **Protoc**, который генерирует код сервера и клиента для множетсва языков
во-вторых, для запросов и ответов используется Бинарный формат данных **Protobuf** котоырй использует сжатии, а значит траффика будет меньше и передача данных будет быстрее
в-третьих, используется Протокол HTTP 2 который поддерживает потоковую передачу данных, бинарный формат запросов, имеет выше скорость
Но минусы конечно тоже есть. grpc банально сложнее разрабатывать потому что в нем больше "движущихся частей" - дополнительные файлы, дополнительные команды для компиляции, автосгенерированный плохочитаемый код. Да и сами запросы неудобно дебажить тк они в бинарном виде.
таким образом,
gRPC может быть предпочтительным в случаях, когда важна высокая производительность, эффективная сериализация данных или нужно связать вместе компоненты написанные на разных языках
---
### Синхронное и асинхронное взаимодействие

Note:
Отлично, допустим мы выбрали подходящий протокол. Теперь основное приложение может отправить запрос в наш сервис, сервис рассчитает рекомендации и вернет ответ клиенту. Такой способ взаимодействия называется синхронным - пока сервис рассчитывает результат клиент просто ждет ответа. Но когда рассчет занимает много времени это может стать проблемой. и проблема эта решается с помощью асинхронного взаимодействия.
При асинхронном взаимодействии отправитель продолжает свою работу без ожидания ответа от получателя. Вместо этого, может быть установлен механизм обратной связи для получения ответа позже.
Простейший вариант асинхронного взаимодействия можно сделать используя два синхронных эндпоинта. Дернув первый, клиент вместо результата получает некоторый айдишник, но зато сразу же. Чтобы получить результат нужно сходить во второй эндпоинт с этим айдишником. Если результата пока нет он просто ничего не вернет
---
Когда использовать синхронное:
* Простые случаи
* Требуется синхронность
Когда использовать асинхронное:
* Долгие операции
* Повышение производительности
* Отложенные операции
Note:
Когда использовать синхронное:
В случаях, когда ответ ожидается немедленно и нет необходимости выполнять другие задачи в ожидании этого ответа.
В сценариях, где порядок выполнения задач важен и следующие шаги зависят от предыдущих.
Когда использовать асинхронное:
Когда операция, которую нужно выполнить, может занять много времени, и не желательно блокировать остальные задачи.
также В случаях, когда можно параллельно выполнять несколько задач.
или Когда результат операции не нужен немедленно и его можно обработать позже.
Выбор между синхронным и асинхронным взаимодействием зависит от специфики конкретной задачи и требований системы. В большинстве случаев синхронное взаимодействие проще в реализации и отладке, но асинхронное взаимодействие может быть более эффективным когда требуется больше производительность или возможна обработка задач в фоновом режиме.
<!--
Сервисы бывают синхронные и асинхронные.
Синхронное взаимодействие подразумевает, что вся логика обработки запроса выполняется перед тем, как клиенту возвращается ответ. Например, мы отправляем запрос на добавление каких-то новых данных в базу и сервис гарантирует, что после возврата ответа клиенту данные уже будут записаны.
Асинхронное взаимодействие подразумевает, что запрос клиента только инициирует действие и ответ клиенту возвращается сразу. При этом обычно есть способ узнать когда действие завершено - например клиенту возвращается уникальный айди его запроса и в другом эндпоинте можно проверить статус выполнения. Или с помощью механизма коллбеков, то есть сервис после выполнения логики может выполнить другой запрос, который уведомит изначального клиента (или кого-то еще) о том, что запрос был выполнен.
Возможно иметь и синхронные и асинхронные эндпоинты в одном сервисе. По сути асинхронное взаимодействие часто организуется как раз через несколько синхронных эндпоинтов.
Асинхронное взаимодействие сложнее организовать, зато такие сервисы проще масштабировать.
Асинхронное взаимодействие используется когда запрос исполняется долго чтобы не тратить ресурсы на поддержание сессии. -->
---
### Взаимодействие через Message Broker

- Продюсер (Producer): отправляет сообщения в очередь или тему в брокере.
- Очередь (Queue) или Тема (Topic): механизм организации сообщений
- Консьюмер (Consumer): обрабатывает сообщения из очереди или темы
Примеры: Apache Kafka, RabbitMQ, Apache ActiveMQ и другие
Note:
Если у вас большая нагрузка и производительность максимально важна,
может иметь смысл вообще все взаимодейстие между сервисами сделать асинхронным используя обмен сообщениями через message broker.
Message broker - это промежуточный компонент, который передает сообщения между различными сервисами в распределенной системе. Он обеспечивает асинхронное взаимодействие между ними.
Обычно мессадж брокеры устроены так. Во-первых, есть
Продюсер - Это компонент, который отправляет сообщения (или эвенты) в определенные очереди (или темы) в брокере.
Очередь (Queue) или Тема (Topic) - Это механизмы, который используется для хранения и организации сообщений внутри message broker. Очереди обычно связаны с моделью point-to-point, где каждое сообщение обрабатывается одним консьюмером. Темы, с другой стороны, поддерживают модель publish-subscribe, где несколько консьюмеров могут подписаться на определенную тему и получать копии сообщений.
Консьюмер - Это компонент, который получает и обрабатывает сообщения из очереди. Для этого он должен подписаться на эту очередь, после чего он начинает получать сообщения из нее для обработки.
Один сервис может одновременно быть и продюсером и консьюмером разных очередей. например, прочитал сообщение из очереди с тасками, выполнил таску, результат положил в другую очередь
---
Использование message broker
- Асинхронная коммуникация
- Устойчивость и надежность
- Масштабируемость
- Распределенная архитектура
Note:
Использование message broker имеет смысл в следующих случаях:
Если система нуждается в обработке сообщений или задач без ожидания мгновенного ответа, message broker позволяет разделить отправку и получение сообщений во времени.
Если нужна надежность: Message broker обеспечивает возможность сохранения сообщений в случае отказов или временных проблем. Это позволяет избежать потери данных и обеспечить их обработку после восстановления системы.
Если нужна Масштабируемость: При увеличении объема обрабатываемых сообщений или компонентов в системе, message broker может помочь распределять нагрузку и обеспечить горизонтальное масштабирование.
При Распределенной архитектуре: В системах, где различные сервисы или компоненты должны обмениваться информацией в распределенной среде, использование message broker упрощает интеграцию и взаимодействие между ними.
---
Резюме
* Выбрали архитектуру (Монолит вс микросервис)
* Выбрали http vs grpc
* Выбрали синк или асинк
* Возможно пересели на message broker
Note:
Итак, теперь мы умеем выбирать архитектуру для проекта - для начала и в простых случаях берем монолит, если важна гибкость и масштабирование - микросервис.
Внутри у сервиса мы выбрали протокол - опять же http для всех базовых сценариев, либо grpc если поняли что нам важна производительность.
Если нам нужно еще больше производительности, то мы можем переделать взаимодействие на асинхронное чтобы клиент не ждал обработки задачи. А если мы хотим максимальную производительность и масштабируемость, то время пересаживаться на message broker.
В следующем видео мы разберемся с дополнительными компонентами для построения сложных систем.
---
## Обвязка
<!---->

<!-- / Сашино пояснение: эта картинка будет выстраиваться шаг за шагом, дополняя текст на слайде, подсвечивая новые элементы
/ не придумал чо нарисовать
/ сказать что это не только для мл валидно, а для всех сервисов. Или наоборот, что это для всех, и в том числе для мл
/ человечек который пырит в комп и когда появляется мониторинг и логи у него на экране тоже это появляется. Альтернативная идея - туман войны вокруг микросервиса.
/ картинка которая сейчас, ей можно пояснить лоад балансер и масштабирование, а для логирование и мониторинга нужно другое
-->
Note:
В прошлом видео мы разобрали архитектуру, сервисы и протоколы для их взаимодействия.
Допустим мы применили эти знания и теперь наш сервис работает и интегрирован с основным приложением. Теперь наша задача сделать так, чтобы он продолжал работать дальше. А если с этим возникают проблемы, то нужно эффективно их решать. Для этого в систему навешивают дополнительные побрякушки, которые помогают заметить когда, как и почему что-то пошло не так.
---
**Логгирование**:

Решения для централизации записи, хранения и визуализации логов.
Инструменты:
- ELK Stack
- Splunk
Note:
Во-первых, при работе каждого приложения генерируются логи - это первое к чему мы обратимся когда что-то пойдет не так.
Гораздо удобнее когда логи всех приложений собраны в одном месте и не нужно скакать по разным железками и руками грепать файлы.
Как раз для этого существуют такие решения как
- ELK Stack (Elasticsearch, Logstash, Kibana): Популярный стек для сбора, обработки и визуализации логов.
- Splunk: Платформа для анализа данных, включая логи.
---
**Мониторинг**:

Решения для наблюдение за работой системы, сбор метрик и оповещение о возможных проблемах или неполадках.
Инструменты:
- Prometheus
- Grafana
Note:
Так же важен мониторинг - Это наблюдение за работой системы, сбор метрик и оповещение о возможных проблемах или неполадках. Под метриками можно понимать разные вещи, например загрузку процессора и количество используемой памяти, или количество и среднее время обработки запросов.
Инструменты:
- Prometheus: Система мониторинга с поддержкой метрик и алертинга.
- Grafana: Инструмент для визуализации данных из различных источников мониторинга.
---
**Масштабирование**:
Возможность системы увеличивать обработку данных или трафика при увеличении нагрузки или объема работы.
Инструменты:
- Kubernetes
- Docker Swarm
- Облачные решения
Note:
Далее - масштабирование. Это возможность системы увеличивать обработку данных или трафика при увеличении нагрузки или объема работы.
Инструменты:
- Kubernetes: Оркестратор контейнеров, который управляет развертыванием и масштабированием контейнеризированных приложений.
- Docker Swarm: Инструмент для управления контейнерами, предоставляющий возможности масштабирования.
- Облачные решения
---
**Балансировщики нагрузки**:

Распределяют входящий трафик между несколькими серверами, обеспечивая эффективность и отказоустойчивость.
Инструменты:
- NGINX
- HAProxy
Note:
Когда у вас несколько инстансов одного и того же сервиса, для равномерного распределения трафика перед ними добавляют такую штуку как балансировщик нагрузки. Вместо конкретного сервера клиенты теперь обращаются к нему, а балансировщик уже роутит запрос на конкретный инстанс. Могут использоваться в связке с сервис дискавери, что добавляет возможность динамически масштабироваться и не только. Например одна из стратегий раскатки новых релизов это когда вы поднимаете новые инстансы рядом со старыми, а потом просто переключаете лоад балансер, добиваясь нулевого даунтайма
Инструменты:
- NGINX: Веб-сервер, который также может быть использован в качестве балансировщика нагрузки.
- HAProxy: Высокопроизводительный балансировщик для TCP и HTTP-сервисов.
---
Note:
Каждый из этих компонентов решает определенные проблемы, связанные с управлением и обеспечением надежности работы веб-сервисов в распределенных системах. Как правило, они используются в сочетании для создания надежной и масштабируемой инфраструктуры.
---
### Еще полезности
- Стратегии развертывания
- Автоматическое восстановление
- Управление конфигурацией
- Infrastructure as Code
Читайте ссылки из конспекта :books:
Note:
Помимо того что мы разобрали, во время развертывания веб сервисов мы можем столкнуться и с другими компонентами. Разбирать мы их не будем, но в конспекте будут ссылки на почитать - их изучение позволит вам чуть больше погрузиться в мир разработки и развертывания веб-сервисов, который нужно понимать млопсу.
- стратегии развертывания. Если вы деплоите модель сами, и к тому же управляете траффиком, полезно знать про такие стратегии как blue-green deployment, canary releases, and rolling updates. Мы уже упомянули их в прошлом уроке, но отметим, что все то же самое может использоваться и для обычных веб сервисов без мл
- Автоматические роллбэки и процедуры восстановления. Если вы обновляете веб сервисы с мл моделями в проде, то вашей же задачей будет поднимать упавшие сервисы и откатываться к предыдущим версиям модели, если новая перестала нормально работать
- Управление окружением и конфигурацией. Необходимо чтобы исключить возможность расхождения в работе модели на проде и в деве. Кроме того, часто мы используем секреты в работе веб сервисов и мы должны знать базовые принципы обращения с ними, такие например, как что их не надо хранить в коде, а в виде ENV переменных задаваемых в рантайме.
- Infrastructure as Code (IaC): DevOps подход, при котором вся инфраструктура записывается как некий конфиг, который можно "накатить" с помощью специальных тулзов. К Такому конфигу можно применять те же практики, что мы применяем к обычному коду, например версионирование.
Если вы в своей работе столкнетесь с чем-то из этого списка, мы рекомендуем вспомнить об этом и посмотреть в конспект, чтобы изучить источники.
в конспект:
https://12factor.net
https://martinfowler.com/bliki/BlueGreenDeployment.html
https://learnk8s.io/kubernetes-rollbacks
https://selectel.ru/blog/infrastructure-as-code-iac/
https://spacelift.io/blog/infrastructure-as-code
---
### Итоги
* Монолит и микросервисы
* Вебсервисы
* Протоколы взаимодействия
* Вспомогательные компоненты
Note:
В этом уроке мы познакомились с двумя видами архитектры - монолитной и микросервисной.
Разобрались с тем что из себя представляют вебсервисы, как выбирать подходящий протокол и связывать их с остальной системой.
Ну и в конце поговорили про то какие существуют вспомогательные компоненты для того чтобы сделать вашу систему удобнее и надежнее.
На следующих уроках мы на практике разберем как написать сервис для сервинга модели и как завернуть его в контейнер.
---
/ конспект
## Коды ответов
| Код | Название | Описание |
| -------- | -------- | -------- |
| 200 | OK | Запрос выполнен успешно |
| 201 | Created | Возвращается при каждом создании ресурса в коллекции|
| 204 | No Content | Нет содержимого. Это ответ на успешный запрос, например, после DELETE) |
- https://habr.com/ru/post/440900/ - статья про коды и REST
- https://developer.mozilla.org/ru/docs/Web/HTTP/Status - полная таблица кодов
| Код | Название | Описание |
| -------- | -------- | -------- |
| 400 | Bad Request | Ошибка на стороне Клиента. Например, неправильный синтаксис запроса, неверные параметры запроса и т.д.|
| 401 | Unauthorized | Клиент пытается работать с закрытым ресурсом без предоставления данных авторизации |
| 403 | Forbidden | Сервер понял запрос, но отказывается его обрабатывать |
| 404 | Not found | Запрашивается несуществующий ресурс |
| 405 | Method Not Allowed | Клиент пытался использовать метод, который недопустим для ресурса. Например, указан метод DELETE, но такого метода у ресурса нет|
| 500 | Server error|Общий ответ об ошибкtе на сервере, когда не подходит никакой другой код ошибки|
---
# То шо ниже убираем
## Тестирование
## Зачем вообще нужно тестирование?
Тестирование позволяет убедиться, что система работает так, как мы этого ожидаем. И еще важнее, что она продолжает работать именно так после внесения каких-либо изменений.
---
## Тестирование в классической разработке
----
Тесты можно грубо разделить на несколько категорий в зависимости от того, что они проверяют и на каком уровне системы применяются.
----
Выделяют несколько типов тестов:
- unit
- integration
- system, end-2-end, e2e
- acceptance
----
### Юнит-тесты
- Юнит - тесты одного участка кода в изоляции от остальной системы.
- Есть вход, есть выход, проверяем совпадение.
- Как правило, покрывают небольшой участок кода / функцию.
Примеры: сортировка массива, на вход - [1 ,4 ,0, 2], выход - [0, 1, 2, 4]
----
### Интеграционные тесты
- Интеграционный тест - тест того, как разные компоненты системы взаимодействуют друг с другом.
- Пример: интеграция приложения с базой данных.
- Инициализация - очищаем тестовую базу, кладем в нее значение.
- Запускаем часть системы
- Проверяем, что ответ соотвествует нашим ожиданиям.
----
### Системное тестирование
- Системное тестирование - проверяет, что система целиком работает.
- Пример
- Развернули приложение со всеми тестовыми базами,
- Отправили запрос на выдачу рекомендаций,
- Проверили что ответ пришел
- И что он _разумный_
----
### Приемочное тестирование
- Приемочное / продакшн тестирование - проверяет, что система работает "как ожидается" в бою.
- Пример:
- Выдерживание нагрузки и времени ответа
- Переключение реплик
- Плавная деградация
- И все то, что без реальной нагрузки проверить сложно
{"title":"05 - DevOps ликбез","description":"Миш, посмотри вот на это, вдруг пригодится - про апи и сервисы https://hackmd.io/eEE8YfbZTtqyn340GBz9pQ?both","slideOptions":"{\"theme\":\"white\",\"showNotes\":true}","contributors":"[{\"id\":\"e0bc91de-98f7-46f8-a3a9-852912833a93\",\"add\":4882,\"del\":679},{\"id\":\"da65023d-0b33-4856-963e-92ab2158270b\",\"add\":95655,\"del\":59496}]"}