Данный текст преимущественно ориентирован на новичков в IT-индустрии, предназначен для желающих познакомиться с профессией, узнать о ее содержании, основных принципах, практиках и инструментах, используемых в ней, и является попыткой структурировать и свести воедино свои знания и опыт, накопленные за время работы в этой увлекательной профессии.
Кто такой системный аналитик?
Системный аналитик является посредником между бизнесом и разработчиками. Он изучает потребности бизнеса, формализует их, передает разработчикам в виде требований и участвует в приемке конечного результата. Для этой работы необходимы хорошие коммуникативные навыки и аналитический склад ума.
Главная цель аналитика - понять проблему бизнеса и предложить решение с использованием информационных технологий.
Системный аналитик должен быть погружен в технические аспекты информационных систем. Он должен обладать большим количеством практических технических навыков и стараться «говорить на одном языке» с разработчиками - детально описать все технические нюансы, связанные с разработкой.
В современных реалиях от системного аналитика зачастую требуется глубокое погружение в предметную область (бизнес-домен) и особенности внутренних процессов. Аналитики должны стараться следить за тенденциями в технологиях, а также уметь добывать необходимые знания и применять их на практике.
Для знакомства с профессией необходимо изучить базовые понятия, на которых основаны компьютерные системы и сети.
Интернет и взаимодействие в нем
Своим бурным ростом и развитием IT-сфера обязана сети Интернет. В основе всего взаимодействия в интернете лежит модель OSI, а точнее ее развитие - модель TCP/IP.
Модель OSI (Open System Interconnection), как и модель TCP/IP описывают, как устройства в локальных и глобальных сетях обмениваются данными и что происходит с этими данными.
![Модель OSI и модель TCP/IP Модель OSI и модель TCP/IP](https://habrastorage.org/getpro/habr/upload_files/bd0/6d7/760/bd06d77604412910c8860d99235f6a6e.png)
Канальный уровень (Link layer) описывает организацию физического соединения между устройствами в пределах одной сети. Протоколы канального уровня работают с физическими адресами (MAC-адресами) устройств.
Сетевой уровень (Network layer) описывает правила передачи данных из одной сети в другую (маршрутизацию).
Транспортный уровень (Transport layer) - отвечает за передачу данных с гарантированной или негарантированной доставкой между устройствами.
Прикладной уровень (Application layer) – обеспечивает взаимодействие между приложениями в сети.
Процесс работы TCP/IP
перед отправкой информация разделяется на пакеты, каждый из которых получает свой уникальный IP-адрес, указывающий на конечную точку доставки;
на транспортном уровне (TCP) проверяется, чтобы все пакеты пришли без ошибок и в нужном порядке. Кроме того, контролируется поток информации, предотвращая перегрузку сети;
на сетевом уровне (IP) каждому пакету сообщается, какие узлы или маршруты следует использовать для достижения конечной точки;
на канальном уровне (Ethernet) каждый пакет получает физический номер (MAC-адрес) для доставки на конкретное устройство внутри сети;
по прибытии в конечную точку доставки пакеты собираются в правильном порядке и восстанавливают исходную информацию.
Сетевое взаимодействие. Протокол HTTP
Правила взаимодействия устройств в сети Интернет определяются протоколом HTTP (Hypertext Transfer Protocol). Он устанавливает порядок формирования запросов от веб-браузера (клиента) к веб-серверу (серверу).
Защищенной версией протокола HTTP является протокол HTTPS (Hypertext Transfer Protocol over Secure Socket Layer), обеспечивающий защиту данных в сети с помощью шифрования передаваемых данных в соответствии с протоколом SSL.
Основой HTTP является взаимодействие «клиент-сервер»:
![Взаимодействие «клиент-сервер» Взаимодействие «клиент-сервер»](https://habrastorage.org/getpro/habr/upload_files/b4f/38e/80b/b4f38e80b603b49c7e3e66d7a57062e4.png)
клиент инициирует соединение и посылает запрос на сервер (Request);
сервер обрабатывает запрос и посылает ответ клиенту (Response).
HTTP-запрос
![HTTP-запрос HTTP-запрос](https://habrastorage.org/getpro/habr/upload_files/d12/31a/bdf/d1231abdf480330c187c788d5de986b9.png)
HTTP-запрос клиента к веб-серверу должен включать:
URL (Uniform Resource Locator) - текстовая строка (адрес), которая указывает на местоположение ресурса в сети;
метод (Method) - определяет действие, выполняемое сервером, после получения сообщения;
заголовок (Header) - часть HTTP-запроса, которая содержит техническую информацию, необходимую для формирования запроса или ответа;
тело (Body) - сервер и клиент передают друг другу данные в теле (Body) HTTP-запроса.
Скрытый текст
![Пример HTTP-запроса Пример HTTP-запроса](https://habrastorage.org/getpro/habr/upload_files/559/534/7a8/5595347a8b2f49aaf858ff951b0e1eba.png)
Основные методы, которые предоставляет HTTP:
POST - создание ресурса. Клиент передаёт на сервер информацию, которую он должен записать у себя определённым образом;
GET - чтение ресурса. Клиент запрашивает у сервера определённую информацию и получает ее в ответ;
PUT - полное обновление информации. Клиент может заменить существующую на сервере информацию;
PATCH - частичное обновление информации. Клиент может заменить часть существующей на сервере информации;
DELETE - удаление информации. Клиент может удалить информацию с сервера.
Скрытый текст
CONNECT - метод для установления тоннеля (двусторонней связи) между клиентом и сервером.
HEAD - запрашивает заголовки. Может быть выполнен перед загрузкой большого ресурса для получения данных о ресурсе.
OPTIONS - метод запроса данных о методах, поддерживаемых ресурсом.
TRACE - метод для проверки соединения. Сервер должен вернуть полученное сообщение назад клиенту в теле ответа.
Применение методов соответствует спецификации протокола HTTP, однако это не означает, что вы не можете отправить запрос на создание ресурса с помощью метода GET, или запросить ресурс на чтение методом POST.
Скрытый текст
Чаще всего в методе GET параметры передаются в URL (1) или в параметрах запроса (query parameters) (2):
1. GET https://qwerty.com/books/245 - в этом случае в запросе передан идентификатор (245) некой книги (books) в магазине на сайте (qwerty.com).
2. GET https://qwerty.com/api/v1/books?author=Orwell&title=1984 - в этом случае в запросе переданы параметры типа «ключ-значение», которые «прикрепляются» к URL ресурса через символ «?». Если запрос подразумевает поиск по нескольким параметрам, они могут быть соединены через «&».
Но если запрос будет сложнее и надо будет передать в нем больше параметров, то можно столкнуться с ограничением длины URL-строки в 2048 символов, и параметры будут потеряны при передаче на сервер.
Поэтому в таких случаях используют метод POST, в котором можно сложить запрашиваемые параметры в тело запроса в виде JSON-объекта (о нем речь пойдет далее) и спокойно передать на сервер.
HTTP-ответ
Сервер также отвечает клиенту определенным образом.
![HTTP-ответ HTTP-ответ](https://habrastorage.org/getpro/habr/upload_files/4d7/ddb/fe8/4d7ddbfe823a16dab6cfa671ab913254.png)
HTTP-ответ состоит из кода ответа, заголовков и тела:
коды ответа объединены в группы по значению, которое даёт краткую информацию о результате выполнения запроса;
в заголовке ответа сервер сообщает клиенту, как интерпретировать полученный ответ и правильно обработать HTTP-сообщение сервера;
тело ответа содержит данные, которые являются результатом выполнения запроса. Но не у всех ответов оно есть. Например, у DELETE запроса тело ответа может отсутствовать.
Скрытый текст
![Пример HTTP-ответа Пример HTTP-ответа](https://habrastorage.org/getpro/habr/upload_files/460/b12/000/460b12000e1f1d6294cf65bcfefde554.png)
Формат обмена данными. JSON
Как и для передачи тела запроса, так и для передачи тела ответа самым популярным форматом данных является формат JSON (JavaScript Object Notation), определяющий правила описания объектов.
![JSON JSON](https://habrastorage.org/getpro/habr/upload_files/359/8c2/cfb/3598c2cfbefc649eaa05dc300cb4b21b.png)
Объект (Object) — это некоторое понятие предметной области в виде пары
{ "ключ": "значение" }. Начало и конец объекта обозначаются фигурными скобками.
Один объект от другого можно отличить благодаря их свойствам, называемым ключом (Key).
Каждый объект содержит один или несколько ключей.
Каждый ключ содержит одно или несколько значений (Value).
Если у ключа множество значений, начало и конец множества обозначаются квадратными скобками, а значения разделяются запятой. Несколько пар «ключ/значение» тоже разделяются запятой.
Значение ключа также можно представить, как объект, состоящий из объектов. Подобная вложенность заключается в отдельные фигурные скобки (как для обозначения начала и конца объекта), а свойства внутри неё также берутся в кавычки и отделяются запятыми.
В JSON можно передавать следующие типы данных: строка, число (целое или дробное), логический тип данных (Boolean) – true или false, массив и объект.
Для передачи даты обычно используют формат unix-time в строке, например: "2024-07-26T14:30:00-03:00".
Фронтенд и бэкенд в приложениях. API
Фронтенд (frontend) и бэкенд (backend) - две основные части системы, которые используются в архитектуре программного обеспечения.
Фронтенд представляет собой презентационную часть системы, ее пользовательский интерфейс и связанные с ним компоненты.
Бэкенд является внутренней реализацией системы.
Такое разделение позволяет фронтенд-разработчикам сосредоточиться на интерфейсных решениях, не зная деталей внутренней реализации, а бэкенд-разработчикам - на создании программных интерфейсов (application programming interface).
API (Application Programming Interface) - программный интерфейс, который описывает способы взаимодействия одной компьютерной программы с другими. Зачастую для обозначения API используют слово «контракт». Иными словами - договор между двумя сторонами, определяющий обмен информацией между ними.
Упрощенно, API включает в себя: операцию, данные на входе операции, данные на выходе операции, а также логику обработки ошибок.
Одними из популярных подходов к разработке в настоящее время являются:
Code first — сначала пишем код, потом по нему генерируем контракт;
API first (Contract first ) — сначала создаем контракт, потом по нему пишем или генерируем код.
API делят на те, которые обеспечивают взаимодействие бэкенд-бэкенд: backend-API и фронтенд-бэкенд: web-API.
![Виды API Виды API](https://habrastorage.org/getpro/habr/upload_files/5c7/d2f/543/5c7d2f543630b419013606c9f760a41f.png)
Взаимодействия между системами бывают:
синхронные (например: REST API, SOAP, gRPC);
асинхронные (например: Kafka, RabbitMQ, WebSocket).
Различия их в том, что приложения с асинхронным взаимодействием не ждут ответа после отправки запроса, а могут продолжить выполнять свой основной поток задач.
![Синхронное и асинхронное взаимодействие Синхронное и асинхронное взаимодействие](https://habrastorage.org/getpro/habr/upload_files/d53/44c/e87/d5344ce87fff83175fa3275159f73d2a.png)
Интеграцию по API используют, когда необходимо:
обмениваться данными в режиме реального времени;
иметь гибкий доступ к функционалу приложения (системы);
иметь способы аутентификации и авторизации для защиты доступа к системе или ее данным.
Базы данных. SQL, noSQL
Для хранения и обработки информации используют базы данных, различающиеся способом хранения данных.
Если данные в базе представлены в виде связанных таблиц, такую базу данных называют реляционной (англ. relation, «связь»).
Основные понятия.
Сущность (entity) – объект предметной области, который представлен в базе. Сущности обычно соответствуют таблицам в реляционных базах.
Атрибут (attribute) – характеристика сущности. Атрибуты соответствуют столбцам в реляционных базах.
Для обеспечения уникальности записи в таблице к каждой записи добавляется признак (атрибут) — первичный ключ (primary key), который может быть составным (состоять из значений нескольких атрибутов).
Таблицы в базе данных не существуют изолированно друг от друга, между ними устанавливаются связи.
Внешний ключ (foreign key) – атрибут, ссылающийся на первичный ключ другой сущности. Он обеспечивает однозначную логическую связь записей между таблицами внутри одной базы данных.
Связи между таблицами бывают следующих типов:
Один-к-одному (one-to-one) – одной записи в таблице А соответствует одна запись в таблице В;
Один-ко-многим (one-to-many) – одной записи в таблице А может соответствовать несколько записей в таблице В (в обратную сторону не работает);
Многие-ко-многим (many-to-many) – одной записи в таблице А соответствует несколько записей в таблице В и так же в обратную сторону.
Всякую связь "многие–ко–многим" в реляционной базе данных необходимо заменить на связь "один–ко–многим" с помощью введения дополнительных таблиц.
Нормализация – это организация данных в таблицах таким образом, чтобы устранить дублирование и избыточность данных и тем самым избежать нарушения целостности данных при их изменении (аномалий). База данных считается нормализованной после достижения третьей нормальной формы.
Виды нормальных форм (рассмотрим только наиболее часто встречающиеся на практике три формы):
1НФ: В таблице нет повторяющихся строк.
2НФ: У таблицы есть первичный ключ, а все остальные поля зависят него, но не от его части (если первичный ключ составной).
3НФ: Все атрибуты, не являющиеся ключом зависят только от первичного ключа и не зависят друг от друга.
Базы данных управляются системами управления базами данных - СУБД (например, PostgreSQL, mySQL итд).
Для работы с базой данных существует свой язык запросов – SQL (Structured Query Language).
Запросы в языке SQL пишут с помощью операторов.
Скрытый текст
SELECT - оператор чтения записи из таблицы.
INSERT - оператор вставки записи в таблицу.
UPDATE - оператор обновления записи в таблице.
DELETE - оператор удаления записи из таблицы.
FROM – оператор, указывающий таблицу, в которой проводится операция.
WHERE – оператор фильтрации.
ORDER BY – оператор сортировки записей.
GROUP BY – оператор группировки записей.
HAVING – оператор фильтрации поверх группировки.
LIMIT – оператор ограничения количества читаемых записей.
OFFSET – оператор пропуска записей при чтении.
AND, OR, NOT – логические операторы.
IN, LIKE, BETWEEN – операторы условия.
JOIN – оператор соединения таблиц.
INNER JOIN - предполагает объединение по «внутренней» области, общей для двух таблиц.
LEFT OUTER JOIN - в результат объединения войдут все записи из левой таблицы
RIGHT OUTER JOIN - в результат объединения войдут все записи из правой таблицы
FULL OUTER JOIN - в результат объединения войдут все записи из двух таблиц
Если данные в БД представлены не в виде связанных таблиц, то такие БД относятся к типу noSQL (not only SQL). Выделяют четыре основных типа noSQL СУБД:
key-value СУБД – данные хранятся в виде записи «ключ - значение» (Redis, DynamoDB);
колончатые СУБД - данные хранятся в виде разреженной матрицы, строки и столбцы которой используются как ключи (HBase, Cassandra);
документоориентированные СУБД - хранят иерархические структуры данных (MongoDB);
графовые СУБД - хранят данные в виде графа и его обобщений (Neo4j).
Как устроены современные приложения и системы
В завершении первой части статьи рассмотрим пример абстрактной системы.
Рассмотрим вариант клиент-серверной архитектуры, в которой у нас есть сервер (Application Server) с монолитным приложением и два клиента, общающиеся с приложением по REST API.
![Простейший вариант клиент-серверной архитектуры Простейший вариант клиент-серверной архитектуры](https://habrastorage.org/getpro/habr/upload_files/2b7/892/6e9/2b78926e9bd78e0c08db9088cd5411a1.png)
Для того, чтобы хранить данные приложению необходимо иметь подключение к базе данных. В данном случае чаще всего для хранения структурированных данных используют реляционные БД.
![Добавляем БД для хранения данных Добавляем БД для хранения данных](https://habrastorage.org/getpro/habr/upload_files/556/3ca/0c4/5563ca0c447f008dfb6274399dff6074.png)
С ростом количества запросов к приложению, необходимо предусмотреть кэш, чтобы сократить время отклика приложения при частых запросах одних и тех же редко изменяемых данных.
Так как БД хранит данные на жестком диске, то для ускорения доступа к ним логично хранить данные в оперативной памяти на локальном сервере (in-memory cache) или на отдельном сервере с помощью in-memory database.
![Добавляем кэш для хранения часто запрашиваемых и редко изменяемых данных Добавляем кэш для хранения часто запрашиваемых и редко изменяемых данных](https://habrastorage.org/getpro/habr/upload_files/fc3/c58/c09/fc3c58c094d9eef3632524db2f9054bf.png)
Для обеспечения отказоустойчивости приложения, хранения и доступа к наиболее критичным данным, необходимо использовать подходы к масштабированию БД, один из которых – репликация.
С этой целью БД объединяются в кластер (Database Cluster). Объявляется Master Server, в случае выхода из строя которого основную нагрузку до его восстановления принимает Slave сервер. Данные реплицируются из Master-ноды по всем Slave-нодам.
![Масштабируем БД Масштабируем БД](https://habrastorage.org/getpro/habr/upload_files/aab/4d7/586/aab4d7586c7def2f0c039fceede844d3.png)
С ростом нагрузки возникает необходимость перейти к микросервисной архитектуре. Монолитное приложение разбивается на сервисы (каждый из которых выполняет определенный кусок логики внутри бизнес-контекста).
Для маршрутизации запросов от клиентских устройств выделяется отдельный слой (приложение) API Gateway, который помимо маршрутизации запросов между сервисами выполняет набор дополнительных функций (о которых будет сказано далее).
Если к БД обращаются несколько микросервисов, то рекомендуется выделение отдельного сервиса (handler) для работы с этой БД.
![Переходим к микросервисной архитектуре Переходим к микросервисной архитектуре](https://habrastorage.org/getpro/habr/upload_files/20f/bc6/6ff/20fbc66ffc85e843c68aa6bdd7e282c5.png)
Рассмотрим масштабирование приложений.
Для того, чтобы обрабатывать возросшее количество запросов можно добавить реплик (экземпляров) каждого приложения. Таким образом вырастет и количество серверов, которые объединяются в кластера (Server Cluster).
Для балансировки трафика между кластерами серверов и экземплярами сервисов используется API Gateway с его функционалом load balancing.
![Масштабируем приложение Масштабируем приложение](https://habrastorage.org/getpro/habr/upload_files/5d9/538/0db/5d95380db06ae6c8b56b677d2dbb239f.png)
При росте нагрузки синхронный подход (REST API) к обмену сообщениями начнет давать все большую задержку, вызванную тем, что на время установления соединения все ресурсы (порты) сервиса будут заняты.
К тому же в случае разрыва соединения или отказа сервиса часть сообщений может быть потеряна.
Для избегания этих ситуаций переходят к асинхронному взаимодействию. Одним из самых распространенных подходов является использование брокеров сообщений (Kafka, RabbitMQ).
В случае с Kafka, сервис, передающий сообщение, записывает его в соответствующий топик (очередь сообщений), из которого это сообщение вычитывается другим сервисом.
Таким образом обеспечивается слабая связанность сервисов и гарантия доставки сообщений.
![Добавляем асинхронное взаимодействие между сервисами Добавляем асинхронное взаимодействие между сервисами](https://habrastorage.org/getpro/habr/upload_files/a37/8cb/83b/a378cb83bc9cd88ac38ec8f2a996f49f.png)
Для хранения неструктурированных данных (временных рядов, документов JSON или файлов) более производительным решением по сравнению с реляционными базами данных будут noSQL БД и объектные хранилища S3.
![Храним неструктурированные данные Храним неструктурированные данные](https://habrastorage.org/getpro/habr/upload_files/229/923/d98/229923d987b17e1a6df468735cdc3f82.png)
Для обеспечения наблюдаемости сервисов необходимо использовать системы мониторинга, сбора логов и метрик.
Самыми популярными решениями является использование связки ElasticSearch (БД) + Kibana (графический интерфейс) и/или PrometheusDB (БД) + Grafana (графический интерфейс).
![Обеспечиваем наблюдаемость Обеспечиваем наблюдаемость](https://habrastorage.org/getpro/habr/upload_files/62d/3a4/536/62d3a45363ccd18cacfb2775f4d66eb8.png)
В этой статье вы узнали об основах сетевого взаимодействия, основном протоколе и формате обмена данными в сетях, из каких частей состоят простейшие приложения и увидели пример сложного приложения в виде распределенной системы.
Для того, чтобы понять каким образом можно проектировать и создавать такие системы в следующих частях будут рассмотрены типы требований, процесс их сбора, а также способы и инструменты документирования, типы программной архитектуры и взаимодействий, а также многое другое, что поможет получить более полное представление о профессии системного аналитика.
Эту и другие статьи по системной аналитике и IT-архитектуре, вы сможете найти в моем небольшом уютном Telegram-канале: Записки системного аналитика
OlegZH
Будут ли здесь приведены примеры конкретных систем, способов и принципов их построения?