.NET Разработчик
6.44K subscribers
416 photos
2 videos
14 files
1.99K links
Дневник сертифицированного .NET разработчика.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2250. #SystemDesign101
Начинаю серию постов про System Design. Это будут небольшие шпаргалки, описывающие ту или иную технологию. Надеюсь, вам понравится.

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

SOAP
- Зрелый, всеобъемлющий, на основе XML;
- Лучше всего подходит для корпоративных приложений.

RESTful
- Популярный, простые в реализации методы HTTP;
- Идеально подходит для веб-сервисов.

GraphQL
- Язык запросов, запрашивает только нужные данные;
- Снижает сетевые издержки, ускоряет ответы.

gRPC
- Современный, высокопроизводительный;
- Подходит для архитектур микросервисов.

WebSocket
- Двунаправленные, постоянные соединения в реальном времени;
- Идеально подходит для обмена данными с малой задержкой.

Webhook
- Управляемый событиями, использует обратные вызовы HTTP, асинхронный;
- Уведомляет системы о событиях.

Источник: https://github.com/ByteByteGoHq/system-design-101
День 2254. #SystemDesign101
REST API или GraphQL


REST
Использует стандартные методы HTTP, такие как GET, POST, PUT, DELETE для операций CRUD.
Хорошо работает, когда вам нужны простые, единообразные интерфейсы между отдельными сервисами/приложениями.
Стратегии кэширования просты в реализации.
Может потребоваться несколько циклов для сбора связанных данных из отдельных конечных точек.

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

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

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

Источник:
https://github.com/ByteByteGoHq/system-design-101
День 2261. #SystemDesign101
Как работает gRPC?
RPC (Remote Procedure Call – Удалённый Вызов Процедур) называется «удалённым», потому что он обеспечивает связь между удалёнными сервисами, когда они развёрнуты на разных серверах в архитектуре микросервисов. С точки зрения клиента он действует как локальный вызов функции.

На схеме выше показан поток данных для gRPC.
1. Выполняется REST-запрос от клиента. Тело запроса обычно имеет формат JSON.

2–4. Сервис заказов (клиент gRPC) получает REST-запрос, преобразует его и выполняет вызов RPC к сервису платежей. gPRC кодирует заглушку клиента в двоичный формат и отправляет её на низкоуровневый транспортный уровень.

5. gRPC отправляет пакеты по сети через HTTP2. Благодаря двоичному кодированию и сетевой оптимизации gRPC примерно в 5 раз быстрее JSON.

6–8. Сервис платежей (сервер gRPC) получает пакеты из сети, декодирует их и вызывает серверное приложение.

9–11. Результат возвращается из серверного приложения, кодируется и отправляется на транспортный уровень.

12–14. Сервис заказов получает пакеты, декодирует их и отправляет результат клиентскому приложению.

Источник: https://github.com/ByteByteGoHq/system-design-101
День 2267. #SystemDesign101
Что Такое Веб-Хук?

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

Существует два способа общения с внешним PSP.

1. Поллинг (polling)
После отправки платёжного запроса в PSP сервис платежей постоянно опрашивает PSP о статусе платежа. Рано или поздно PSP вернёт статус.
Недостатки:
- Требует ресурсов от сервиса платежей.
- Прямое взаимодействие сервиса платежей с внешним поставщиком услуг создаёт уязвимости безопасности.

2. Веб-хук (webhook)
Мы можем зарегистрировать веб-хук во внешнем сервисе. Это означает: вызовите определённый мной URL, когда у вас появятся обновления по запросу. Когда PSP завершит обработку, он сделает HTTP-запрос для обновления статуса платежа.

Платёжному сервису больше не нужно тратить ресурсы на опрос статуса платежа.

Что, если PSP не вызовет URL? Можем настроить задание для проверки статуса платежа каждый час.

Веб-хуки часто называют обратными API или push-API, потому что сервер отправляет HTTP-запросы клиенту. При использовании веб-хука нужно обратить внимание на 3 вещи:
- Разработать правильный API для вызова внешнего сервиса.
- Настроить правила в API-шлюзе из соображений безопасности.
- Зарегистрировать правильный URL обратного вызова во внешнем сервисе.

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

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

Источник:
https://github.com/ByteByteGoHq/system-design-101
День 2275. #SystemDesign101
Как Улучшить Производительность API?


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

2. Асинхронное ведение журнала
Синхронное логирование пишет на диск при каждом вызове и может замедлить работу системы. Асинхронное логирование сначала отправляет логи в буфер без блокировки и немедленно возвращает управление. Логи будут периодически сбрасываться на диск. Это значительно снижает накладные расходы на ввод-вывод.

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

4. Сжатие данных
Запросы и ответы можно сжимать с помощью gzip и подобных ему алгоритмов, чтобы размер передаваемых данных был намного меньше. Это ускоряет загрузку и скачивание.

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

Источник: https://github.com/ByteByteGoHq/system-design-101
День 2281. #SystemDesign101
Версии Протоколов HTTP


HTTP 1.0 был окончательно доработан и полностью задокументирован в 1996 году. Каждый запрос к одному и тому же серверу требует отдельного TCP-соединения.

HTTP 1.1 был опубликован в 1997 году. TCP-соединение можно оставлять открытым для повторного использования (постоянное соединение), но это не решало проблемы HOL-блокировки* (head-of-line).
*HOL-блокировка возникает, когда количество разрешённых параллельных запросов в браузере исчерпано, последующие запросы должны ждать завершения предыдущих.
Также введены:
- Статус продолжения: чтобы избежать отклонения запроса сервером, клиент может сначала отправить только заголовки запроса и проверить, получит ли он код статуса продолжения (100);
- Новые HTTP-методы: PUT, PATCH, DELETE, CONNECT, TRACE и OPTIONS

HTTP 2.0 был опубликован в 2015 году. Он решает проблему HOL с помощью мультиплексирования запросов, что устраняет HOL-блокировки на уровне приложений, но они всё ещё существуют на транспортном (TCP) уровне.
Как вы можете видеть на схеме, HTTP 2.0 представил концепцию «потоков» HTTP: абстракцию, которая позволяет мультиплексировать различные обмены HTTP в одно и то же TCP-соединение. Каждый поток не обязательно должен быть отправлен по порядку.
Также добавлены:
- Приоритетность запросов: возможность установить числовой приоритет в пакете запросов, например, получить CSS перед JS.
- Автоматическое сжатие GZip.
- Серверный push: сервер пытается предсказать ресурсы, которые будут запрошены в ближайшее время и проактивно отправляет эти ресурсы в кэш клиента.

Первый черновик HTTP 3.0 был опубликован в 2020 году. Он использует QUIC вместо TCP для базового транспортного протокола, тем самым устраняя HOL-блокировку на транспортном уровне.
QUIC (Quick UDP Internet Connections) разработан для обеспечения гораздо меньшей задержки для HTTP-соединений. Как и HTTP/2, это мультиплексный протокол, но HTTP/2 работает по одному TCP-соединению, поэтому обнаружение потери пакетов и повторная передача, обрабатываемые на уровне TCP, могут блокировать все потоки. QUIC запускает несколько потоков по UDP и реализует обнаружение потери пакетов и повторную передачу независимо для каждого потока, так что в случае возникновения ошибки блокируется только поток с данными в этом пакете.
По состоянию на октябрь 2022 около 26% сайтов используют HTTP 3.

Источник: https://github.com/ByteByteGoHq/system-design-101
День 2292. #SystemDesign101
Объяснение Модели OSI
Как данные передаются по сети? Зачем нам нужно так много уровней в модели OSI (Open Systems Interconnection)?

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

Шаг 1: Когда устройство A отправляет данные устройству B по сети через протокол HTTP, сначала добавляется заголовок HTTP на прикладном уровне.

Шаг 2: Затем к данным добавляется заголовок TCP или UDP. Они инкапсулируются в сегменты TCP на транспортном уровне. Заголовок содержит порт источника, порт назначения и порядковый номер.

Шаг 3: Сегменты инкапсулируются с заголовком IP на сетевом уровне. Заголовок IP содержит IP-адреса источника/получателя.

Шаг 4: Добавляется заголовок MAC на канальном уровне с MAC-адресами источника/получателя.

Шаг 5: Инкапсулированные фреймы отправляются на физический уровень и передаются по сети в двоичном формате.

Шаги 6–10: Когда устройство B получает двоичные данные из сети, оно выполняет процесс деинкапсуляции, который является обратным процессу инкапсуляции. Заголовки удаляются слой за слоем, и в итоге устройство B может прочитать данные.

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

Источник: https://github.com/ByteByteGoHq/system-design-101
День 2320. #SystemDesign101
Прямой Прокси и Обратный Прокси

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

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

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

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

Использование:
- защита и сокрытие серверов локальной сети и их характеристик,
- защита от распространенных веб-атак, таких как DoS или DDoS,
- шифрование и дешифрование SSL-сообщений,
- балансировка нагрузки между несколькими серверами,
- кэширование статического и динамического контента,
- сжатие содержимого для уменьшения времени его загрузки,

Источники:
-
https://github.com/ByteByteGoHq/system-design-101
-
https://ru.wikipedia.org/wiki/Прокси-сервер
-
https://ru.wikipedia.org/wiki/Обратный_прокси
День 2326. #SystemDesign101
Распространённые Алгоритмы Балансировки Нагрузки


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

2. Закреплённый Круговой Алгоритм (Sticky Round Robin)
Усовершенствование кругового алгоритма. Если первый запрос Алисы отправляется в сервис A, следующие запросы также отправляются в сервис A.

3. Взвешенный Круговой Алгоритм (Weighted Round Robin)
Администратор может указать вес для каждого сервиса. Сервисы с более высоким весом обрабатывают больше запросов, чем другие.

4. Хэш IP/URL
Применяет хеш-функцию к IP или URL входящих запросов. Запросы направляются в соответствующие экземпляры на основе результата хеш-функции.
Преимущества
- Постоянство сессии – алгоритм гарантирует, что запросы от одного клиента всегда попадают на один и тот же сервер.
- Облегчает кеширование данных на стороне сервера для конкретных клиентов.
Недостатки
- Если много пользователей приходят из одного диапазона IP, один сервер может быть перегружен.
- Неэффективен в средах, где IP клиентов часто меняются (мобильные сети).
- Может привести к неравномерной нагрузке, если некоторые клиенты генерируют больше трафика.

Динамические алгоритмы
5. Наименьшее Количество Соединений (Least Connections)

Новый запрос отправляется в экземпляр сервиса с наименьшим количеством одновременных подключений.
Преимущества
- Более мощные серверы естественным образом будут обрабатывать больше запросов и, следовательно, иметь больше соединений. И напротив, менее мощные серверы будут получать меньше запросов, что предотвращает их перегрузку.
- Гибкость – если один сервер начинает работать медленнее, он будет получать меньше новых запросов.
Недостатки
- Алгоритм считает все соединения одинаковыми, не учитывая, что некоторые запросы могут быть более ресурсоёмкими.
- Вновь добавленный сервер может получить слишком много запросов, т.к. изначально у него 0 соединений.

6. Наименьшее Время Ответа (Least Time)
Новый запрос отправляется в экземпляр сервиса с самым быстрым временем ответа. Аналогичный алгоритм - Наименьший объем трафика (Least Bandwidth).
Преимущества
- Учёт текущей производительности серверов и динамическая адаптация обеспечивают оптимальный баланс и наилучший пользовательский опыт.
- Хорошо работает с серверами разной мощности и приложениями с разными характеристиками.
Недостаток
- Сложность реализации – требует постоянного мониторинга и анализа производительности серверов, отсюда повышенная нагрузка на балансировщик.

Источники:
-
https://github.com/ByteByteGoHq/system-design-101
-
https://proglib.io/p/6-glavnyh-algoritmov-balansirovki-nagruzki-2024-08-06