Тестирование бэкенда
Что такое клиент-серверная архитектура и для чего она нужна
Клиент-серверная архитектура представляет собой модель взаимодействия между программными компонентами, где один компонент (клиент) обращается к другому компоненту (серверу) для получения данных
- Клиент: Клиент – это устройство или приложение, которое отправляет запросы на сервер для получения данных или выполнения определенной задачи. Клиент может быть написан на разных языках программирования и работать на разных устройствах.
- Сервер: Сервер предоставляет данные или услуги клиенту. Он обрабатывает запросы, выполняет определенные функции и отправляет обратно ответы на запросы клиенту. Сервер обычно работает на мощном выделенном оборудовании и имеет специальное программное обеспечение для обработки запросов.
- Канал связи: в будущем мы познакомимся с таким понятием как API. Пока запомни, что канал связи между клиентом и сервером это API.
- Клиент отправляет запрос на сервер с определенной просьбой или задачей.
- Сервер получает этот запрос, обрабатывает его и отправляет обратно ответ или результат выполнения задачи клиенту.
- Взаимодействие клиента и сервера основано на протоколах коммуникации, таких как HTTP, TCP/IP и других.
Давай рассмотрим клиент-серверную архитектуру на примере обычного визита в ресторан. В этой аналогии:
- Клиент: Вы (клиент) - приходите в ресторан (сервер) для заказа еды и получения обслуживания. Вы выступаете в роли клиента, который хочет получить определенные услуги или продукты.
- Сервер: Ресторан - это сервер, предоставляющий услуги и продукты. Он имеет шеф-повара, кухню, официантов, которые обрабатывают заказы клиентов и предоставляют им необходимые блюда и услуги.
- Процесс заказа и обслуживания: Вы (клиент) приходите в ресторан (сервер) и делаете заказ у официанта (клиентская часть). Официант принимает ваш заказ (запрос) и передает его на кухню (серверная часть) для приготовления блюд. После этого официант (сервер) возвращает вам заказанные блюда (ответ).
- Взаимодействие: Здесь вы (клиент) взаимодействуете с рестораном (сервером) через официанта (интерфейс), чтобы получить то, что вам нужно (данные или услуги).
- Сетевое взаимодействие: В данном случае, вы (клиент) общаетесь с рестораном (сервером) через официанта (интерфейс), используя сетевое взаимодействие (заказы, запросы и передачу данных).
Это аналогия показывает, как клиенты (ваш запрос) обращаются к серверам (ресторану) для получения определенных услуг или продуктов, используя интерфейс (официант) для взаимодействия с сервером и получения необходимых данных или услуг.
Пример когда может быть несколько клиентов:
Также стоит отметить что может быть несколько клиентов, несколько серверов, несколько баз данных. Зависит от реализации.
Клиенты в клиент-серверной архитектуре представляют собой программные компоненты или устройства, которые обращаются к серверам для получения данных или услуг. Вот несколько примеров клиентов в различных областях:
Веб-браузеры: Браузеры, такие как Google Chrome, Mozilla Firefox, Safari и другие, являются клиентами, которые обращаются к веб-серверам для загрузки веб-страниц, изображений, файлов стилей и другого контента.
Postman - наверняка вы слышали про этот инструмент, когда изучали сферу тестирования. В будущем мы больше погрузимся в него, но пока определение: это популярный инструмент для тестирования API. Также является клиентом, так как запрашивает данные с сервера
Swagger - то же самое, как и с постманом, но сваггер это документация для API, предоставляемая разработчиками
Для более хорошего понимания советую посмотреть это видео
API
Как передать данные с сервера на клиент и наоборот? В этом нам поможет API
Если говорить на техническом языке, то: API - это сокращение от Application Programming Interface (интерфейс прикладного программирования). Это набор определенных правил, протоколов и инструментов, которые позволяют различным программным приложениям взаимодействовать между собой. API определяет способы, с помощью которых приложения могут отправлять запросы друг к другу для получения данных или выполнения определенных операций. Это позволяет разным системам обмениваться информацией и функциональностью без необходимости раскрытия своей внутренней реализации.
Если говорить по-простому, то: представь, что API - это набор инструкций, по которым разные приложения могут общаться между собой, как если бы они говорили на одном языке. Он определяет, как одно приложение может запрашивать данные или просить другое приложение выполнить определенную задачу. Наподобие того, как ты можешь отправить текстовое сообщение другу, чтобы получить информацию или попросить сделать что-то определенное. API - это своего рода "мостик" между разными программами, который помогает им работать вместе
Рассмотрим пример: у тебя есть мобильное приложение для погоды. Оно использует API погодного сервиса, чтобы получать данные о текущей погоде. Приложение отправляет запрос через API этого сервиса, указывая, что оно хочет узнать погоду в определенном месте. API сервиса обрабатывает этот запрос, выполняет необходимые действия (например, обращается к своим базам данных) и отправляет обратно запрошенную информацию о погоде обратно в приложение.
API определяет набор правил и инструкций, которые определяют способы взаимодействия между разными программами или компонентами программного обеспечения. Многое из перечисленного будет тебе непонятно, но пока стоит запомнить, не погружаясь основательно. Некоторые из основных правил общения, которые могут быть частью API:
- Форматы данных: Определение того, какие форматы данных используются для запросов и ответов. Например, данные могут передаваться в формате JSON, XML. В будущем мы поговорим об этом подробнее
- Методы запросов: Указание доступных действий или операций, которые можно выполнить с помощью API. Например, GET для получения данных, POST для отправки данных на сервер, PUT для обновления существующих данных и DELETE для удаления. В будущем мы поговорим об этом подробнее
- Аутентификация и безопасность: Правила для защиты доступа к API, такие как использование токенов, ключей доступа, аутентификации по паролю или другим методам, чтобы только разрешенные пользователи могли использовать API и его функциональность.
- Описание эндпоинтов(Например, Notion/read): Эндпоинты - это конечные точки в API, определяющие конкретные адреса или URL, по которым можно отправлять запросы для выполнения определенных действий или получения определенных данных.
- Документация и справочные материалы(Swagger): API часто сопровождаются документацией, объясняющей, как использовать его функции, как формировать запросы и как обрабатывать ответы.
Монолит/Микросервисы
Микросервисы — это архитектурный подход к разработке программного обеспечения, при котором приложение строится как набор маленьких, независимых и самодостаточных сервисов, каждый из которых выполняет конкретную бизнес-функцию.
Основные принципы микросервисной архитектуры:
- Разделение на независимые сервисы: Приложение разбивается на отдельные сервисы, каждый из которых работает автономно и выполняет ограниченный набор задач.
- Каждый сервис — одна задача: Каждый микросервис обслуживает конкретный бизнес-процесс или функциональность, что облегчает масштабирование и развитие.
- Независимое развертывание и масштабирование: Поскольку сервисы независимы друг от друга, их можно разрабатывать, тестировать, разворачивать и масштабировать независимо.
- Коммуникация через API: Микросервисы взаимодействуют друг с другом посредством API, обеспечивая связь и обмен данными.
- Технологическая гетерогенность: Каждый сервис может быть разработан с использованием разных технологий и языков программирования.
- Упрощение поддержки и разработки: Разбиение на микросервисы облегчает поддержку кодовой базы, позволяет быстрее внедрять изменения и улучшать функциональность.
Преимущества микросервисной архитектуры включают гибкость, масштабируемость, возможность быстрой разработки и развертывания новых функций, а также лучшую изоляцию ошибок и улучшенную поддержку кода. Однако внедрение такой архитектуры также требует управления сложностью взаимодействия между сервисами и управления их жизненным циклом.
- Гибкость и масштабируемость: Микросервисы позволяют гибко масштабировать и управлять каждым сервисом независимо от других, что улучшает гибкость системы.
- Изолированность и надежность: Изоляция каждого сервиса обеспечивает большую надежность системы в целом. Ошибка в одном сервисе не влияет на работу других.
- Легкость в разработке и обновлении: Каждый сервис можно разрабатывать, тестировать и обновлять независимо от других, что упрощает процессы разработки и развертывания.
- Гетерогенность технологий: Разные сервисы могут использовать различные технологии и языки программирования в зависимости от их потребностей.
- Улучшенное масштабирование и нагрузка: Позволяет масштабировать только необходимые сервисы, а не всю систему, что экономит ресурсы и повышает эффективность.
- Сложность управления: Управление множеством сервисов требует больше усилий по мониторингу, развертыванию, управлению конфигурациями и т.д.
- Сложность разработки в начале: Разработка микросервисной архитектуры может быть сложнее на старте проекта, чем создание монолита.
- Сложность тестирования и отладки: Интеграционное тестирование и отладка могут быть сложнее из-за взаимодействия между сервисами.
- Сетевая задержка: Взаимодействие между сервисами по сети может приводить к увеличению задержек и проблемам с производительностью.
- Размер команды и культурные изменения: Работа с микросервисами требует более распределенной и согласованной командной работы, что может потребовать культурных изменений.
Монолит — это тип архитектуры программного обеспечения, в которой вся функциональность приложения интегрирована и разворачивается как единое целое. В монолитной архитектуре весь код, отвечающий за различные функции приложения, обычно размещается в одном центральном модуле или приложении.
Основные черты монолитного приложения:
- Единое приложение: Весь функционал (базы данных, бизнес-логика, пользовательский интерфейс и др.) находится в одном приложении.
- Единый код: Весь код находится в одном репозитории и компилируется/разворачивается как единое целое.
- Сложность масштабирования: При увеличении функциональности или нагрузки монолитные приложения могут стать сложными в поддержке и масштабировании.
- Одна технологическая платформа: Обычно используется одна технологическая платформа или стек технологий для всего приложения.
- Ограниченная гибкость: Внесение изменений в монолит может быть сложным из-за тесной связанности компонентов.
- Простота начального развертывания: Приложение разворачивается как единое целое, что облегчает начальное развертывание.
Хотя монолитные приложения просты в начале, с развитием проекта они могут столкнуться с проблемами масштабируемости, сложности поддержки и монолитностью кодовой базы. Это приводит к появлению альтернативных архитектурных решений, таких как микросервисная архитектура, которая стремится решить некоторые из этих проблем путем разделения функционала на отдельные сервисы.
- Простота разработки и старта: Единая кодовая база упрощает разработку и начальное развертывание, что особенно полезно на ранних этапах проекта.
- Простота тестирования: Тестирование интеграции между компонентами проще, поскольку они находятся внутри одного приложения.
- Производительность: Внутренняя коммуникация между компонентами может быть более эффективной по сравнению с удаленными вызовами в микросервисной архитектуре.
- Простота масштабирования на начальных этапах: Пока приложение небольшое или нагрузка невысока, монолит может легко масштабироваться вертикально.
- Меньшие накладные расходы: Для небольших приложений или приложений с низкой нагрузкой монолит может быть более эффективным без дополнительной инфраструктуры для управления множеством сервисов.
- Сложность масштабирования: При росте приложения могут возникнуть сложности с масштабированием из-за необходимости масштабировать все компоненты сразу.
- Сложность разработки и поддержки в долгосрочной перспективе: Увеличение размера приложения и его функциональности делает кодовую базу сложнее для понимания и поддержки.
- Гибкость и изменения: Внесение изменений в монолит может быть сложным из-за тесной связанности компонентов.
- Одна технологическая платформа: Обычно используется одна технологическая платформа или стек технологий для всего приложения, что может быть ограничивающим.
- Одна точка отказа: Ошибка в одной части приложения может повлиять на всю систему.
Рекомендую к просмотру данное видео
Архитектура приложений (Монолит/Микросервисы 2)
В современной разработке применяют 2 подхода к организации: монолит и микросервисы.
Примечательно, что может быть интеграция через API двух систем, одна из которых — монолит, а другая — микросервис.
- Простота и легкость разработки. Компоненты монолитной системы тесно связаны, поэтому писать и тестировать такой код сравнительно легко. Вы поддерживаете единую базу кода, и это упрощает понимание общей логики приложения.
- Производительность и эффективность. Поскольку все компоненты выполняются в рамках одного процесса, отпадает нужда в межпроцессном взаимодействии. То есть, более быстрое время выполнения и минимальные временные затраты.
- Среда совместно используемых данных. У всех компонентов есть прямой доступ к той же базе данных, что позволяет беспрепятственно обмениваться этими данными. Тем самым устраняется необходимость в сложных механизмах синхронизации.
В чем минусы монолитной архитектуры?
- Масштабирование. Масштабировать монолиты не так уж просто, ведь все приложение масштабируется как единое целое. В итоге, если дополнительные ресурсы нужны только для определенных компонентов, это может вылиться в их нерациональное использование.
Помните, как выше мы говорили о том, что один из плюсов монолитов – внутренняя производительность? В этом же заключается и их головная боль. Ведь, если подумать, весь монолит потребляет ресурсы сервера, на котором работает (будь то выделенный сервер, виртуальная машина и что-то еще). А если у вас есть сложный продукт с множеством опций, то вся система начнет хромать, когда для работы одной из таких функций потребуются дополнительные ресурсы. Представьте себе ситуацию: пользователь загрузил большой файл, который нужно обработать. И это внезапно сказалось на процессе входа. Пользовательский опыт в данном случае будет просто ужасным.
Монолиты часто «завязаны» на определенном стеке технологий. И добавление новых технологий или фреймворков чревато перепроектированием всего приложения. Такое скудное технологическое разнообразие ограничивает ваши возможности и замедляет дальнее развитие приложения (вы когда-нибудь пробовали поддерживать 10-летнего монолита? Конечно же, там вы не найдете ни намека на код React или Next JS).
Что до развертывания и обслуживания, то монолитные архитектуры – слегка громоздкие. Любые изменения или обновления требуют повторного развертывания всего приложения, и это ведет к увеличению времени простоя и возможным сбоям.
Итого: монолитная архитектура предлагает простоту и эффективность; в ней используется единая база кода и общие данных. Но в монолитах отмечаются явные проблемы с масштабируемостью, развертыванием/обслуживанием, а также ограниченное технологическое разнообразие.
Представьте себе современный город с множеством обособленных зданий, каждое из которых используется для определенной цели. В этом и заключается суть микросервисов – они разбивают приложения на более мелкие автономные сервисы, которые взаимодействуют друг с другом. Если вернуться к тому же примеру с монолитами, то все население вашего города будет находиться внутри одного гигантского здания, в котором каждый человек живет, работает и совершает покупки.
В чем плюсы микросервисной архитектуры?
В микросервисной архитектуре есть множество плюсов, которые привлекли внимание разработчиков по всему миру.
- Одним из главных преимуществ данной архитектуры служит масштабируемость и гибкость. Каждый микросервис можно масштабировать независимо от других, исходя от его конкретных потребностей. Такая детализированная масштабируемость позволяет эффективно распределять ресурсы и обеспечивает оптимальную производительность, особенно при работе с меняющимися требованиями к рабочей нагрузке.
- Также для микросервисов характерно технологическое разнообразие и автономия. Каждый сервис работает обособленно, так что можно подобрать для него разные технологии и фреймворки – если только их интерфейсы не зависят от технологий (например, используют HTTP API или веб-сокеты). Это открывает целый мир возможностей и позволяет командам выбирать лучшие инструменты для реализации конкретных задач. Микросервисы похожи на динамичную экосистему, в которой каждый сервис может эволюционировать и улучшаться в собственном темпе.
- Непрерывная доставка и развертывание – еще одни важные плюсы микросервисной архитектуры. Сервисы не имеют привязки друг к другу, благодаря чему их можно разрабатывать, тестировать и развертывать обособленно. Это сокращает срок вывода на рынок, ведь новые функции и обновления можно развертывать без изменения всего приложения. У вас как будто есть целый гибкий набор сервисов, готовых адаптироваться и улучшаться в любое время. Кроме того, все это позволяет работать над каждым микросервисом сразу нескольким командам, благодаря чему существенно ускоряется время разработки.
В целом, микросервисы – довольно удобные и продуманные. Но, как и везде в нашей отрасли, какой бы гениальной технология не была, ей никогда не стать эталоном. В микросервисах есть ряд существенных недочетов, о которых необходимо знать.
В свободе и гибкости микросервисов есть и обратная сторона.
- Одним из недочетов микросервисной архитектуры являются сложности с управлением распределенной системой. Для координации взаимодействия между сервисами, обеспечения согласованности данных и обработки сбоев необходимо скрупулезное проектирование и внедрение. Ведь, по сути, если у вас есть множество микросервисов, то им же нужно как-то обращаться между собой, обмениваться данными… а как быть, если один из них вдруг выйдет из строя? Как восстановить после этого другие сервисы? Где каждый сервис будет хранить свои данные? Все эти вопросы необходимо задать себе до запуска продукта. А теперь представьте, что у вас есть 30 микросервисов… или даже 100 (причем для крупных систем это не так уж и много). Сможете ли вы ответить на все эти вопросы по каждому сервису? Теперь понимаете, в чем дело? Также следует учитывать издержки на координацию и взаимодействие процессов. Чем больше сервисов становится, тем сложнее поддерживать их взаимодействие и согласованность данных. Получается, что для реализации эффективных процессов взаимодействия нужны дополнительные средства (например, API или очереди сообщений).
Итого: микросервисная архитектура может похвастаться масштабируемостью, технологическим разнообразием и непрерывной доставкой. Однако все это сопряжено с рядом трудностей, связанных со сложностью этой архитектуры, распределенными системами и взаимодействием между сервисами.
Сравнение монолит vs микросервисы. Основные отличия — масштабируемость и отказоустойчивость.
Например, если у нас в интернет-магазине всё разделено на микросервисы (например, мс под пользователей, мс под оформление заказов, мс под остатки на складах и тд), то при упавшем микросервисе, который отвечает за статистику, вся система в целом продолжит работать и пользователь сможет купить. В случае же падения какой-то части монолита падает вся система целиком.
Также, если потребовалось внедрить какой-то новый продукт в нашу систему на другом стеке для увеличения скорости, то на мс мы сможем сделать так, например: система на Java, а нам нужен модуль для обработки каких-то данных, который будет написан на Go другой командой, то так сделать вполне можно.
С монолитом так не получится сделать.
На практике конфигурации взаимодействия могут быть самые разнообразные, например:
- 1 продукт — 1 монолит — 1 команда разработки
- 1 продукт - 1 микросервис — 1 команда разработки
- 3 продукта — 3 микросервиса — 1 команда разработки
- 1 продукт — 5 микросервисов — 5 команд разработки
- 1 продукт — 15 микросервисов — 1 команда разработки, разбитая на 2 подкоманды
Пример реализации микросервисной архитектуры:
Принципы рест архитектуры/rest api + json
Рекомендую к просмотру данное видео
Одной из ключевых особенностей REST API является его архитектурный стиль, основанный на наборе принципов и ограничений, обеспечивающих простоту, удобство использования и масштабируемость. Вот основные особенности REST API:
1. Ресурсы и URI: Ресурсы представляют собой объекты или данные (например, пользователи, товары, заказы). REST API использует уникальные идентификаторы ресурсов (URI), которые предоставляют доступ к ним (например, /users, /products/123).
2. HTTP Методы (GET, POST, PUT, DELETE): REST API использует стандартные методы HTTP для выполнения операций над ресурсами. Например, GET для получения ресурсов, POST для создания, PUT для обновления, DELETE для удаления.
3. Представление ресурсов (Representation): Ресурсы могут быть представлены в различных форматах (например, JSON, XML). Клиенты могут запрашивать и получать представления ресурсов в удобном для них формате.
4. Самоописываемые сообщения (Self-descriptive messages): Каждый запрос и ответ содержат достаточную информацию, чтобы их можно было понять без необходимости дополнительной документации. Это включает метаданные, кэширование, управление кэшем и другую информацию.
5. Состояние и безопасность (Stateless and Security): RESTful сервисы должны быть без состояния, что означает, что сервер не должен хранить состояние между запросами. Каждый запрос должен содержать всю необходимую информацию для его обработки. Также REST API должны быть защищены, обеспечивая безопасность передаваемых данных.
6. Кэширование: REST API может использовать кэширование, позволяющее клиентам кэшировать ответы сервера для улучшения производительности и снижения нагрузки на сервер.
Эти принципы позволяют создавать гибкие, легко масштабируемые и удобные для использования API, которые обеспечивают эффективное взаимодействие между клиентами и серверами.
JSON — это Java Script Object Notation, самый популярный формат обмена данными между приложениями. Этот формат очень похож на объекты JavaScript.
JSON-Объект заключён в фигурные скобки {} в начале объекта и в конце, состоит из формата ключ-значение, разделённого двоеточием, каждая из пар отделяется запятой.
Ключ всегда имеет строковый тип данных — заключён в кавычки "brand".
Значение может быть одним из следующих типов данных:
- a string (строка, например: "brand" или ⚠️"123" — может сбить с толку, но т.к. число в кавычках, то тип данных именно строковый)
- a number (число, например: 123)
- an object (объект, например: { "brand": “Apple” } )
- an array (массив, например: [ "apple", "orange", "kiwi" ]
- a boolean (Булев, Логический тип данных, т.е. одно из 2х значение истина и ложь: либо true, либо false)
- null (нул, отсутствие какого-либо объектного значения, не путать с нулём: 0 — это конкретное значение, тип данных которого число)
{
"brand": "Apple",
"model": "iPhone 15 Pro Max",
"isAvailable": true,
"display": 6.69,
"memories": [256, 512, 1024],
"features": {
"tripleCamera": true,
"faceId": true,
"touchId": false,
"eSIM": true
}
}
При выполнении REST API запросов необходимо выставить в Headers Content-type application/json. Postman такой флаг в заголовках поставит автоматически при использовании JSON в body запроса.
HTTP
HTTP (Hypertext Transfer Protocol) - это протокол передачи данных, который используется для обмена информацией между клиентами и серверами в сети Интернет. Как выглядит работа HTPP?
У протокола HTTP есть расширение, которое называется HTTPS. В чем же разница?
ПHTTPS (HTTP Secure) - это версия HTTP, которая добавляет шифрование с использованием SSL/TLS для обеспечения безопасной передачи данных. SSL/TLS использует алгоритмы для шифрования передаваемых данных, что не позволяет злоумышленникам считать их при передаче через зашифрованное соединение. Эти данные включают потенциально конфиденциальную информацию, такую как имена, адреса, номера кредитных карт и другие финансовые данные.
SSL-сертификат – это цифровой сертификат, удостоверяющий подлинность веб-сайта и позволяющий использовать зашифрованное соединение. Аббревиатура SSL означает Secure Sockets Layer – протокол безопасности, создающий зашифрованное соединение между веб-сервером и веб-браузером.
HTTP (Hypertext Transfer Protocol) определяет различные методы запросов, которые клиент может отправлять серверу для выполнения различных действий.
Например: GET: Используется для запроса содержимого ресурса. Запрос с методом GET не должен изменять состояние сервера.
POST: Используется для отправки данных для обработки на сервере. Обычно используется для отправки данных форм, загрузки файлов и других операций, которые могут изменить состояние сервера или создать новый ресурс.
PUT: Используется для загрузки или обновления содержимого ресурса на сервере. Если ресурс не существует, метод PUT может создать новый.
DELETE: Используется для удаления ресурса на сервере.
PATCH: Используется для частичного обновления ресурса на сервере. Клиент отправляет только те данные, которые должны быть изменены, без необходимости отправки полного представления ресурса.
В контексте протокола HTTP, методы запросов классифицируются на "безопасные" (safe) и "небезопасные" (unsafe) на основе их воздействия на данные на сервере. Безопасные методы предназначены для получения данных и не должны влиять на состояние ресурсов на сервере, т.е. не должны инициировать какие-либо изменения данных или их структуры.
- GET: Этот метод используется для запроса данных с сервера. Он должен только извлекать данные и не вносить изменений в состояние данных на сервере. GET-запросы могут быть кэшированы и оптимизированы сервером.
- HEAD: Похож на метод GET, но сервер возвращает только заголовки ответа без тела сообщения. HEAD позволяет извлечь метаданные, связанные с ресурсом, не передавая сам ресурс. Этот метод используется для проверки действительности ресурсов, изменений контента и т.д.
- OPTIONS: Используется для запроса описания параметров связи для целевого ресурса без вызова какого-либо действия на сервере. OPTIONS может использоваться для проверки возможностей веб-сервера или для проверки поддерживаемых методов HTTP для конкретного ресурса без его извлечения или изменения.
Они важны для обеспечения целостности данных на сервере, позволяя клиентам запрашивать информацию без риска нечаянного изменения данных или их состояния. Это особенно критично в веб-приложениях, где неавторизованные или неожиданные изменения могут иметь серьёзные последствия.
Идемпотентные методы - это методы, которые либо не изменяют состояние в базе данных, либо изменяют состояние только при первом запросе. В случае повторной отправки идентичного запроса, состояние в базе данных не изменяется. Идемпотентными методами являются: GET, PUT, DELETE Например, ты отправишь GET запрос на получение этой страницы несколько раз и у тебя не изменится ответ и не изменится состояние сервера. Это и называют Идемпотентным методом.
Как Выглядит и что включает в себя HTTP запрос и HTTP ответ
Запрос на сервер в контексте веб-разработки обычно осуществляется с использованием протокола HTTP или HTTPS и состоит из нескольких ключевых компонентов, которые сообщают серверу, что именно клиент (например, веб-браузер или мобильное приложение) хочет сделать, и какие данные он отправляет. Вот основные элементы запроса на сервер:
Определяет тип операции, которую нужно выполнить. Наиболее распространенные методы HTTP включают:
GET
для запроса данных от сервера.POST
для отправки данных на сервер для создания или обновления ресурса.PUT
для полного обновления существующего ресурса.DELETE
для удаления ресурса.PATCH
для частичного обновления ресурса.
2. URL (Uniform Resource Locator)
Указывает сервер и точный адрес (путь) ресурса на сервере, с которым клиент хочет взаимодействовать. URL включает в себя протокол (например, http или https), доменное имя или IP-адрес сервера, порт (опционально) и путь к ресурсу.
Содержат дополнительную информацию о запросе и клиенте, отправляющем запрос. Заголовки могут включать тип содержимого (Content-Type), типы принимаемого содержимого (Accept), параметры аутентификации, куки (Cookies) и многое другое. Заголовки позволяют клиенту и серверу передавать дополнительные параметры и настройки.
Необязательный компонент, присутствующий в некоторых типах запросов (например, POST, PUT, PATCH), содержащий отправляемые данные. В теле запроса могут находиться данные формы, файлы, JSON или XML-структуры и т. д. Тело запроса используется для передачи информации от клиента к серверу.
5. Параметры запроса (Query Parameters)
Опциональные ключи и значения, которые добавляются к URL запроса после знака вопроса (?
). Параметры запроса используются для передачи дополнительной информации серверу, например, для фильтрации результатов или указания определённой страницы пагинации.
Хотя они обычно передаются в заголовках запроса, они играют важную роль в управлении сессиями и аутентификации пользователя, позволяя серверу идентифицировать возвращающихся пользователей.
Эти компоненты вместе формируют HTTP-запрос, который отправляется серверу. Сервер затем обрабатывает запрос согласно своей логике и отправляет ответ обратно клиенту, обычно также в форме, состоящей из статуса ответа, заголовков и тела ответа.
Как выглядит ответ на сервере?
Ответ сервера в контексте веб-коммуникации, осуществляемой через протокол HTTP или HTTPS, состоит из нескольких ключевых компонентов. Эти компоненты предоставляют клиенту (например, веб-браузеру) информацию о результате обработки его запроса. Вот основные элементы ответа сервера:
1. Статусная строка (Status Line)
Содержит версию протокола HTTP, используемую сервером, числовой статусный код ответа, указывающий на результат обработки запроса, и текстовое описание статусного кода. Например, "HTTP/1.1 200 OK" или "HTTP/1.1 404 Not Found".
2. Заголовки ответа (Response Headers)
Предоставляют дополнительную информацию о сервере и о том, как должен быть обработан ответ. Заголовки могут включать тип содержимого (Content-Type
), дату и время ответа (Date
), параметры кэширования (Cache-Control
) и другие данные, связанные с безопасностью, сжатием, куки и т.д.
Отделяет заголовки ответа от тела ответа. Эта пустая строка является обязательной и указывает на окончание заголовков.
4. Тело ответа (Response Body)
Содержит данные, запрошенные клиентом. В зависимости от типа запроса и статусного кода, тело ответа может содержать запрошенную веб-страницу, данные в форматах JSON или XML (для REST API), сообщение об ошибке или может быть пустым (например, при ответе со статусным кодом 204 No Content).
- Веб-страницы: При запросе веб-страницы тело ответа обычно содержит HTML-код страницы.
- API-запросы: При запросах к API тело ответа часто содержит данные в формате JSON или XML, которые могут представлять результаты запроса, данные сущности или сообщение об ошибке.
- Загрузка файлов: При загрузке файлов с сервера тело ответа содержит бинарные данные файла.
Каждый из этих компонентов играет важную роль в обеспечении эффективного взаимодействия между клиентом и сервером. Статусный код помогает клиенту определить результат обработки запроса (успешно, ошибка, перенаправление и т.д.), заголовки предоставляют метаинформацию о ответе и его обработке, а тело ответа содержит собственно запрошенные данные.
HTTP-заголовки (HTTP Headers) — несколько строчек текста в определенном формате, которые либо уточняют запрос, либо описывают содержимое тела сообщения Примеры заголовков можно посмотреть тут
HTTP-заголовки позволяют клиенту и серверу отправлять дополнительную информацию с HTTP-запросом или ответом. Они содержат не чувствительное к регистру название, а затем после двоеточия непосредственно значение. HTTP-заголовки можно разделить на 3 основные группы
- General Headers (Общие заголовки) - используются в запросах и ответах
- Request Headers (Заголовки запроса) - используются только в запросах
- Response Headers (Заголовки ответа) - используются только в ответах
HTTP-заголовки решают проблему непонимания между браузером и сервером, помогая "перевести" запросы и ответы так, чтобы обе стороны "поняли" друг друга. Они содержат информацию о странице, браузере, нужных действиях и помогают в безопасности и скорости загрузки
Примеры часто встречаемых заголовков:
General Headers (Общие заголовки) и Request Headers (Заголовки запроса)
Accept
: указывает тип данных, которые клиент может обработать.Authorization
: содержит информацию о доступе к ресурсу.Cache-Control
: управляет кэшированием ресурсов.Connection
: управляет соединением между клиентом и сервером.Content-Length
: указывает размер тела сообщения.Content-Type
: указывает тип содержимого сообщения.User-Agent
: указывает информацию о браузере или клиенте
Response Headers (Заголовки ответа)
Cache-Control
: управляет кэшированием ресурсов.Content-Language
: указывает язык, используемый для тела сообщения.Content-Length
: указывает размер тела сообщения.Content-Type
: указывает тип содержимого сообщения.Date
: указывает дату и время отправки сообщения.Location
: указывает URL, на который клиент должен перейти.Set-Cookie
: устанавливает cookie на клиенте.
Статус коды и что они обозначают
HTTP-статус-коды представляют собой трехзначные числа, которые сервер отправляет в ответ на запрос клиента. Они указывают на успешность выполнения запроса, перенаправление, ошибку сервера и другие сценарии. Вот краткий обзор некоторых основных HTTP-статус-кодов:
1xx (Сотые) - информационные коды:
- 100 Continue: Сервер понял запрос клиента и продолжает обработку.
- 101 Switching Protocols: Сервер согласен изменить протокол соединения в ответ на запрос клиента.
2xx (Двухсотые) - успешные коды:
- 200 OK: Запрос успешно выполнен. Это стандартный код для успешных HTTP-запросов.
- 201 Created: Ресурс успешно создан в ответ на POST-запрос.
- 204 No Content: Запрос успешен, но ответ не содержит информации (например, при обновлении данных).
3xx (Трехсотые) - коды перенаправления:
- 301 Moved Permanently: Ресурс перемещен на постоянной основе. Клиент должен использовать новый URL для доступа к ресурсу.
- 302 Found (или Moved Temporarily): Ресурс временно перемещен. Клиент должен использовать новый URL, но запросы к старому URL могут продолжаться.
- 304 Not Modified: Ресурс не был изменен с момента последнего запроса. Клиент может использовать кэшированную версию.
4xx (Четырехсотые) - коды ошибок клиента:
- 400 Bad Request: Запрос некорректен или не может быть обработан сервером.
- 401 Unauthorized: Клиент не авторизован для доступа к ресурсу.
- 403 Forbidden: Клиент имеет доступ к ресурсу, но сервер отказывает в выполнении запроса.
- 404 Not Found: Запрашиваемый ресурс не найден на сервере.
- 405 Method Not Allowed: Метод запроса не разрешен для данного ресурса.
5xx (Пятисотые) - коды ошибок сервера:
- 500 Internal Server Error: Общая ошибка сервера. Обычно это свидетельствует о программной ошибке или неполадке на сервере.
- 502 Bad Gateway: Сервер, действуя в качестве шлюза или прокси, получил недопустимый ответ от вышестоящего сервера.
- 503 Service Unavailable: Сервер временно не может обрабатывать запросы. Это может быть вызвано перегрузкой или временной неполадкой.
- 504 Gateway Timeout: Сервер, действуя в качестве шлюза или прокси, не получил своевременный ответ от вышестоящего сервера.
Это лишь несколько примеров HTTP-статус-кодов, их полный список более обширен. Важно знать эти коды, чтобы эффективно диагностировать проблемы при взаимодействии с веб-серверами и понимать, как обрабатывать ответы сервера в ваших приложениях.
Кэш и куки
Постман/сваггер
Postman - это инструмент для тестирования API (интерфейсов программирования приложений). Он предоставляет удобный пользовательский интерфейс для отправки HTTP-запросов к вашему серверу и просмотра ответов. Вот пошаговая инструкция по работе с Postman:
- Установка Postman:
- Скачайте и установите Postman с официального сайта: postman.com.
- Открытие Postman:
- Создание нового запроса:
- Настройка запроса:
- Введите имя запроса в поле "Request Name".
- Выберите HTTP-метод (GET, POST, PUT, DELETE и т. д.) в выпадающем меню рядом с URL.
- Введите URL вашего API в поле "Enter request URL".
- Настройка параметров запроса (если необходимо):
- Отправка запроса:
- Просмотр ответа:
- Сохранение запроса:
- Если запрос работает правильно, вы можете сохранить его для последующего использования, нажав на кнопку "Save" в правом верхнем углу.
- Коллекции:
- Тестирование API:
- Используйте функционал Postman для автоматизации тестирования API, написания сценариев и мониторинга.
- Оформление запросов:
Работа с заголовками в Postman важна для настройки запросов и передачи необходимой информации между клиентом и сервером. Вот как вы можете управлять заголовками в Postman:
- Добавление заголовков к запросу:
- Откройте запрос в Postman.
- В разделе "Headers" добавьте новый заголовок, указав его имя и значение.
- Нажмите "Send" для отправки запроса с указанными заголовками.
- Работа с типами содержимого (Content-Type):
- Установите заголовок "Content-Type" для указания типа данных, передаваемых в теле запроса. Например, для отправки JSON установите значение "application/json".
- Postman часто автоматически устанавливает заголовок "Content-Type" в соответствии с типом тела запроса.
- Авторизация с использованием заголовков:
- Некоторые API требуют авторизацию через заголовки. Добавьте заголовок "Authorization" и укажите в нем данные авторизации (например, токен).
- Пользовательские заголовки:
- Вы можете добавить пользовательские заголовки, которые необходимы для вашего конкретного API. Введите имя и значение заголовка в соответствующие поля.
- Передача параметров через заголовки:
- Некоторые параметры, такие как язык или версия API, могут передаваться через заголовки. Укажите соответствующие заголовки с необходимыми значениями.
- Просмотр ответа с заголовками:
- После отправки запроса, вы можете просмотреть ответ, включая заголовки. Вкладка "Headers" в разделе ответа покажет все заголовки, возвращенные сервером.
- Глобальные переменные для заголовков:
- Если вам часто приходится использовать одни и те же заголовки в разных запросах, вы можете использовать глобальные переменные для их удобного управления и переиспользования.
- Предопределенные заголовки:
Управление заголовками в Postman дает вам гибкость настройки запросов и адаптации их к требованиям вашего API. Важно ознакомиться с документацией вашего API, чтобы узнать, какие заголовки требуются для корректной работы запросов.
Без сниппетов (автоматизированных фрагментов кода) в Postman, вы все равно можете вручную использовать консоль для отладки и вывода информации. Вот несколько способов работы с консолью в Postman без использования сниппетов:
- Консоль Postman:
- В правом нижнем углу Postman есть вкладка "Console". Здесь отображаются различные логи, включая информацию о запросах, ответах и любых ошибках.
- Просто откройте вкладку "Console" и посмотрите на вывод после выполнения запросов.
- Вывод в консоль вручную:
- В каждом запросе, в разделе "Tests", вы можете использовать объект
console
для вывода информации в консоль. - Пример использования:
javascriptCopy code console.log("Запрос выполнен успешно");
- Использование переменных в логах:
- В логах можно использовать переменные и данные, полученные в результате выполнения запросов. Например:
javascriptCopy code console.log("ID пользователя: " + pm.response.json().user_id);
- Уровни логирования:
- Postman предоставляет уровни логирования (log levels) для вывода различных видов сообщений. Вы можете использовать
console.log
,console.warn
, иconsole.error
в своих тестах в зависимости от важности сообщения. - Пример отслеживания событий:
- В разделе "Tests", вы можете использовать JavaScript для отслеживания событий. Например, выводить в консоль сообщение при получении определенного статус-кода:
javascriptCopy code if (responseCode.code === 200) { console.log("Запрос успешен"); }
- Просмотр подробных данных ответа:
- В консоли вы можете просмотреть более подробные данные о ответе, такие как тело ответа, статус-код, заголовки и другие детали.
- Вручную анализ ответа:
- При отладке без сниппетов, вы можете вручную изучать тело ответа, заголовки и другие данные для проверки корректности выполнения запроса.
- Просмотр истории:
Использование консоли вручную в Postman может быть полезным для быстрой отладки и понимания происходящих событий во время разработки и тестирования запросов.
curl -X 'POST' \\ '<https://petstore.swagger.io/v2/pet>' \\ -H 'accept: application/json' \\ -H 'Content-Type: application/json' \\ -d '{ "id": 45, "category": { "id": 1, "name": "тЕСТ" }, "name": "Собачка", "photoUrls": [ "Тест" ], "tags": [ { "id": 45, "name": "Кршка" } ], "status": "available" }'
Разберем на примере этого курла Разберем заголовки Postman-Token -
Postman-Token
- это заголовок (header), который иногда используется в HTTP-запросах для управления сеансами в Postman. Этот токен используется для идентификации уникального сеанса в Postman и может быть полезен при отправке запросов с помощью Postman.
В Postman, когда вы отправляете запрос, Postman автоматически вставляет заголовок Postman-Token
в запрос. Это значение токена обычно уникально для каждого сеанса или запроса, что позволяет идентифицировать конкретный запрос, выполняемый в рамках данного сеанса.
Этот механизм может использоваться для предотвращения отправки повторных запросов в некоторых случаях, например, если сервер требует уникальных токенов в каждом запросе. Однако, стоит отметить, что использование Postman-Token
не является обязательным или стандартным для всех HTTP-запросов, и многие серверы могут игнорировать этот заголовок.
Если вы разрабатываете свой собственный API или взаимодействуете с API других сервисов, обратитесь к документации API для определения, следует ли использовать заголовок Postman-Token
и как он влияет на ваши запросы. В большинстве случаев использование этого заголовка не требуется, так как большинство серверов корректно обрабатывают запросы без него.
Content-Type
- это заголовок HTTP-запроса и ответа, который указывает тип медиа-контента, передаваемого в теле запроса или ответа. Этот заголовок позволяет серверу и клиенту определить, как обрабатывать тело сообщения.
Примеры некоторых значений Content-Type
:
application/json
: Данные в теле запроса или ответа представлены в формате JSON.application/xml
: Данные в теле запроса или ответа представлены в формате XML.text/html
: Данные в теле запроса или ответа представлены в формате HTML.multipart/form-data
: Используется при отправке файлов или форм-данных.application/x-www-form-urlencoded
: Данные формы, отправляемые в теле запроса, закодированы в URL-кодированной форме.
Установка правильного Content-Type
важна, поскольку она говорит серверу, как правильно интерпретировать тело запроса, а клиенту - как правильно обрабатывать тело ответа.
Пример использования Content-Type
в HTTP-запросе:
httpCopy code POST /api/example Host: example.com Content-Type: application/json { "key": "value" }
В данном примере, серверу сообщается, что данные в теле запроса представлены в формате JSON.
Content-Length
- это заголовок HTTP, который указывает размер тела запроса или ответа в байтах. Этот заголовок помогает серверу и клиенту определить длину содержимого и, таким образом, корректно прочитать данные.
Пример использования Content-Length
в HTTP-запросе:
httpCopy code POST /api/example Host: example.com Content-Type: application/json Content-Length: 26 { "key": "value" }
В данном примере, Content-Length
равен 26 байтам, что соответствует размеру тела запроса (в данном случае, JSON-данные).
Этот заголовок полезен в ситуациях, когда сервер ожидает знать точный размер тела запроса для его корректной обработки, например, при передаче данных методом POST или при использовании метода PUT. В ответах сервера Content-Length
указывает клиенту, сколько байтов данных следует ожидать в теле ответа.
Важно отметить, что использование Content-Length
не всегда обязательно. В некоторых случаях, особенно при использовании Transfer-Encoding: chunked, сервер и клиент могут обойтись без явного указания длины содержимого.
Host
- это обязательный заголовок HTTP-запросов, который указывает на имя хоста (домена), к которому отправляется запрос. Этот заголовок помогает серверу определить, к какому веб-сайту или веб-службе направлен запрос, особенно в случае, когда на одном физическом сервере размещено несколько веб-приложений с разными доменными именами.
Пример использования Host
в HTTP-запросе:
httpCopy code GET /path/resource Host: example.com
В данном примере, Host: example.com
указывает, что запрос направлен к веб-сайту, расположенному по доменному имени "example.com".
Host
также может включать порт, если запрос отправляется на определенный порт сервера. Например:
httpCopy code GET /path/resource Host: example.com:8080
В данном случае, запрос направлен на порт 8080 веб-сайта с доменным именем "example.com".
Заголовок Host
является одним из обязательных заголовков в HTTP/1.1 и используется для правильного маршрутизации запросов на сервере. Он необходим, когда веб-сервер обслуживает несколько доменных имен на одном IP-адресе и порту.
Заголовок User-Agent
в HTTP-запросе предоставляет информацию о клиенте (браузере, приложении или другом агенте), отправляющем запрос. Этот заголовок используется сервером для определения, с какого клиента пришел запрос, что может быть полезно для подготовки и отправки контента, который наилучшим образом подходит для конкретного типа клиента.
Пример использования заголовка User-Agent
:
httpCopy code GET /path/resource Host: example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
В данном примере, User-Agent
содержит информацию о браузере Chrome, который работает на операционной системе Windows.
Этот заголовок может быть использован сервером для:
- Определения совместимости: Сервер может использовать информацию о User-Agent для определения, какой браузер или клиент отправил запрос, и предоставить соответствующий контент или стили.
- Статистики и аналитики: User-Agent может использоваться для сбора статистики о том, какие браузеры или клиенты чаще всего посещают сайт.
- Обнаружения ботов: Некоторые веб-серверы могут использовать заголовок
User-Agent
для обнаружения посещений от поисковых роботов или других автоматизированных агентов.
Важно отметить, что клиент может подменять или изменять свой User-Agent
, и поэтому эта информация не всегда является абсолютно точной или надежной
Заголовок Accept
в HTTP-запросе указывает на типы контента (медиа-типы), которые клиент (браузер, приложение и т.д.) может принять от сервера в ответе. Этот заголовок сообщает серверу о предпочтениях клиента в отношении форматов данных.
Пример использования заголовка Accept
:
httpCopy code GET /path/resource Host: example.com Accept: application/json, text/html
В данном примере, Accept
сообщает серверу, что клиент готов принять ответ в формате JSON (application/json
) или HTML (text/html
).
Сервер может использовать этот заголовок для принятия решения о том, в каком формате предоставить запрошенные данные. Например, если клиент предпочитает JSON, и сервер может предоставить данные в обоих форматах (JSON и HTML), то сервер может выбрать JSON как формат ответа.
Пример ответа сервера с учетом Accept
:
httpCopy code HTTP/1.1 200 OK Content-Type: application/json { "key": "value" }
В данном ответе сервер удовлетворяет предпочтения клиента и отправляет данные в формате JSON.
Accept
может содержать различные медиа-типы и их параметры качества (quality parameters), которые указывают, насколько предпочтителен каждый тип. Например:
httpCopy code Accept: text/html;q=0.9, application/json;q=0.8
В этом случае, клиент предпочитает HTML, но также готов принять JSON с немного меньшим приоритетом.
Заголовок Accept-Encoding
в HTTP-запросе указывает на поддерживаемые клиентом методы сжатия (кодирования) данных, которые сервер может применить к содержимому перед отправкой обратно клиенту. Это помогает уменьшить объем передаваемых данных и улучшить производительность, особенно при передаче больших объемов текстового или бинарного контента.
Пример использования заголовка Accept-Encoding
:
httpCopy code GET /path/resource Host: example.com Accept-Encoding: gzip, deflate
В данном примере, клиент указывает, что он поддерживает методы сжатия данных gzip
и deflate
. Это означает, что сервер может сжимать ответ перед отправкой, если он поддерживает один из этих методов.
Пример ответа сервера с учетом Accept-Encoding
:
httpCopy code HTTP/1.1 200 OK Content-Type: text/plain Content-Encoding: gzip ... (сжатые данные)
В данном ответе сервер сжимает данные методом gzip
перед отправкой клиенту, так как клиент выразил поддержку этого метода в заголовке Accept-Encoding
.
Accept-Encoding
может содержать несколько методов сжатия, указанных в порядке предпочтения. Сервер может выбрать один из поддерживаемых методов с учетом предпочтений клиента и возможностей сервера. Если сервер не поддерживает ни один из методов сжатия, он может отправить данные без сжатия.
Примечание: Заголовок Accept-Encoding
является важным для оптимизации передачи данных по сети, особенно при работе с ресурсами веб-страниц и API, где объем данных может быть значительным.
Заголовок Connection
в HTTP используется для управления параметрами соединения между клиентом и сервером. Он может содержать различные значения, которые определяют, как следует обрабатывать соединение после завершения текущего запроса-ответа. Например, указание на закрытие соединения или его сохранение для последующих запросов.
Пример использования заголовка Connection
:
httpCopy code GET /path/resource Host: example.com Connection: keep-alive
В данном примере, заголовок Connection: keep-alive
указывает на то, что клиент запрашивает у сервера сохранение соединения для возможных последующих запросов.
Некоторые значения, которые может принимать заголовок Connection
:
- close: Сервер должен закрыть соединение после завершения текущего запроса и ответа. Это является значением по умолчанию, если заголовок
Connection
отсутствует. - keep-alive: Сервер должен сохранить соединение открытым после завершения текущего запроса и ответа, чтобы оно могло быть использовано для последующих запросов. Это может сэкономить время на установке нового соединения для каждого запроса.
- Upgrade: Используется, например, при использовании HTTP/2.0, чтобы указать на возможность обновления протокола.
- TE: Указывает, какие кодировки поддерживает клиент (Transfer-Encoding), что может использоваться для оптимизации передачи данных.
Примечание: В некоторых случаях, например, при использовании прокси-серверов, значения заголовка Connection
могут меняться по мере прохождения запроса через сеть.
В Postman, заголовок Authorization
используется для передачи учетных данных (обычно в форме токена) в HTTP-запросе. Однако различные типы аутентификации могут использовать разные значения и форматы для этого заголовка. Рассмотрим некоторые из наиболее распространенных вариантов:
- Basic Auth (Базовая аутентификация):
- В случае Basic Auth, заголовок
Authorization
выглядит следующим образом:Гдеbase64(username:password)
- это строка, представляющая собой базовую аутентификацию, гдеusername
иpassword
представляют учетные данные пользователя в кодировке base64.bashCopy code Authorization: Basic base64(username:password)
- Bearer Token (Токен аутентификации):
- В случае использования токена, заголовок
Authorization
может выглядеть следующим образом:ГдеYOUR_ACCESS_TOKEN
- это токен, который предоставляется для аутентификации.makefileCopy code Authorization: Bearer YOUR_ACCESS_TOKEN
- API Key (Ключ API):
В Postman, при отправке запроса, вы можете указать тип аутентификации в соответствующем разделе запроса и заполнить соответствующие поля (например, имя пользователя и пароль для Basic Auth, токен для Bearer Auth, и т.д.).
Примечание: Важно соблюдать правила безопасности при использовании аутентификации и не хранить учетные данные в открытом виде в запросах. Использование HTTPS также важно для защиты учетных данных в процессе передачи через сеть.
Swagger (OpenAPI Specification, OAS). Инструмент для документирования API.
Swagger — это инструмент для автоматического формирования документации API. Сваггер — это просто устоявшееся название любой спецификации, подобная история с “ксероксом”.
Посмотреть на него можно здесь: https://auth.dev-cinescope.store/swagger
Несмотря на то, что через сваггер можно выполнять запросы, всё же это именно инструмент для документации, а не для тестирования API. Для тестирования используются другие инструменты, например, Postman, т.к. сваггер сильно ограничен в возможностях — по сути, мы только можем выполнить запрос с разными данными, не более. Даже заголовки или url изменить мы там не можем.
В сваггере описаны методы, которые используются на бэкенде, обязательные и необязательные поля, типы данных, а также ожидаемые ответы и статус коды успешных и неуспешных вызовов.
Внизу сваггера описана модель (Schema) каждого метода и использующимся типом данных для каждого из ключей.
Из Swagger можно экспортировать коллекцию запросов в Postman через Import swagger.json.
Swagger коллекция — это просто большой JSON файл:
Объяснение работы постмана и сваггера на примере (смотрим чтобы понимать принципы, код нам писать не нужно будет)
Логи
В идеале логи пишутся во время работы всех IT-систем, однако если писать все подряд и «складывать в кучу», полезная информация превратится в хаос. Чтобы упростить поиск и чтение логов, их делят на уровни. Основных четыре:
1) Debug — запись масштабных переходов состояний, например, обращение к базе данных, старт/пауза сервиса, успешная обработка записи и пр.
2) Warning — нештатная ситуация, потенциальная проблема, может быть странный формат запроса или некорректный параметр вызова.
4) Fatal — тотальный сбой работоспособности, когда нет доступа к базе данных или сети, сервису не хватает места на жестком диске.
Дополнительно файл логирования может расширяться записями еще двух уровней:
1) Trace — пошаговые записи процесса. Полезен, когда сложно локализовать ошибку.
2) Info — общая информация о работе службы или сервиса.
Работа с уровнями логирования регламентируется методическими документами и внутренними правилами организации. В них может определяться соответствие источника сообщения уровню логирования, значимость, порядок обработки каждого уровня и другие параметры.
Для удобства обработки логов их делят на типы:
- системные, связанные с системными событиями
- серверные, отвечающие за процесс обращения к серверу
- почтовые, работающие с отправлениями
- логи баз данных, которые отражают процессы обращения к базам данных
- авторизационные и аутентификационные, которые отвечают за процесс входа, выхода из системы, восстановление доступа и пр.
Apache Kafka КРАТКО
Kafka Apache — распределенная система обмена сообщениями между серверными приложениями в режиме реального времени. Благодаря высокой пропускной способности, масштабируемости и надежности применяется в компаниях, работающих с большими объемами данных. Написана на языках Java и Scala.
Kafka Apache — эффективный инструмент для организации работы серверных проектов любого уровня. Благодаря гибкости, масштабируемости и отказоустойчивости используется в различных направлениях IT-индустрии, от сервисов потоковых видео до аналитики Big Data.
Для связи микросервисов. Kafka — связующее звено между отдельными функциональными модулями большой системы. Например, с ее помощью можно подписать микросервис на другие компоненты для регулярного получения обновлений.
Потоковая передача данных. Высокая пропускная способность системы позволяет поддерживать непрерывные потоки информации. За счет грамотной маршрутизации «Кафка» не только надежно передает данные, но и позволяет производить с ними различные операции.
Ведение журнала событий. Kafka сохраняет данные в строго организованную структуру, в которой всегда можно отследить, когда произошло то или иное событие. Информация хранится в течение заданного промежутка времени, что можно использовать для разгрузки базы данных или медленно работающих систем логирования.
Кратко архитектуру системы сообщений можно охарактеризовать следующим образом:
- распределенность — отдельные узлы системы располагаются на нескольких аппаратных платформах (кластерах). Это обеспечивает ей высокую отказоустойчивость;
- масштабируемость — систему можно наращивать за счет простого добавления новых узлов (брокеров сообщений). </aside>
В архитектуре Kafka Apache ключевыми являются концепции:
- продюсер (producer) — приложение или процесс, генерирующий и посылающий данные (публикующий сообщение);
- потребитель (consumer) — приложение или процесс, который принимает сгенерированное продюсером сообщение;
- сообщение — пакет данных, необходимый для совершения какой-либо операции (например, авторизации, оформления покупки или подписки);
- брокер — узел (диспетчер) передачи сообщения от процесса-продюсера приложению-потребителю;
- топик (тема) — виртуальное хранилище сообщений (журнал записей) одинакового или похожего содержания, из которого приложение-потребитель извлекает необходимую ему информацию. </aside>
В упрощенном виде работа Kafka Apache выглядит следующим образом:
- Приложение-продюсер создает сообщение и отправляет его на узел Kafka.
- Брокер сохраняет сообщение в топике, на который подписаны приложения-потребители.
- Потребитель при необходимости делает запрос в топик и получает из него нужные данные.
Сообщения хранятся в Kafka в виде журнала коммитов — записей, размещенных в строгой последовательности. Их можно только добавлять. Удалять или корректировать нельзя. Сообщения хранятся в той последовательности, в которой поступили, их считывание ведется слева направо, а отслеживание — по изменению порядкового номера. Брокеры Kafka не обрабатывают записи — только помещают их в тему на кластере. Хранение может длиться в течение определенного периода или до достижения заданного порога.
А теперь мы поговорим о кафке поподробнее
Свойства кафки (нажмите на название) распределенная система обмена сообщениями между серверными приложениями в режиме реального времени. 1. Распределенность означает что существует не один а несколько серверов, которые работают слажено
Как выглядит модель передачи данных без кафки:
У нас есть некоторые события, которые должны быть обработаны Для этого нам нужен Продюсер или по-другому поставщик данных, Консьюмер или по-другому потребитель данных Одинаковые Данные могут понадобиться разным потребителям, поэтому модель передачи данных будет выглядеть (на скрине) как для 3 продюсера и 1,2,3 консьюмера
Какие проблемы могут возникнуть при такой модели:
Чтобы решить эти проблемы необходимо добавить компонент: брокер Брокер примет на себя функцию получения данных от продьюсера и соответственно предоставление данные консьюмерам В самом брокере есть набор ящиков под каждый тип событий Продьюсер складывает в ящики брокера определенный тип событий а потребитель забирает из ящиков необходимые события
Схема теперь будет выглядеть так:
Какие удобства при этой схеме:
1) Надежность и гарантия доставки
2) Подключение новых получателей
3) Отправители не знают получателей(они отправляют события в единой узел брокер, но они не знают кто будет получать эти данные, так как потребители сами вытаскивают необходимые события)
4) техническая поддержка
5) интеграция разных стеков(продюсерам в этом случае необходимо знать только АПИ брокера и им отправить, консьюмеру тоже надо знать только АПИ брокера, между собой отправитель и потребитель никак не контактируют)
Брокер отвечает за прием сообщений от продюсеров Он хранит сообщения, чтобы потом предоставлять потребителям их сообщения Если бы брокер был один, то произошла бы проблема надежности и производительности данных. Соответственно именно поэтому добавляются новые брокеры, чтобы данные не терялись, они между собой общаются и создавая собой кластер
Зукипер - координатор, хранилище, небольшая база данных. Для хранения мета данных кластера, состояний, хранится брокеры где они, конфиги кластера, сами данные где расположены ящики топики партиции. все это хранится в зукипере
Среди брокеров выбирается один брокер и он называется кафка контроллером. Он обеспечивает консистентность данных. Кафка сама по себе мастер-слэй система. Зукипер в данном случае используется чтобы тоже выбрать контроллер. Так как представляет собой хранилище настроек-конфигов
Теперь поговорим про Message(сообщения)
Теперь поговорим про Топики и партиции
Топик представляет из себя стрим данных, получение однотипных событий, которые объеденены логически, какое-то единое событие. Оно может получаться из разных источников, а может и из одного. Зависит от логики проекта. В топики у нас выстраивается некая очередь, в которую вкладываются все наши входящие сообщения. Из этой же очереди сообщения потом и извлекаются(сообщения вкладываются в очередь в том порядке в каком порядке продюсер передал их, считываются получателем эти данные тоже в том порядке в каком они стоят в топике т.е в том порядке в каком отправил продюсер). Функция эта называется FIFO - First in first out. В реббите нет этой фичи и там не поддерживается этот порядок. Стоит отметить что когда получатель считывает сообщения сами сообщения из топика не удаляются. Это обеспечивается широковещательный режим, когда у нас может быть несколько разных консьюмеров и им необходимо потреблять одни и те же данные.
Данные не удаляются, новый потребитель пришел и считал нужные сообщения. Иногда нагрузку нужно распределять. Условно говоря у тебя есть одна функциональность - импорт документов, каждый импорт документов доставляется в разные микросервисы. Соответственно использовать один топик для всех документов может быть нецелесообразным решением, поэтому мы распределяем нагрузку по топикам в зависимости от получателя-микросервиса, но бывает огромный поток данный для одного микросервиса и в данном случае используются Partition или по-другому партиции. Внутри топика появляются несколько партиции, где распределяются сообщения, соответственно можно передавать события паралелльно и считывать также. Выглядит эта схема примерно так:
Мы можем заметить что в данном случае сообщения считываются не в том порядке в каком поступили, в данном случае сообщения считываются в том порядке в каком они находятся в партиции
У нас не один брокер, их несколько, соответственно все не так просто. Самая идеальная схема распределения топиков по брокерам будет выглядеть примерно так
Где же хранятся данные топика? Данные топика хранятся в обычных log файлах
Рассмотрим: Есть у брокера файловая система. есть папка логс, в этой папке есть папки под каждую партицию. В этой папке мы можем увидеть папки для партици, в которые если перейти, то можем увидеть 3 файла:
При открытии этой папки мы можем увидеть сами сообщения, которые хранятся с какой-то дополнительной информацией -Офсет это номер сообщения в самой партиции. Они пронумерованы от нуля
-Позиции - смещение в этом файле в байтах. Условно первое сообщение заняло 67 байтов,именно поэтому след сообщение будет начинаться с 67 байта
Мапинг офеста на позицию. мы идем в этот файл и по позиции смотрим начиная с нужного байта нужное сообщение
.timeindex - маппинг тайминдекса на офсет
Условно говоря тебе нужно прочитать сообщения начиная с четверга
Файлов в директории может быть больше. Так как файлы не бесконечные и когда память заканчивается (обычно 1гб), то создается новый сегмент (файл)
Можно ли удалить данные из топика? Нет. в кафке операция удаления данных по хотелке не поддерживается
Но существует автоматическое удаление данных по истечению какого-то периода времени (На моем проекте сообщения в кафке удаляются каждый день). Но данные удаляются не выборочно, а по сегментам партиции.
Data replication - надежность данных и отказоустойчивость Пример: если бы все партиции на каждом брокере находились бы в одном экземляре, то в случае падения одного из брокеров мы начинаем терять данные Для таких случае создана настройка конфига set replication-factor(настройка при создании топиков). Соответственно получается примерно такая картина
Почему реплики одной партии не существуют в рамках одного брокера?
Все просто: упадет один брокер - упадут вместе с репликами, поэтому реплики существуют на разных брокерах. Особенность кафки заключается в том, что если один из брокеров упал, то она автоматически добавит реплику в брокеры тех топиков, которые находились на упавшем ранее брокере
Напоминаю что кафка реализована как master-slave система. Соответсвенно одна из реплик назначается лидер-репликой. Остальные называются ведомыми или по-другому followers. Данные на чтение и запись идут ВСЕГДА только в лидер реплику, фолловеры изредка по триггеру опрашивают лидер реплику на предмет нужных им данных. Соответственно а что же произойдет если лидер-реплика упадет? и Кто же назначает эти лидер реплики? Насколько вы можете помнить ранее я говорила о том, что у нас есть лидер-брокер или брокер-контроллер. Как раз он и назначает лидер реплики. А в случае падения лидер-реплики всегда есть несколько фолловеров, которые подписаны как ISR. Для фолловеров isr идет синхронное сохранение данных, которые попадали в лидер-реплику и соответственно при падении лидер реплики они и становятся кандидатами на престол отца и кто-то из них станет лидер репликой. Цикл повторяется:
Поговорим про Продюсера или по-другому отправителя
Напомню что продюсеры пишут только в лидер-реплику а консьюмеры читают тоже только лидер-реплики
У продюсера есть 3 режима отправления сообщений:
- acks=0 → продюсера вообще не ждет подтверждение отправки сообщения: он отправил в брокер и все, дальше его не интересует что происходит. Это самый ненадежный режим, потому что сообщения могут теряться, если брокер упал, а мы отправили не подумали и тд
- acks = 1. Продюсер ждет подтверждение только от лидер-реплики. Этот режим скорее более компромиссный, так как если упадет и лидер реплика и брокер в одно время, то сообщения могут потеряться. Часто используемый вариант
3)acks = all. Продюсер ждет подтверждение отправки сообщения от всех isr и лидер-реплик. Самый надежный режим
Поговорим о консьюмере или по-другому о потребителе
Уточню что для отправки сообщения в брокер продюсером используется команда send под капотом, а для получение данных poll Консьюмер обрабатывает сообщение, следуя бизнес-логике. Затем отправляет ack или nack-запрос обратно на сервер, используя уникальный идентификатор, полученный ранее — тем самым либо подтверждая успешную обработку сообщения, либо сигнализируя об ошибке. В случае успеха сообщение удаляется с сервера навсегда.
На практике тестирование запросов с очередями выглядит так:
1. Выполняем HTTP-запрос к системе через условный Postman. Сразу получаем либо успешный статус-код (202 Accepted), либо условную 500-ую или 400-ую ошибку.
2. Переходим в логи и ищем выполненный запрос, а также ищем ответ от бэка.
3. Смотрим на ответ бэка: всё ли прошло корректно, какой статус-код, какая структура ответа, корректны ли данные внутри ответа.
4. Переходим в систему и проверяем, собственно, функциональность, например, был ли создан тикет или произошли ли какие-то изменения (т.е. проводим функциональное и интеграционное тестирование стори/фичи)
Одним из самых популярных инструментов для работы с Kafka является Kafka Tool. Его интерфейс довольно прост, и, как говорится, чем проще, тем лучше. Этот инструмент позволяет всем нашим кластерам, включая всех брокеров, просматривать списки топиков и консьюмеров. А в топиках мы можем читать сообщения.
Эта информация полезна при тестировании различных сервисов, которые читают топики и пишут в топики Kafka, но это далеко не полный функционал Kafka Tool. Здесь мы можем создавать свои топики и разделы, что позволяет нам заменить их в конфигурационном файле на фейковые данные, созданные тестером, чтобы проверить тот или иной тест кейс.
Далее мы можем модифицировать конкретное сообщение и отправить его в нужный нам топик, добившись желаемого результата.
Конечно, отправка сообщения с несколькими заголовками сопряжена с некоторыми неудобствами. Но в целом это не плохой инструмент.
Рекомендую к просмотру данное видео про кафку
Sql теория
База данных в приложении - это структурированная коллекция данных, которая хранится и используется программой или приложением для сохранения информации. Она может содержать информацию о пользователях, их действиях, настройках, контенте и многое другое в зависимости от конкретного приложения.
Например, социальная сеть может иметь базу данных, в которой хранятся профили пользователей, их посты, комментарии, друзья и связи между ними. Интернет-магазин может использовать базу данных для хранения информации о товарах, заказах, клиентах и транзакциях.
База данных в приложении обеспечивает способ хранения, организации и доступа к данным, позволяя приложению эффективно управлять информацией, необходимой для работы и взаимодействия с пользователями.
Существует множество различных типов баз данных, каждый из которых оптимизирован для определенных целей и задач. Некоторые из наиболее распространенных типов баз данных:
- Реляционные базы данных (RDBMS): Это один из наиболее широко используемых типов. Данные организованы в виде таблиц, связанных друг с другом ключами. Примеры: MySQL, PostgreSQL, Oracle.
- Документоориентированные базы данных: Хранят данные в формате документов, таких как JSON или XML. Это удобно для хранения сложных структур данных. Примеры: MongoDB, Couchbase.
- Ключ-значение хранилища: Хранят данные в виде простых ключей и связанных с ними значений. Они предоставляют быстрый доступ к данным, но обычно менее функциональны. Примеры: Redis, DynamoDB.
- Сетевые базы данных: Данные представлены в виде сети узлов, связанных между собой. Это редкий тип, который используется в специфических случаях. Примеры: IMS, CODASYL.
- Объектно-ориентированные базы данных: Хранят объекты программирования (классы, объекты) непосредственно в базе данных. Примеры: db4o, ObjectDB.
- Временные базы данных: Специализированные базы данных для хранения временных данных, которые действительны в определенный период времени. Примеры: TimescaleDB, InfluxDB.
- Колоночные базы данных: Данные хранятся колоночно (по столбцам), что обеспечивает высокую производительность при анализе больших объемов данных. Примеры: Amazon Redshift, ClickHouse.
Каждый тип базы данных имеет свои особенности, и выбор конкретного зависит от потребностей проекта, структуры данных, требуемой производительности и других факторов.
База данных — это упорядоченный набор структурированной информации или данных, которые обычно хранятся в электронном виде в компьютерной системе.
Например, вы в библиотеке, где есть каталог — ящики с карточками. В каждой карточке указана информация о книге: название, автор, жанр, издательство. Карточки расположены по группам в стойках в алфавитном порядке, например, по жанрам. Когда вы найдёте нужную карточку, вы получите номер стеллажа и отыщите книгу. Работа с базой данных происходит по такому же принципу.
База данных обычно управляется системой управления базами данных (СУБД). Данные вместе с СУБД, а также приложения, которые с ними связаны, называются системой баз данных, или, для краткости, просто базой данных.
Как стало известно вам ранее, приложение может состоять из трёх частей:
Клиент через возможности фронтенда запрашивает информацию у бэкенда, который общается с базой данных и возвращает ответ. База данных, в свою очередь, это составная часть большого приложения и взаимодействие с ней тоже нужно проверить.
- нам необходимо протестировать, что бэкенд получит из базы те данные, которые ему нужны;
- или же нам необходимо протестировать, что изменения (добавление данных, изменение или удаление) корректно записываются в базу.
Протестировать базу данных можно двумя способами: работая с ней напрямую или выполняя действия на фронтенде/бэкенде, которые воздействуют на данные в ней.
- если в процессе разработки приложения база данных уже готова, а бэкенд — нет, то можно проверить структуру базы данных (что она содержит всю нужную информацию в удобном для нас виде);
- нужно проверить, что бэкенд и база данных работают согласованно. Т.е. выполнить действия методами фронтенда, бэкенда или API бэкенда и проверить, что:
- API выполнило ожидаемые действия и вернуло корректные данные;
- фронтенд и бэкенд также отреагировали корректно;
- в базе данных произошли ожидаемые изменения.
Также базы данных отличаются по способам хранения информации.
Основное отличие между реляционными и нереляционными (или нереляционными) базами данных заключается в способе организации, хранения и обработки данных.
Реляционные базы данных (RDBMS):
- Данные организованы в таблицы с жестко определенными структурами, каждая таблица содержит ряды (строки) и колонки (поля).
- Используют язык SQL для выполнения запросов.
- Схема данных четко определена с использованием сущностей (таблиц) и их атрибутов (столбцов).
- Поддерживают ACID (атомарность, согласованность, изолированность, долговечность) транзакций.
- https://webonto.ru/pervichnyiy-klyuch-i-vneshniy-klyuch-tablits-relyatsionnyih-baz-dannyih/
Нереляционные базы данных (NoSQL):
- Не требуют строгой схемы или жестко определенных отношений между данными.
- Могут хранить данные в различных форматах, таких как документы, ключ-значение, столбцы или графы.
- Могут быть горизонтально масштабируемыми, позволяя легко добавлять новые сервера для увеличения производительности.
- Отсутствие жесткой схемы делает их гибкими для изменения структуры данных.
- Могут обеспечивать высокую производительность для определенных типов задач, таких как хранение и обработка больших объемов данных, веб-аналитика и др.
Выбор между реляционными и нереляционными базами данных зависит от конкретных потребностей проекта: если необходима строгая структура данных и поддержка сложных запросов, то реляционные БД могут быть более подходящим выбором; в то время как для масштабируемости, гибкости и обработки больших объемов данных нереляционные БД могут быть предпочтительны.
Поговорим поподробнее о реляционных базах данных Но сначала поговорим о типах данных
- INTEGER- данные из целых чисел;
- FLOAT – данные из дробных чисел, так называемые данные с плавающей точкой;
- CHAR, VARCHAR – текстовые типы данных (символьные);
- LOGICAL – логический тип данных (да/нет);
- DATE/TIME – временные данные.
Все данные VARCHAR при сравнении, выводе (не считая выборки данных при select) пишутся как ‘текст’
sql - язык, который помогает работать с базамии данных, которые также написаны на sql
Возьмем на примере заданий из sql академии и разберем их подробно
Задание №1: Вывести имена всех людей, которые есть в базе данных авиакомпаний
Начнем с структуры запроса на примере таблицы passenger
SELECT name FROM Passenger где Select - ключевое слово, которое говорит какое действие выполнить. В данном случае это select или по-другому выбрать ***** - показывает нам что нужно выбрать все что есть в этой таблице. Мы можем поменять звездочку на любое название поля, что нам нужно и что относится к выбранной таблице FROM- ключевое слово, которое показывает из какой таблицы нам необходимо выбрать данные
Здание №2: Вывести названия всеx авиакомпаний
Давайте попробуем разобрать немного более сложный пример:
SELECT * FROM Table - структура есть структура, когда нам необходимо вывести данные, но с каким-то условием
Задание №3: Предположим, нам нужно вывести рейсы совершенные из Москвы Если попробуем вывести это так: SELECT * FROM Trip, то нам выведутся все рейсы и из Москвы и из Рязани и тд и тп. Что же делать в данном случае? Добавляем ключевое слово WHERE и наша структура теперь видоизменяется
Select * FROM trip Where town_from = 'Moscow'
Мы можем прочитать это как Выбрать все из таблицы trip где все рейсы совершены из Москвы. По сути своей мы сравниваем знаком = все значения из колонки town_from и ищем все совпадения с Moscow
Но операторов сравнений на самом деле больше
1. Оператор сравнения мы уже знаем и это =
2. Есть оператор сравнения > или <
3. Есть оператор сравнения <> НЕ равно (другая запись не равно может выглядеть так ≠ или != (восклицательный знак и равно без пробела))
4. Соответственно может быть и операторы >= или <=. Когда нам нужно включить значение на границе (Например, вывести всех детей старше 14 или того же возраста)
Но что если нам нужно Вывести все рейсы, совершенные из Москвы или из Питера? тогда добавляются AND, OR
Select * FROM trip Where town_from = 'Moscow' OR town_from = ‘Saint Petersburg’
Вывести все рейсы, совершенные из Москвы и из Питера?
Select * FROM trip Where town_from = 'Moscow' AND town_from = ‘Saint Petersburg’
Поговорим о еще одном операторе LIKE
Предположим вы помните что имя пассажира заканчивалось на определенные буквы или помните имя частично или вам нужно вывести всех пассажиров, имя которых заканчивается на определенные буквы
Наша структура запроса будет меняться в данном случае таким образом: Возвращаемся к нашим таблицам
Задание №4 звучит так: Вывести имена людей, которые заканчиваются на "man”
Select name from passenger Where name LIKE '%man'
%
(знак процента): Это подстановочный символ, который может заменять любую последовательность символов (включая отсутствие символов, даже нуль символов)._
(нижнее подчеркивание): Это подстановочный символ, который заменяет любой одиночный символ.
Это может быть интерперетировано как угодно. Например Select name from passenger Where name LIKE 'a%man' или Where name LIKE 'aman%man' или Where name LIKE '%a%'
А что если нам нужно чтобы данные сортировались по алфавитному порядку?
У нас появляется новый оператор ORDER BY
Отсортируем имена пассажиров по порядку
SELECT name FROM Passenger ORDER BY name;
Когда мы не указываем как отсортировать данные, то автоматически указывается по asc
ASC - сортировка по возрастанию, DESC - сортировка по убыванию.
Поэтому если нужно отсортировать по убыванию, то мы указываем
SELECT name FROM Passenger
ORDER BY name DESC;
Поговорим о Group by
Используем уже другие таблицы с расписанными данными
В таблице auto есть машины красного, зеленого и синего цветы
Мы можем сгруппировать такие таблицы по признаку цвета, по марке (тк есть группы).
Можно заметить что в колонке regnum и phonenum нет групп, там уникальные идентификаторы. Но в колонках марки и цвета есть группы, поэтому мы можем с ними работать)
Задание №5: Как работает GROUP BY на примере сортировки по цветам
SELECT color FROM auto GROUP BY color
Что выведется в запросе: синий,зеленый, красный
Примечание: поля, которые перечисляются после SELECT и поля, которые перечисляются после GROUP BY должны быть одинаковые, иначе мы получим ошибку)
Определение GROUP BY было бы неполным без определения агрегатных функций, так как этот оператор зачастую работает с ним начнем с определений
-count(ключ) - количества элементов в группе
-sum(колонка) - сумма по заданным значениям - только для числовых данных
-avg(колонка) - среднее по заданным значениям в группе - только для числовых данных
-max(колонка) - максимальное значение в группе, только для числовых данных и дат
-min(колонка) - минимальное значение в группе, только для числовых данных и дат
Задание №6: вывести количество auto, сгрупированных по цвету
SELECT COUNT(*) color FROM auto GROUP BY color
Ответ:
Синий: 4
Зеленый: 1
Красный: 3
но можно посчитать количество и без оператора group by
Например: количество строк в таблице auto select count(*) from auto
Вывести количество красных машин в таблице auto select count(*) from auto WHERE color ‘КРАСНЫЙ’
Задание № 7: Подумайте какое условие было у задачи, если запрос и ответ выглядят так: SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type
Ответ:
Найдём количество каждого вида жилья и отсортируем полученный список по убыванию:
SELECT home_type, COUNT(*) as amount FROM Rooms GROUP BY home_type ORDER BY amount DESC
При использовании AS мы можем назвать поле своим именем для облегчения вывода информации
GROUP BY можно использовать с ORDER BY
Напоминаю что в базе данных не одна таблица: их может быть как 10, так и 100, так и 500. Зависит от проекта
Некоторые таблицы соединены по внешнему и внутреннему ключу. Связь через одинаковое поле
Например: Мы можем заметить что таблица company связана с таблицей trip по id→ company, потому что поездка совершается от лица определенной компании, a таблица Passenger связана c Pass_in_trip по id → passenger, тк нужно знать пассажиров, которые приняли поездку. Также можем найти связь таблиц trip и pass_in_trip
Рассмотрим на примере задания
Задание №8: Какие компании совершали перелеты на Boeing
Решение:
Select DISTINCT Company.name From company JOIN Trip ON company.id = trip.company WHERE plane = 'Boeing'
Начнем с DISTINCT. Это слово убирает повторяющиеся позиции. То есть если у нас было два перелета из компании n, то выведется только один, потому что у нас не стоит задача найти количество, задача вывести сами компании. Но информация о компаниях и перелетах находится в разных таблицах и именно для вывода данных с двух таблиц нам необходим join или по-русски джоин
Select DISTINCT Company.name - в данном случае мы также обращаемся к полю/полям, которые нас интересуют, но по-хорошему следует указать из какой таблицы мы берем данное имя и это таблица Company. То есть из таблицы Company мы берем name
From company - здесь мы обращаемся к таблицам, с которыми работаем и именно здесь мы используем JOIN
JOIN Trip ON company.id = trip.company - здесь мы объединили таблицу company и таблицу trip ключевым словом JOIN ON
Примечание Джоинов может быть несколько. и каждый из них выполняет разные функции. Начнем с основного:
NNER JOIN - этот джоин подразумевает что мы будем брать только ту информацию которая присутствует в обеих таблицах
JOIN Trip ON company.id = trip.company - напомню что = это оператор сравнения и здесь мы сравниваем одинаковые поля разных таблиц company.id = trip.company. В таблице company это id, в таблице trip это company
Примечание: всегда при указании поля сначала указывается таблица, а потом уже само поле
WHERE plane = 'Boeing' - тут все также. ищем где есть самолет Boeing
Ответ:
Теперь рассмотрим LEFT JOIN Возьмем другие таблицы.
Например:
Специфика: здесь необходимо сохранять порядок обращения полей.
То есть если мы обращаемся сначала к таблице Сustomers, то ставим первой ее
Select Customers.CustomerName, Orders,OrderID FROM Customers LEFT JOIN Orders ON Customer.ID = Orders.CustomerID
LEFT JOIN - если раньше мы выводили поля, которые есть в обеих таблицах, то сейчас мы выведем дополнительно и все поля, которые есть в ЛЕВОЙ таблице. Аналогично и с RIGHT JOIN
Попрактикуйся в написании sql скриптов (можешь гуглить ответы и анализировать их. Слишком долго не задерживайся. Максимум 1-2 дня!!!) https://sql-academy.org/ru
https://stepik.org/course/63054/promo
https://karpov.courses/simulator-sql
Рекомендую к просмотру данное видео про SQL
Реляционные базы данных
Реляционная база данных — это набор данных с предопределенными связями между ними, она состоит из таблиц и связей.
Таблица — это совокупность строк и столбцов.
Столбцы — это поля. В них содержится определенная характеристика. В данном примере мы видим характеристики покупателей (имя, фамилия, дата регистрации, общее количество заказов, статус в нашем условном магазине). У каждого поля уникальное имя. Одна из наших задач как раз научится искать нужную информацию по таким именам полей.
Строки таблицы — это записи. Каждая строка — информация об одном конкретном покупателе.
Ячейка — место пересечения строки и столбца, в каждой ячейке содержится значение атрибута.
Каждое поле имеет какой-либо определенный тип данных.
Типы данных SQL — это своего рода маркеры, которые указывают на свойства данных и необходимый объём места для их хранения.
Выделяют следующие основные типы данных:
С помощью чисел в таблицы записывают цены товаров, суммы в чеках и другие данные, которые важны для анализа. Операции с числами позволяют аналитикам рассчитывать выручку, расходы, рентабельность, чтобы после сравнивать результаты вычислений — по неделям, месяцам или кварталам, и делать выводы о росте или падении показателей. Один из числовых типов данных это integer / int / int4 — целочисленный тип. В PostgreSQL диапазон целых чисел от -2147483648 до 2147483647
База данных может содержать ФИО клиентов, их адреса, описания товаров или примечания. Например, в базе заказов могут быть пометки, которые тоже будут храниться в формате текста. Во всех этих случаях для работы с информацией используют строковые типы данных SQL. Один из строковых типов данных varchar(n) — строка переменной длины, где n — ограничение длины. Этот тип данных варьирует длину хранимой строки: в поле можно занести любую строку короче, чем n символов. Пример: слово 'Ростелеком' — значение строкового типа, в SQL-запросе его заключают в одинарные кавычки.
Boolean — логический тип данных. В PostgreSQL есть три варианта значений:
Также существуют типы данных для хранения Даты и времени
Любые значения даты или времени заключают в одинарные кавычки. Один из таких типов данных timestamp. В формате timestamp чаще всего хранят события, для которых недостаточно указать только дату. Например, в логах указывают дату и точное время произошедшего события. Требуется точность до секунды. Пример:'1990-01-01 00:00:00'
Более подробно изучить типы данных самостоятельно можно в официальной документации postgres
Для наглядности изучения данного вопросы рассмотрим, как можно организовать данные интернет-магазина.
Требования к базе следующие: нужно хранить учётные данные пользователей и историю их заказов.
Здесь товар, пользователь и заказ — сущности, информация о которых должна храниться в БД. У каждой сущности есть свойства. Например, у человека — имя или возраст, а у товара — название или стоимость. Каждому свойству отводят отдельный столбец в таблице — поле. Каждая строка — отдельная запись со своими значениями свойств.
Например, вам нужно хранить информацию о пользователях, товарах и заказах в БД. Чтобы хранить данные удобным способом, нужно записать её в разные таблицы — по одной на каждую сущность.
Один к одному значит, что строка в первой таблице связана с одной-единственной строкой во второй таблице.
Например, перед тобой таблица с именами и фамилиями; а также таблица с данными о дате рождения и местах рождения. Каждому человеку соответствует одна строка с датой и местом рождения. Id одинаковый в обеих таблицах.
Один ко многим — тип связи, когда каждая строка в одной таблице соответствует многим строкам в другой таблице.
Такой тип связи есть в примере с книгами. Автор может написать несколько книг, но у одной книги — только один автор.
Многие ко многим — тип связи, когда несколько строк одной таблицы соответствуют нескольким строкам другой таблицы.
- есть таблица users с пользователями и первичным ключом id;
- есть таблица items с информацией о товарах id;
Вам надо найти заказы. Чтобы это было возможно, нужна ещё одна таблица orders: с её помощью сопоставляются таблицы users и items.
Для того чтобы управлять базой данных, применяют специальные инструменты — СУБД, системы управления базами данных. Это комплекс программ, который позволяет создать базу данных, наполнить её новыми таблицами, отобразить содержимое, редактировать существующие таблицы.
Наиболее популярными СУБД являются:
Нереляционные базы данных
SQL
SQL (от англ. Structured Query Language, «язык структурированных запросов») — язык запросов, с помощью которого можно управлять данными в реляционной базе.
Знание SQL позволяет получать, анализировать и манипулировать данными напрямую из баз данных, что может повысить эффективность тестирования, сократить время обнаружения проблем и улучшить качество конечного продукта.
- создавать и удалять таблицы в реляционной БД
- изменять данные в существующих таблицах
- наполнять таблицы данными
- доставать из таблиц необходимую информацию
Запрос — это команда к базе данных, которая написана в синтаксисе SQL. В запросе пишут, например, какие данные выбрать, как именно их обработать или изменить.
Запрос в свою очередь формируется с помощью специальных слов или символов в синтаксисе SQL которые называются – оператор.
Оператор SELECT является одним из основных операторов и почти всегда знакомство с SQL начинается именно с него. Его используют для получения выборки данных.
В запросе два ключевых слова: SELECT и FROM — буквально «выбрать из».
SELECT указывает, какие столбцы выбрать из таблицы базы данных.
FROM (англ. «из») указывает, из какой таблицы взять данные.
Таким образом синтаксис запроса с SELECT выглядит следующим образом:
SELECT column_1 FROM table_1; SELECT * FROM table_1;
Где column_1 столбец который необходимо вывести, а table_1 таблица из которой необходимо вывести данные. При использовании специального символа * выводятся все столбцы таблицы т.е. вся таблица целиком.
Существует таблица с названием products
И если мы выполним следующий запрос:
SELECT product_name FROM products;
При выполнении запроса с использованием специального символа *
SELECT * FROM products;
Мы получаем в результате всю таблицу
Условие в SQL-запросе, которое покажет ограниченную выборку, прописывают командой WHERE (англ. «где»). Оператор проверяет, соответствует ли каждая строчка таблицы условию, и выбирает подходящие. Синтаксис запроса строится так же, как и SELECT, но добавляется WHERE:
SELECT column_1 FROM table_1 WHERE column_2 = 'value'
При выполнении подобного запроса в результате мы получим один столбец column_1 и все строки, где column_2 = 'value'
Порядок операторов строго определён. Они должны идти так:
Обозначить границы выборки в условиях помогают операторы сравнения:
Также, можно использовать математические операторы
Ниже перечислены математические операторы PostgreSQL. Некоторые математические операторы являются стандартными и присутствуют в любой СУБД. Некоторых операторов может не быть в других СУБД или их синтаксис может отличаться.
В тестировании API встречаются тест-кейсы, которые проверяют изменение данных в базе. Обычно их тестируют в таком порядке:
- сначала нужно изменить содержимое таблиц в БД: добавить строки с нужными значениями, отредактировать уже существующие записи или удалить лишние. Это делают, чтобы получить определённое состояние БД, которое подходит для тестирования;
- затем проходят по шагам тест-кейса;
- в последнюю очередь проверяют соответствие ОР и ФР оператором SELECT.
Существует уже знакомая таблица с названием products
И если мы выполним следующий запрос:
SELECT * FROM products WHERE price < 6000;
SQL оператор DISTINCT используется для удаления дубликатов из результирующего набора оператора SELECT.
SELECT DISTINCT column_1 FROM table_1
При выполнении подобного запроса в результате мы получим только уникальные значения, содержащиеся в поле column_1
Если в операторе DISTINCT указано только одно выражение, запрос возвратит уникальные значения для этого выражения.
Если в операторе DISTINCT указано несколько выражений, запрос извлекает уникальные комбинации для перечисленных выражений.
В SQL оператор DISTINCT не игнорирует значения NULL. Поэтому при использовании DISTINCT в вашем операторе SQL ваш результирующий набор будет содержать значение NULL в качестве отдельного значения.
Существует таблица с названием products
И если мы выполним следующий запрос:
SELECT DISTINCT **product_name FROM products**
LIKE в SQL выполняет функцию оператора, который помогает фильтровать результаты.
Оператор LIKE (англ. «подобный») находит схожие значения в таблице. Искать можно не только целое слово, но и его часть.
SELECT column_1, column_2 FROM table_1 WHERE column1 LIKE '%example____';
Перед оператором LIKE указывают столбец, в котором нужно искать, а после LIKE — шаблон для поиска — паттерн.
Паттерн (маска) — это шаблон, который позволяет найти целую строку по подстроке. Паттерны построены из символов, которые помогают заменить значение. Например, знак нижнего подчёркивания _ в паттерне заменяет одно подстановочное значение, то есть 1 символ. Знак процента % заменяет любое количество символов.
Существует два подстановочных знака, которые используются в сочетании с оператором LIKE SQL:
- % — знак процента представляет собой ноль, один или несколько символов;
- _ — подчёркивание представляет собой один символ.
Существует таблица с названием products
И если мы выполним следующий запрос:
SELECT * FROM products WHERE product_name LIKE 'M%'
INSERT помогает добавить новую строку в таблицу (англ. «вводить»). В запросе два ключевых оператора: INSERT INTO и VALUES.
INSERT INTO указывает, в какую таблицу добавить данные.
VALUES перечисляет данные, которые нужно добавить.
INSERT INTO table_1 (column_1, column_2, column_3) VALUES (values_for_column_1, 'values_for_column_2', values_for_column_3)
Название столбцов после названия таблицы перечислять не обязательно. Если после названия таблицы не перечислить названия столбцов, то обязательно необходимо в VALUES передавать данные в строгом порядке. Но также возможно и применение опционального параметра.
Зачем применять опциональный параметр, если и без него всё отработало?
Во-первых, можно указать столбцы в произвольном порядке. Переставив порядок столбцов, нужно переставить и порядок значений.
Во-вторых, можно перечислить не все столбцы, а только «важные». Все неуказанные столбцы заполнятся значениями по умолчанию. Значения по умолчанию — это один из параметров таблицы, создаются вместе с ней.
Оператор UPDATE (англ. «обновить») меняет текущую информацию в таблице.В запросе три ключевых оператора: UPDATE, SET и WHERE.UPDATE указывает, в какой таблице изменить данные.SET указывает столбец, в котором необходимо поменять данные.WHERE выбирает строки, опционально.
UPDATE table_1 SET column_2 = 'values' WHERE column_1 = 'values2'
Оператор DELETE удаляет записи из таблицы (англ. «удалять»).
В запросе два ключевых оператора: DELETE FROM и WHERE.
DELETE FROM указывает, из какой таблицы удалить записи.
WHERE выбирает строки, в которых нужно удалить данные.
DELETE FROM table_1
WHERE column_1 = 'values1'
Если вам нужно определить количество строк для среза, объедините функцию COUNT() с конструкцией WHERE.
SELECT COUNT(column_1) FROM table_1
WHERE column_1 = 'values'
В зависимости от цели количество строк считают по-разному:
- COUNT(*) возвращает общее количество строк в таблице;
- COUNT(column) возвращает число строк в столбце column;
- COUNT(DISTINCT column) (англ. distinct, «отдельный, особый») возвращает количество уникальных строк в столбце column.
SELECT COUNT(column_1) FROM table_1
Кстати, данный оператор можно использовать и в обычной выборке после слова SELECT, что позволит получить нам только уникальные записи.
Функция SUM(column) возвращает сумму по столбцу column. Когда функция выполняется, пропуски игнорируются.
!Обратите внимание: функция SUM() работает только с числовым форматом данных.
AVG (column) возвращает среднее значение по столбцу column.
Минимальное и максимальное значения вычисляют функциями MIN() и MAX().
SELECT min(column_1) FROM table_1
При выполнении подобного запроса в результате мы получим минимальное значение в столбце column_1
Пример использования агрегирующих функций
Существует уже знакомая таблица с названием products
И если мы выполним следующий запрос:
SELECT avg(price) FROM products
Соответственно выполнив следующий запрос
SELECT max(price) FROM products
Команду GROUP BY (англ. «группировать по») применяют, когда данные нужно разделить на группы по значениям полей.
SELECT column_1, COUNT(column_2) FROM table_1 GROUP BY column_1
После того как вы вызовете агрегирующую функцию, имя столбца выведется в неудобном виде. Чтобы исправить это, применяется команда AS (англ. «как»).
После команды GROUP BY перечисляют все поля из блока SELECT. Саму агрегирующую функцию включать в блок GROUP BY не нужно — с ней запрос не выполнится.
Конструкцию GROUP BY можно применять со всеми агрегирующими функциями: COUNT(), AVG(), SUM(), MAX(), MIN().
Чтобы сортировать данные по указанным полям, применяют команду ORDER BY (англ. order by, «упорядочить по»). В отличие от GROUP BY, в блоке с командой ORDER BY нужно перечислить только поля, по которым вы хотите сортировать информацию.
У команды ORDER BY есть аргумент, регулирующий порядок сортировки в столбцах. Он может принимать такие значения:
- ASC (от англ. ascending, «восходящий») сортирует данные в порядке возрастания. Это значение аргумента ORDER BY по умолчанию.
- DESC (от англ. descending, «нисходящий») сортирует данные по убыванию.
Аргументы команды ORDER BY указывают сразу после поля, по которому сортировали данные:
SELECT column_1, COUNT(column_2) AS sum FROM table_1
GROUP BY column_1
ORDER BY sum desc (asc)
Не всегда удобно идти в одну таблицу, смотреть первичные ключи, и искать их же во второй таблице. Удобнее получить понятный результат с помощью одного запроса. Чтобы это сделать, применяют соединение таблиц — используют оператор JOIN (англ. «соединять»).
Таблицы можно соединить через INNER (англ. «внутренний») и OUTER (англ. «внешний»):
INNER JOIN формирует выборку только из тех данных, у которых выполнено условие присоединения. От порядка присоединения таблиц результат не изменится.
Пример структуры запроса с INNER JOIN:
SELECT
table_1.column_1,
table_1.column_2,
table_2.column_1,
table_2.column_2
FROM
table_1
JOIN
table_2 ON
table_1.column_1 = table_2.column_2
INNER JOIN — название способа соединения, после него указывают имя таблицы, с которой нужно соединить таблицу из блока FROM;
ON открывает условие присоединения: TABLE_2.поле_1 = TABLE_1.поле_2. Соединяют только те строки, которые соответствуют условию. В этом случае значения в поле_1 и поле_2 равны.
Так как поля в разных таблицах могут быть названы одинаково, к ним обращаются с указанием имени таблицы. Сначала название таблицы, а потом имя её поля: TABLE_1.поле_1.
Различают три вида OUTER JOIN: LEFT, RIGHT и FULL
LEFT OUTER JOIN: возвращаются все строки левой таблицы. Если у строк левой таблицы выполняются условия соединения, они дополнятся данными правой таблицы. Если есть недостающие данные, вместо строк правой таблицы подставляются NULL-значения.
RIGHT OUTER JOIN: возвращаются все строки правой таблицы. Если у строк правой таблицы выполняется условие соединения, они дополнятся данными левой таблицы. Если есть недостающие данные, вместо строк левой таблицы подставляются NULL-значения. RIGHT JOIN — брат-близнец LEFT JOIN. Вот только в отличие от него: в результат своей работы он берёт всю правую таблицу, и строки на пересечении с левой, если они соответствуют условию.
FULL OUTER JOIN: возвращаются строки и левой, и правой таблиц. Если у строк левой таблицы и правой таблицы выполняется условие соединения, они объединятся в одну строку. Если есть строки, у которых не выполняется условие соединения, они дополнятся NULL-значениями.
Инструкция по установке локальной БД
Хранилища данных
При разработке современных веб-сайтов достаточно часто необходимо сохранять данные на стороне клиента. Для таких целей в браузере существует несколько разных способов, которые появились в разное время и отличаются друг от друга.
В рамках клиент-серверной архитектуры нужная для работы информация загружается с сервера и хранится на клиенте.
Основные места хранения информации:
- Кэш
- Web storage: Local storage и Session storage
- Cookies
Не стоит путать эти хранилища.
Например, кэш нужен для оптимизации скорости загрузки файлов: проще один раз загрузить картинку, сохранить её в кэше и не скачивать её несколько раз.
В то время как storage и куки для работы с авторизационными данными, маркетинговыми и т.д.
Куки применяют, чтобы хранить информацию на устройстве пользователя. Сами по себе куки не работают — они значимы только для сервера, к которому обращается пользователь. В момент запроса сайт ищет подходящий cookie-файл на устройстве пользователя, затем изучает сохранённую информацию и извлекает необходимые для сеанса данные.
- В своём браузере вы вводите URL-адрес сайта.
- Браузер отправляет соответствующий запрос на сайт.
- Браузер ищет на вашем устройстве файл cookie этого сайта.
- Если cookie присутствует, он отправляется вместе с URL-адресом на сервер сайта.
- Если файл не найден, то cookie не отправляется.
- Когда сервер сайта получает данные cookie, он может их использовать.
- При отсутствии cookie сервер идентифицирует пользователя как нового посетителя.
Куки передаются в заголовках HTTP-запросов
Кука is_adult_confirmed по умолчанию отсутствует, поэтому выводится блокировка:
После получения апрува значение куки меняется на true:
Это один из примеров применения cookies.
К слову, ozonIdAuthResponseToken — тот самый авторизационный токен, речь о котором будет дальше.
Также куки используются для маркетинга и тд.
Это объект, хранящийся в window
, который позволяет долговременно сохранять данные в браузере. Работает как хранилище данных в формате ключ-значение — при сохранении данных мы указываем имя поля, в которое должны быть сохранены данные, и затем используем это имя для их получения.
- Значения хранятся в виде строк. При попытке сохранения других типов данных, они будут приведены к строке. Например, если записать число, то при чтении нам вернётся число, записанное в строку.
- Не имеет ограничений по времени хранения, может быть очищен пользователем вручную или браузером при переполнении автоматически (браузеры на основе движка WebKit, например Safari, очищают
localStorage
, если к нему не обращались в течение 7 дней). - Максимальный объем данных ограничен размером 5MB.
Это объект, хранящийся в window
, который позволяет сохранять данные в браузере на время сессии. Этот тип хранилища очень похож на localStorage
и работает как хранилище данных в формате ключ-значение. При сохранении данных мы указываем имя поля, в которое должны быть сохранены данные, и затем используем это имя для их получения.
- Сессия страницы создаётся при открытии новой вкладки браузера. Сессия остаётся активной до тех пор, пока открыта вкладка, а состояние сессии сохраняется между перезагрузками. Открытие новой вкладки с таким же адресом приведёт к созданию новой сессии.
- Значения хранятся в виде строк. При попытке сохранения других типов данных, они будут приведены к строке. Например, если записать число, то при чтении нам вернётся число, записанное в строку.
- Максимальный объем данных ограничен размером 5MB.
Сравнение cookies, local storage и session storage
Web storage зависит от браузера, в среднем 5мб В Chrome было 5 мб в версиях Chrome 113 и раньше, а начиная 114 сделали 10 мб Но также в принципе можно увеличить место через разрешение/флаг "unlimitedStorage".
В 2013 на web storage было так: 2.5 MB per origin in Google Chrome; 5 MB per origin in Mozilla Firefox, and Opera; 10 MB per storage area in Internet Explore
Для собеседования достаточно запомнить, что размер куки 4кб (точнее 4096 bytes), а остальные хранилища более 5мб.
- Максимально подробно про cookies: https://habr.com/ru/articles/710578/
- Безопасность и cookies. Рассматриваются различные виды атак(Man-in-the-middle, XSS, CSRF): https://www.freecodecamp.org/news/everything-you-need-to-know-about-cookies-for-web-development/
Юзер агент нужен для того, чтобы определять, с какого устройства подключается клиент. Например, что он использует определенную версию Firefox на десктопе.
Это также один из заголовков в HTTP-запросе.
Дополнительное чтение.
https://trofimovdigital.ru/blog/user-agent
Для того, чтобы получить доступ к веб-сервису, требуется авторизация.
Не стоит путать авторизацию и аутентификацию.
Аутентификация — это процесс проверки подлинности пользователя. Авторизация — это процесс предоставления доступа пользователю.
Чаще всего для этого используется авторизационный токен.
Инструментов/систем шифрования довольно много, но наиболее часто встречающиеся: bearer token, JWT, OAuth и basic auth.
Basic auth — это базовая аутентификация, которая ставится на уровне HTTP.
Другие же варианты получения токена идут через шифрование и получение уникального токена.
Авторизационный токен можно хранить в local storage или в куках, однако в целях безопасности лучше хранить именно в куках, через HTTPS, флаг secure.
Хранение в local storage подходит разве что для внутреннего использования корпоративных небольших систем, и всё равно, это считается плохой практикой.
В случае каких-либо проблем с авторизацией или авторизационным токеном на практике встречается 401 ошибка.
Варианты авторизации в Postman
В Postman уже удобно сделаны шаблоны под авторизацию. Скорее всего на проекте встретится один или несколько из них.
Синхронность/Асинхронность
https://docs.google.com/presentation/d/14NFQc0xQWnmbphBnj8V5XbyXHiMxO1T4cbKYDjXKRlM/edit?usp=sharing
Тестирование бэкенда (общая инфа)
Тестирование бэкенда (backend testing) - это процесс проверки программного обеспечения, который выполняется на серверной стороне приложения или веб-сайта. Бэкенд отвечает за обработку запросов, выполнение бизнес-логики, взаимодействие с базами данных и другими внешними сервисами.
Основная цель тестирования бэкенда - убедиться, что серверная часть приложения работает правильно, безошибочно выполняет свои функции и взаимодействует с другими компонентами системы корректно.
Тестирование бэкенда может включать в себя следующие виды тестов:
- Тестирование API (Application Programming Interface) - проверка корректности работы API, его методов, входных и выходных данных.
- Тестирование базы данных - проверка корректности хранения и обработки данных, выполнение SQL-запросов, обновление и удаление записей.
- Тестирование производительности - оценка скорости и нагрузочной стойкости бэкенд-сервера при различных условиях нагрузки.
- Тестирование безопасности - обнаружение уязвимостей, защита от атак, проверка на соответствие стандартам безопасности.
- Тестирование интеграции - проверка взаимодействия бэкенд-сервера с другими компонентами системы, такими как фронтенд, внешние сервисы и т.д.
В общем, тестирование бэкенда необходимо для обеспечения качества и надежности серверной части приложения перед его запуском в продакшн среде.
В тестировании API выделяются шесть основных видов проверок, в зависимости от аспектов, которые проверяются:
- Тестирование методов: Каждый метод API проверяется индивидуально для убеждения в правильной работе и возврате ожидаемых результатов. Это включает проверку входных данных, выполнение операций и проверку вывода.
- Тестирование взаимодействий: Проверка взаимодействия API с другими компонентами программы, сервисами и другими API. Это гарантирует успешную отправку и получение данных, а также обработку различных сценариев использования
- Тестирование обработки ошибок: Проверка поведения API при возникновении непредвиденных ситуаций и ошибок, например, при передаче некорректных данных. Это гарантирует правильную обработку исключений и передачу корректных кодов ошибок.
- Тестирование авторизации и аутентификации: Проверка доступа к API и работа механизмов авторизации, определяющих, кто и каким функциям и данным имеет доступ.
- Тестирование производительности: Проверка производительности API при высоких нагрузках, включая его пропускную способность. Это гарантирует стабильную работу API даже при повышенном спросе.
- Тестирование безопасности: Проверка уязвимостей безопасности API для предотвращения утечек данных или несанкционированного доступа. Это включает анализ мер безопасности API и проведение тестов на проникновение для выявления потенциальных уязвимостей.
В рамках тестирования баз данных выделяют следующие виды проверок:
- Тестирование структуры данных (DDL): Это проверка правильности создания, изменения и удаления таблиц, индексов, ограничений и других объектов базы данных.
- Тестирование манипуляции данными (DML): Здесь проверяется корректность операций добавления, изменения, удаления и выборки данных.
- Тестирование хранимых процедур и функций: Проверка работоспособности программного кода, хранящегося в базе данных.
- Тестирование интеграции с приложениями: Это проверка правильности взаимодействия базы данных с приложениями, использующими её для хранения и обработки данных.
- Тестирование производительности: Оценка скорости выполнения запросов и выявление узких мест в работе базы данных.
- Тестирование безопасности: Проверка защищенности базы данных от несанкционированного доступа и утечки данных.
Тестирование интеграции: стратегии, методологии и подходы в интеграционном тестировании
Программная инженерия задает различные стратегии интеграционного тестирования:
Ниже приведены различные стратегии, способы их выполнения и их ограничения, а также преимущества.
Подход к интеграционному тестированию "Big Bang" (или "большой взрыв") предполагает интеграцию всех компонентов программного обеспечения одновременно в конечной среде тестирования. Этот метод особенно удобен в небольших проектах, когда все компоненты готовы для интеграции и тестирования одновременно, и когда нет необходимости проводить поэтапное или постепенное интеграционное тестирование.
Примером применения подхода "Big Bang" может быть тестирование небольшого веб-приложения, состоящего из клиентской части (фронтенд), серверной части (бэкенд) и базы данных. Предположим, что разработчики завершили разработку всех компонентов и готовы для интеграции:
- Интеграция всех компонентов: Все компоненты - фронтенд, бэкенд и база данных - интегрируются одновременно в конечной среде тестирования.
- Выполнение тестов: После интеграции проводятся тесты для проверки корректности работы приложения в целом. Это может включать в себя тестирование функциональности, производительности, безопасности и других аспектов приложения.
- Выявление и исправление ошибок: Если в процессе тестирования выявляются ошибки или проблемы, разработчики и тестировщики работают над их устранением.
Преимущества подхода "Big Bang" включают в себя простоту и быстроту интеграции, особенно в небольших проектах, где все компоненты могут быть интегрированы и протестированы одновременно. Однако недостатком этого подхода является то, что он может затруднить выявление и исправление ошибок из-за одновременной интеграции всех компонентов. Кроме того, если один из компонентов содержит серьезные ошибки, они могут повлиять на работу всего приложения.
В данном подходе тестирование выполняется путем объединения двух или более логически связанных модулей. Затем добавляются другие связанные модули и проверяются на правильность функционирования. Процесс продолжается до тех пор, пока все модули не будут соединены и успешно протестированы.
Поэтапный подход, в свою очередь, осуществляется двумя разными методами:
Так называемый инкрементальный подход: тестирование начинается с «верхних» модулей и идет далее к «нижним». Так делается потому, что чаще модули нижнего уровня еще не готовы (и тогда вместо неготовых модулей тестируют так называемые стабы).
Стабы (также заглушки) — макеты модулей, симулирующие их функциональность; такой макет принимает нужные параметры и отдает нужные результаты. Стабы имеют hard-coded (фиксированный) ввод и вывод, что помогает тестировать другие модули, интегрированные с тем который заменен стабом.
Плюсы: не нужно ждать пока все модули будут готовы. Можно приоритизировать сначала критически важные модули.
Минусы: нужно много низкоуровневых стабов. И как бы нет гарантии, что они будут протестированы нормально.
Инкрементальный подход здесь работает наоборот, «снизу вверх». Тестирование начинается с низкоуровневых модулей, затем переходят к высокоуровневым, по мере их готовности.
Здесь применяются тестовые драйверы, симулирующие функциональность высокоуровневых модулей, еще не интегрированных.
Преимущества: экономия времени.
Недостаток: высокоуровневые модули, тестируемые на поздних этапах, могут содержать баги, пропущенные из-за спешки.
Сэндвич (гибридная интеграция)
Эта стратегия представляет собой комбинацию подходов «сверху вниз» и «снизу вверх». Здесь верхнеуровневые модули тестируются с нижнеуровневыми, а нижнеуровневые модули интегрируются с верхнеуровневыми, соответственно, и тестируются. Эта стратегия использует и заглушки, и драйверы.
Так называемая «бутербродная интеграция». Сочетание двух описанных выше подходов. Тестирование начинается со «среднего» уровня, и продолжается одновременно в двух направлениях — вверх и вниз. Таким образом, сочетаются преимущества обоих подходов, интерфейсы тестируются быстрее.
Преимущества: гибкость; можно продвигаться в любом направлении, по ситуации. Вероятно, наиболее эргономичный метод, с возможностью приоритизации модулей.
Недостатки: на практике бывает сложно применять, нужно одновременно интегрировать код и продвигаться в обоих направлениях.
При интеграционном тестировании могут возникнуть ошибки и мы должны уметь их локализовывать. С этим нам помогает логирование.
Деплой версий. Jenkins. CI/CD
https://docs.google.com/presentation/d/183XOXJxmo8w90l4dzg-O-a9yRmkTvajpY_GYxdpMvTI/edit?usp=sharing
Jenkins на примере нашего сайта
Деплой (deploy) — это развертывание и запуск веб-приложения или сайта в его рабочей среде, то есть на сервере или хостинге. Разработчик загружает приложение, написанное на локальном компьютере, в специальное пространство, из которого оно доступно в интернете.
Чтобы задеплоить версию определенного микросервиса необходимо кликнуть по
Отслеживать версии можно в телеграм канале нашего разработчика. Там же разработчик описывает какие обновления появились в этой версии. Например, добавлены подробные логи об ошибках в бд. При деплое версии также необходимо смотреть на поды в кубернетисе, так как там могут возникать ошибки. Также внимательно следите за обновлениями версий, тк могут появляться новые таблицы в базе данных и при откате на предыдущую версию нужно будет в базе данных прописывать скрипт для удаления этой таблицы. Это необходимо для отката на предыдущую версию микросервиса в случае если в актуальной есть новые таблицы в базе данных.