Опишите ваш последний или наиболее значимый проект.

Ответ

Последний значимый проект – разработка высоконагруженного REST API для финтех-сервиса.

Стек: Java 11, Spring Boot, Hibernate, PostgreSQL, Redis, Docker.

Основные задачи и оптимизации:

  1. Оптимизация работы с БД: Решил проблему N+1 в JPA, использовал @EntityGraph и проекции DTO.
  2. Внедрение кэширования: Добавил двухуровневое кэширование ответов API для часто запрашиваемых данных.
  3. Асинхронная обработка: Вынес фоновые задачи (логирование, нотификации) с помощью @Async и ThreadPoolTaskExecutor.

Пример реализации кэширования с Spring Cache:

@Service
public class UserServiceImpl implements UserService {
    @Override
    @Cacheable(value = "users", key = "#id", unless = "#result == null")
    public UserDto getById(Long id) {
        // Запрос выполняется только при промахе кэша
        return userRepository.findProjectedById(id);
    }
}

Архитектурные изменения: Участвовал в миграции с монолита на микросервисную архитектуру. Мы выделили три независимых сервиса (пользователи, платежи, отчеты), которые обменивались событиями через Apache Kafka, что повысило отказоустойчивость и масштабируемость системы.

Ответ 18+ 🔞

Да что ж такое-то, блядь! Ну вот сидишь, значит, пишешь свой код, думаешь — всё, красава, всё летает. А потом приходит этот, бизнес, и такой: «А давайте сделаем финтех, но чтобы выдерживало, блядь, овердохуища запросов в секунду!». Ну, пиздец, началось.

Короче, последняя моя эпопея — это высоконагруженное REST API для этих, финтеховских ребят. С деньгами, сука, шутки плохи, там всё должно работать, как часы, а иначе — волнение ебать, терпения ноль ебать у клиентов.

Чем ковырялся: Java 11, Spring Boot, Hibernate, PostgreSQL, Redis, Docker. Стандартный такой, блядь, набор для того, чтобы с ума сойти.

И что я там наворотил, спросишь? А вот что:

  1. С БД пришлось повоевать. Hibernate, он же, сука, такой умный — начнёт тебе по одному юзеру вытаскивать, а у него там связи, ленивые коллекции... Классический N+1, ёпта! Я сначала офигел — откуда такие тормоза? Потом врубил @EntityGraph, проекции DTO начал использовать — чтобы тащил из базы только то, что надо, а не всю ебучую объектную модель. Сразу полегчало, блядь.

  2. Кэширование — наше всё. Без этого нихуя. Сделал двухуровневое: часто запрашиваемые данные, типа курсов валют или справочников, — сразу в Redis летят. Чтоб базу лишний раз не ебашить. Spring Cache, блядь, рулит.

  3. Всё, что можно — в фон. Пользователь платёж сделал — и хуй с ним, пусть идёт. А вот логировать операцию, письмо отправить, смс — это всё в отдельные потоки через @Async. ThreadPoolTaskExecutor настроил, чтобы эти фоновые задачи не забили всё нахуй. Главное — успеть впердолить ответ клиенту, а остальное — как-нибудь потом.

Вот, смотри, как кэш впилил, красиво же:

@Service
public class UserServiceImpl implements UserService {
    @Override
    @Cacheable(value = "users", key = "#id", unless = "#result == null")
    public UserDto getById(Long id) {
        // Запрос выполняется только при промахе кэша
        return userRepository.findProjectedById(id);
    }
}

Красота, да? Запрос в базу — только если в кэше пусто. А так — чирик, и данные на руках.

А самое, блядь, интересное — это архитектура. Мы же начинали с монолита, здоровенного такого. А потом поняли — пидарас шерстяной, так жить нельзя! Один сервис упадёт — и всё, накрылся медным тазом весь наш финтех.

Начали пилить на микросервисы. Выделили три штуки: пользователи, платежи, отчеты. И чтобы они между собой общались не напрямую, а через события в Apache Kafka. Получилось, блядь, элегантно: один сервис сделал своё дело — бросил событие в кафку и забыл. А кто надо — тот подхватит. Масштабируемость выросла, отказоустойчивость — просто удивление пиздец. Теперь если сервис отчётов сдохнет, то платежи-то всё равно работают! Во какие распиздяйства, блядь, но правильные.