Всем привет!

Сегодня я расскажу, как мы разработали распределённое приложение для анализа вакансий с платформы hh.ru. Мы применили микросервисную архитектуру, контейнеризацию, брокеры сообщений и инструменты визуализации данных, чтобы создать решение, которое может быть полезно аналитикам, компаниям и соискателям.

Если вы хотите узнать, как собрать все эти технологии в единое целое и сделать это эффективно — устраивайтесь поудобнее. Поехали!


Идея проекта

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

  • Собирает данные с платформы hh.ru с помощью API.

  • Обрабатывает их и сохраняет в базу данных.

  • Обеспечивает поиск и визуализацию информации для конечных пользователей.

  • Масштабируется при росте нагрузки.

Для этого мы решили использовать микросервисную архитектуру, так как она позволяет:

  • Изолировать отдельные модули приложения.

  • Масштабировать компоненты независимо друг от друга.

  • Легко добавлять новые функции.


Архитектура решения

Архитектура построена из следующих компонентов:

  1. Фронтенд: Vue.js, отображение вакансий и диаграмм.

  2. Бэкенд: Node.js (NestJS), взаимодействие с базами данных и брокером сообщений Kafka.

  3. Сервис сбора данных: Python, интеграция с API hh.ru.

  4. Хранилища данных: MongoDB для структурированных данных, Elasticsearch для аналитики.

  5. Kafka: асинхронная передача сообщений между сервисами.

  6. Nginx: балансировка нагрузки и проксирование запросов.

Схема архитектуры

Архитектура системы
Архитектура системы

Технические детали

1. Фронтенд

Фронтенд написан на Vue.js. Это позволило быстро создать компонентный интерфейс, поддерживающий адаптивный дизайн.

Ключевые инструменты:

  • Axios — для запросов к API.

  • Chart.js — для построения графиков.

Пример компонента для отображения вакансий:

<template>
  <div class="jobs">
    <div v-for="job in jobs" :key="job.id">
      <h3>{{ job.title }}</h3>
      <p>{{ job.description }}</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return { jobs: [] };
  },
  async mounted() {
    const response = await fetch('/api/jobs');
    this.jobs = await response.json();
  }
};
</script>

2. Бэкенд

Бэкенд реализован на Node.js с использованием NestJS. Это позволило модульно организовать код, выделив такие модули, как:

  • Контроллеры: принимают HTTP-запросы.

  • Сервисы: реализуют бизнес-логику.

  • Интеграция с Kafka: обработка сообщений от других микросервисов.

Пример контроллера API:

@Controller('api/jobs')
export class JobsController {
  constructor(private readonly jobsService: JobsService) {}

  @Get()
  async getAllJobs() {
    return this.jobsService.findAll();
  }
}

Для взаимодействия с MongoDB используется Mongoose:

@Injectable()
export class JobsService {
  constructor(@InjectModel(Job.name) private jobModel: Model<Job>) {}

  async findAll(): Promise<Job[]> {
    return this.jobModel.find().exec();
  }
}

3. Сервис сбора данных

Для сбора вакансий с hh.ru используется Python. API hh.ru позволяет фильтровать данные по региону, специальности и другим параметрам.

Ключевые инструменты:

  • aiohttp — асинхронные запросы.

  • pymongo — сохранение данных в MongoDB.

Асинхронная функция для запросов к API hh.ru:

async def fetch_vacancies(self, session, url, params=None):
    async with session.get(url, params=params) as response:
        if response.status == 200:
            return await response.json()
        else:
            logging.error(f"Ошибка {response.status}")

4. Хранилища данных

  1. MongoDB: Основное хранилище данных.

  2. Elasticsearch: Используется для поиска и аналитики.

Данные индексируются в Elasticsearch, после чего визуализируются в Kibana.


5. Kafka

Брокер сообщений Kafka обеспечивает взаимодействие между микросервисами.

Конфигурация Docker Compose для Kafka:

version: '3.7'
services:
  kafka:
    image: confluentinc/cp-kafka:latest
    environment:
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181

6. Nginx

Для маршрутизации запросов настроен Nginx. Он распределяет трафик между экземплярами бэкенда.

Пример конфигурации Nginx:

upstream backend_servers {
    server backend_1:3000;
    server backend_2:3000;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend_servers;
    }
}

Результаты анализа

На основе данных с hh.ru мы провели несколько ключевых исследований:

  1. Распределение вакансий по уровням опыта:

    • Senior: 60%.

    • Middle: 30%.

    • Junior: 10%.

  2. Популярные технологии:

    • Python и JavaScript — лидеры.

  3. География:

    • 70% вакансий сосредоточено в Москве и Санкт-Петербурге.

  4. Тип занятости:

    • Полная занятость доминирует, но гибкие графики набирают популярность.


Итоги и выводы

Этот проект показал, как можно собрать мощное и масштабируемое приложение с использованием современных технологий. Мы использовали Docker для контейнеризации, Kafka для обмена сообщениями, а также Elasticsearch и Kibana для визуализации данных.

Проект может быть полезен:

  • Исследователям рынка труда.

  • Компаниям для мониторинга востребованных навыков.

  • Соискателям, чтобы понимать тенденции.

Если вам интересно узнать больше о проекте, пишите в комментариях — с радостью отвечу!


Комментарии (9)


  1. gmtd
    18.12.2024 20:30

    Какой-то жуткий оверинжениринг...
    Vue, MySQL и PHP


    1. mxr
      18.12.2024 20:30

      Vue, MySQL и PHP

      Звучит как монолит на Laravel c Vue через Inertia =)

      Не плохой бы сервис вышел, но таким образом мы отказываешься лишь от node.js в данной архитектуре. И даже так, в качестве зависимости он нужен.


  1. Folko85
    18.12.2024 20:30

    И на основе какой выборки эта статистика?


  1. PrinceKorwin
    18.12.2024 20:30

    Эм. А сколько реально у вас данных было скравлено в итоге?

    Звучит так, что достаточно какого-то SQL для хранилища. А аналитику строить по данным в памяти. Есть подозрение, что оно все туда влезет.


  1. Horocek
    18.12.2024 20:30

    Это ИИ статья на мой взгляд.


  1. cmyser
    18.12.2024 20:30

    Покажи графики, ссылку на сайт, конфиги можно и реальные а не примерные


  1. mister_xen
    18.12.2024 20:30

    "

    Итоги и выводы

    Этот проект показал, как можно собрать мощное и масштабируемое приложение

    "

    ну нет. не показал.

    "Итоги и выводы"

    ну мы рады за вас


  1. Serj8355
    18.12.2024 20:30

    Пфф, и кому нужна этА липа?) с такого же сайта


  1. alpha_man
    18.12.2024 20:30

    Ваш преподаватель определено вас похвалит за эту статью.

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