|
|
|
# 1 Архитектура сервиса
|
|
|
|
|
|
|
|
## 1.1 Описание архитектуры приложения
|
|
|
|
|
|
|
|
Архитектура проекта описана на странице по [ссылке](Архитектура-проекта).
|
|
|
|
|
|
|
|
## 1.2 Описание алгоритма работы системы
|
|
|
|
|
|
|
|
Алгоритм работы системы можно описать следующей последовательностью действий:
|
|
|
|
1) Ожидание поискового запроса от чат-бота или внешнего сервиса;
|
|
|
|
2) Получение запроса микросервисом «Competence Search», отправка копий текстового запроса всем микросервисам-обработчикам (в данном случае это обработчики данных сервисов: Zulip, Wiki МИЭМ, Кабинет МИЭМ);
|
|
|
|
3) Параллельное формирование ответных сообщений каждым микросервисом-обработчиком, содержащих префиксы корпоративных почт кандидатов, оценку модели, а также дополнительную информацию (например, имя пользователя в корпоративном чате Zulip);
|
|
|
|
4) Асинхронный сбор ответов микросервисов-обработчиков главным микросервисом «Competence Search», вычисление итоговой оценки релевантности, сортировка списка кандидатов по убыванию итоговой оценки релевантности;
|
|
|
|
5) Отправка ответа на запрос;
|
|
|
|
6) В случае, если запрос был отправлен через чат-бот – форматирование ответа, отправка результата пользователю.
|
|
|
|
|
|
|
|
Асинхронный сбор ответов, а также параллельная и независимая друг от друга работа микросервисов позволяет ускорить время получения данных от микросервисов-обработчиков.
|
|
|
|
В случае, если один из сервисов не доступен, главный микросервис может отследить ошибку в отправке запроса и сформировать результат без использования данных проблемного сервиса, указав в ответе, что проблемный сервис недоступен. Это повышает степень отказоустойчивости приложения.
|
|
|
|
|
|
|
|
1. Ожидание поискового запроса от **чат-бота** или **внешнего сервиса**;
|
|
|
|
2. Получение запроса микросервисом **Competence Search**, отправка копий текстового запроса всем _микросервисам-обработчикам_ (в данном случае это обработчики данных сервисов: **Zulip**, **Wiki МИЭМ**, **Кабинет МИЭМ**);
|
|
|
|
3. Параллельное формирование ответных сообщений каждым _микросервисом-обработчиком_, содержащих префиксы корпоративных почт кандидатов, оценку модели, а также дополнительную информацию (например, имя пользователя в корпоративном чате **Zulip**);
|
|
|
|
4. Асинхронный сбор ответов _микросервисов-обработчиков_ главным микросервисом **Competence Search**, вычисление итоговой оценки релевантности, сортировка списка кандидатов по убыванию итоговой оценки релевантности;
|
|
|
|
5. Отправка ответа на запрос;
|
|
|
|
6. В случае, если запрос был отправлен через **чат-бот** – форматирование ответа, отправка результата пользователю.
|
|
|
|
|
|
|
|
> Асинхронный сбор ответов, а также параллельная и независимая друг от друга работа микросервисов позволяет ускорить время получения данных от _микросервисов-обработчиков_.
|
|
|
|
|
|
|
|
> В случае, если один из сервисов не доступен, главный микросервис может отследить ошибку в отправке запроса и сформировать результат без использования данных проблемного сервиса, указав в ответе, что проблемный сервис недоступен. Это повышает степень отказоустойчивости приложения.
|
|
|
|
|
|
|
|
## 1.3 Описание алгоритма и принципа работы модулей системы
|
|
|
|
|
|
|
|
### 1.3.1 Описание алгоритма и принципа работы микросервисов-обработчиков
|
|
|
|
|
|
|
|
Алгоритм работы микросервисов-обработчиков представлен на рисунке.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
Каждый обработчик в начале своей работы запускает два параллельных процесса. Слева изображен процесс-сервер. Большую часть времени сервер ожидает получения запроса. Как только запрос был отправлен, сервер принимает его и определяет тип запроса. Если запрос является поисковым, сервер использует обученную модель обработки данных для формирования ответа на поисковой запрос. В случае, если модель обработки данных не загружена в оперативную память (это происходит при первом запуске или при перезагрузке контейнера в случае сбоя), модель сначала загружается программой, затем формируется ответ. В конце ответ на запрос отправляется клиенту. HTTP статус запроса – 200 («Ok», «Успешно»). Если запрос является запросом на обновление модели, программа загружает из файла модель и отправляет клиенту сообщение с HTTP статусом 200 («Ok», «Успешно»). Все остальные запросы являются не валидными и клиенту возвращается сообщение с ошибкой и статусом HTTP 404 («Not found», «Не найден»).
|
|
|
|
Всего в программе находятся три _микросервиса-обработчика_:
|
|
|
|
- Обработчик данных **Zulip** ([директория микросервиса](https://git.miem.hse.ru/240/competence-search/-/tree/master/zulip));
|
|
|
|
- Обработчик данных **МИЭМ Wiki** ([директория микросервиса](https://git.miem.hse.ru/240/competence-search/-/tree/master/wiki));
|
|
|
|
- Обработчик данных сервиса **Личный Кабинет МИЭМ** ([директория микросервиса](https://git.miem.hse.ru/240/competence-search/-/tree/master/cabinet)).
|
|
|
|
|
|
|
|
Второй процесс ожидает времени начала обучения, установленного в конфигурационном файле. При наступлении времени обучения модель запускает функцию обучения модели, которая включает в себя загрузку новых данных сервиса и обучение самой модели. По завершении обучения модель сохраняется в бинарный файл. После этого процесс отправляет запрос на обновление на процесс-сервер и возвращается в режим ожидания времени обучения.
|
|
|
|
Далее все ссылки на участки кода будут приведены в виде гиперссылок со следующими условными обозначениями:
|
|
|
|
- [`Z`](https://git.miem.hse.ru/240/competence-search/-/tree/master/zulip) - ссылка на код из обработчика данных **Zulip**;
|
|
|
|
- [`W`](https://git.miem.hse.ru/240/competence-search/-/tree/master/wiki) - ссылка на код из обработчика данных **МИЭМ Wiki**;
|
|
|
|
- [`C`](https://git.miem.hse.ru/240/competence-search/-/tree/master/cabinet) - ссылка на код из обработчика данных ***Личный Кабинет МИЭМ**;
|
|
|
|
|
|
|
|
Все запросы локального REST API процесса-сервера представлены в таблице 1.
|
|
|
|
>>>
|
|
|
|
:warning: **Внимание!** :warning:
|
|
|
|
|
|
|
|
| URL и метод запроса | Описание |
|
|
|
|
| ------ | ------ |
|
|
|
|
| /ping (GET) | Запрос, возвращающий пустую JSON строку. Используется в отладочных целях для определения доступности сервиса. Возвращает ответ HTTP со статусом 200 («Ok», «Успешно»). |
|
|
|
|
| /handler (PATCH) | Запрос на обновление модели обработчика. Возвращает ответ HTTP со статусом 200 («Ok», «Успешно») в случае успешной загрузки модели. В случае отсутствия файла возвращает сообщение с HTTP статусом 500 («Internal Server Error», «Внутренняя ошибка сервера»). |
|
|
|
|
|/users (GET)|Запрос на поиск информации по запросу. В параметрах запроса должно быть задано ключевое слово «query» со значением в виде строки (поисковой запрос). Опционально можно передать параметр «more». Если его значение равно «true», запрос вернет дополнительную информацию. В иных случаях запрос вернет префиксы пользователей и оценку модели обработки данных. В случае отсутствия параметра «query» возвращает ответ с HTTP статусом 400 («Bad request», «Неправильный, некорректный запрос»). В случае, если модель не загружена, выполняет загрузку и, в случае ошибок, возвращает ошибки запроса PATCH /handle. В случае успешного выполнения запроса возвращает сообщение с HTTP статусом 200 («Ok», «Успешно»), а также телом в виде JSON строки.|
|
|
|
|
Все ссылки с учетом строк приведены для программы на момент следующего [коммита](240/competence-search@c911531e19c93a1f7a0dc6b70b70c419284db23d). В будущем номера строк **могут быть смещены** в следствие редактирования исходного кода!
|
|
|
|
>>>
|
|
|
|
|
|
|
|
Каждый обработчик в начале своей работы запускает **два** параллельных процесса ([`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/main.py#L20), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/main.py#L20), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/main.py#L20)). Точкой входа для запуска процессов является строчка с ключом `command` в конфигурации запуска в файле [`docker-compose.yml`](https://git.miem.hse.ru/240/competence-search/-/blob/master/docker-compose.yml) или [`docker-compose.prod.yml`](https://git.miem.hse.ru/240/competence-search/-/blob/master/docker-compose.prod.yml).
|
|
|
|
|
|
|
|
Формат возвращаемой запросом GET /users JSON строки представлен на рисунке.
|
|
|
|

|
|
|
|
Слева изображен **процесс-сервер**. Большую часть времени сервер ожидает получения запроса. Как только запрос был отправлен, сервер принимает его и определяет тип запроса. Если запрос является поисковым, сервер использует обученную модель обработки данных для формирования ответа на поисковой запрос (метод `GET` **/users** [`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/server/server.py#L66), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/server/server.py#L39), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/server/server.py#L37)). В случае, если модель обработки данных не загружена в оперативную память (это происходит при первом запуске или при перезагрузке контейнера в случае сбоя), модель сначала загружается программой, затем формируется ответ. В конце ответ на запрос отправляется клиенту. `HTTP` статус запроса – `200` («Ok», «Успешно»). Если запрос является запросом на обновление модели (метод `PATCH` **/handler** [`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/server/server.py#L36), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/server/server.py#L25), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/server/server.py#L23)), программа загружает из файла модель и отправляет клиенту сообщение с `HTTP` статусом `200` («Ok», «Успешно»). Все остальные запросы являются не валидными и клиенту возвращается сообщение с ошибкой и статусом HTTP `404` («Not found», «Не найден»).
|
|
|
|
|
|
|
|
Ключами корневого объекта JSON являются «data» и «message». Ключ «message» является опциональным и служит для передачи служебных сообщений (например, если запрос был выполнен, но часть данных не была загружена). По ключу «data» находится объект, хранящий почты пользователей в виде ключей объекта. Значениями этих ключей являются объекты, содержащие как минимум один ключ – имя модели (или обрабатываемого сервиса), нижнее подчеркивание и слово score. Значением является оценка релевантности пользователя моделей обработки данных. В объектах пользователей также может быть представлена любая другая дополнительная информация (например, имя пользователя в корпоративном чате Zulip), если в параметрах запроса был указан параметр «more» со значением «true».
|
|
|
|
**Второй** процесс ожидает времени начала обучения, установленного в конфигурационном файле (о настройке конфигурационных файлов можно прочитать [здесь](Руководство-администратора#32-настройка-времени-обучения-микросервисов-обработчиков)). При наступлении времени обучения модель запускает функцию обучения модели ([`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/trainer.py#L19), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/trainer.py#L15), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/trainer/trainer.py#L15)), которая включает в себя загрузку новых данных сервиса и обучение самой модели. По завершении обучения модель сохраняется в **бинарный файл** (`<имя_сервиса>/data/model.model`). После этого процесс отправляет запрос (метод `PATCH` **/handler** [`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/trainer/trainer.py#L31), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/trainer/trainer.py#L27), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/trainer/trainer.py#L27)) на обновление на процесс-сервер и возвращается в режим ожидания времени обучения.
|
|
|
|
|
|
|
|
Все запросы локального `REST API` **процесса-сервера** представлены в таблице:
|
|
|
|
|
|
|
|
| URL и метод запроса | Описание |
|
|
|
|
| ------ | ------ |
|
|
|
|
| `GET` **/ping** ([`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/server/server.py#L31), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/server/server.py#L20), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/server/server.py#L18)) | Запрос, возвращающий пустую `JSON` строку. Используется в отладочных целях для определения доступности сервиса. Возвращает ответ `HTTP` со статусом `200` («Ok», «Успешно»). |
|
|
|
|
| `PATCH` **/handler** ([`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/server/server.py#L36), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/server/server.py#L25), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/server/server.py#L23)) | Запрос на обновление модели обработчика. Возвращает ответ `HTTP` со статусом `200` («Ok», «Успешно») в случае успешной загрузки модели. В случае отсутствия файла возвращает сообщение с `HTTP` статусом `500` («Internal Server Error», «Внутренняя ошибка сервера»). |
|
|
|
|
| `GET` **/users** ([`Z`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/zulip/src/server/server.py#L66), [`W`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/wiki/src/server/server.py#L39), [`C`](https://git.miem.hse.ru/240/competence-search/-/blob/c911531e19c93a1f7a0dc6b70b70c419284db23d/cabinet/src/server/server.py#L37)) | Запрос на поиск информации по запросу. В параметрах запроса должно быть задано ключевое слово `query` со значением в виде строки (поисковой запрос). Опционально можно передать параметр `more`. Если его значение равно `true`, запрос вернет дополнительную информацию. В иных случаях запрос вернет префиксы пользователей и оценку модели обработки данных. В случае отсутствия параметра `query` возвращает ответ с `HTTP` статусом `400` («Bad request», «Неправильный, некорректный запрос»). В случае, если модель не загружена, выполняет загрузку и, в случае ошибок, возвращает ошибки запроса `PATCH` **/handle**. В случае успешного выполнения запроса возвращает сообщение с `HTTP` статусом `200` («Ok», «Успешно»), а также телом в виде `JSON` строки.|
|
|
|
|
|
|
|
|
Формат возвращаемой запросом `GET` **/users** `JSON` строки:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"data": {
|
|
|
|
"user_1": {
|
|
|
|
"<имя>_score": 9.3
|
|
|
|
},
|
|
|
|
"user_2": {
|
|
|
|
"<имя>_score": 6.4
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"message": "Сообщение"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Ключами корневого объекта `JSON` являются `data` и `message`. Ключ `message` является опциональным и служит для передачи служебных сообщений (например, если запрос был выполнен, но часть данных не была загружена). По ключу `data` находится объект, хранящий префиксы почты пользователей в виде ключей объекта. Значениями этих ключей являются объекты, содержащие как минимум один ключ – имя модели (или обрабатываемого сервиса), нижнее подчеркивание и слово `score`. Значением является оценка релевантности пользователя **моделей обработки данных**. В объектах пользователей также может быть представлена любая другая дополнительная информация (например, имя пользователя в корпоративном чате **Zulip**), если в параметрах запроса был указан параметр `more` со значением `true`.
|
|
|
|
|
|
|
|
### 1.3.2 Описание алгоритма и принципа работы главного микросервиса
|
|
|
|
Алгоритм работы микросервиса «Competence Search» можно описать следующей последовательностью действий:
|
| ... | ... | |