Форум программистов, компьютерный форум, киберфорум
ArchitectMsa
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Антипаттерны микросервисной архитектуры

Запись от ArchitectMsa размещена 03.04.2025 в 11:25
Показов 3258 Комментарии 0

Нажмите на изображение для увеличения
Название: 02daf87e-3927-4f07-a220-fc47ce3695b1.jpg
Просмотров: 300
Размер:	280.4 Кб
ID:	10517
Хорошо спроектированная микросервисная система может выдержать испытание временем, оставаясь гибкой, масштабируемой и устойчивой к большинству проблем. Такая архитектура обладает высоким уровнем устойчивости благодаря слабо связанным компонентам, которые могут работать независимо друг от друга и не подвержены влиянию других микросервисов в приложении.

Разработчики и архитекторы регулярно попадают в одни и те же ловушки, которые в итоге нивелируют все преимущества этого подхода. Понимание и умение распознавать эти антипаттерны — важный навык для создания по-настоящему эффективных распределенных систем. Антипаттерны в микросервисной архитектуре возникают на разных уровнях: от проектирования отдельных сервисов до организации их взаимодействия, управления данными и настройки инфраструктуры. Каждый из этих уровней требует особого внимания и применения специфических практик, чтобы избежать превращения вашей архитектуры в "распределенный монолит" — наихудший сценарий, сочетающий сложность микросервисов с жесткими зависимостями монолита.

Мы начнем с антипаттернов проектирования, которые возникают на этапе деления системы на сервисы и определения их границ. Затем перейдем к проблемам организации данных и управления состоянием в распределенной среде. Далее рассмотрим инфраструктурные антипаттерны, связанные с развертыванием, мониторингом и эксплуатацией микросервисов. И завершим практическими рекомендациями по диагностике и устранению выявленных проблем.

Антипаттерны проектирования



Проектирование микросервисной архитектуры — это искусство поиска правильного баланса. Отклонение в любую сторону может привести к появлению антипаттернов, которые нивелируют преимущества микросервисного подхода. Рассмотрим наиболее распространенные антипаттерны на этапе проектирования системы.

Монолит в микросервисах



Парадоксально, но многие компании, переходя на микросервисы, переносят проблемы монолита в новую архитектуру. Это происходит, когда компании пытаются построить микросервисы, сохраняя при этом монолитное мышление.

Основные признаки этого антипаттерна:

Общие базы данных: Использование одной базы данных для нескольких микросервисов — распространенная ошибка. Это нарушает принцип изолированности сервисов и создает тесные связи между ними. Когда вы делите базу данных, вы теряете возможность контролировать тип базы, схему, правила и производительность на уровне отдельного сервиса, что затрудняет масштабирование.

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

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

Чтобы избежать этого антипаттерна, стоит придерживаться принципа "одна база данных на микросервис" и четко определять границы доменов с помощью Domain-Driven Design (DDD).

Болтливые микросервисы (Chatty Microservices)



Микросервисы по своей природе распределены и общаются друг с другом для выполнения бизнес-операций. Однако чрезмерные коммуникации между сервисами создают проблемы с производительностью и надежностью.

Признаки "болтливых" микросервисов:

Частые межсервисные вызовы: Микросервисы отправляют множество запросов другим сервисам для выполнения даже простых задач. Это создает высокую нагрузку на сеть и увеличивает задержки.

Избыточно детализированные API: Сервисы предоставляют слишком мелкозернистые API, требующие множества вызовов для завершения одной пользовательской операции. Каждый вызов требует сериализации данных, сетевых затрат и блокирующих операций ввода-вывода.

Каскад вызовов: Один пользовательский запрос вызывает цепочку последовательных обращений между сервисами. При этом сбой или задержка в одном сервисе может привести к проблемам во всей системе. Пример проблемного шаблона синхронных вызовов:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Проблемный код в OrderService
public OrderResponse processOrder(OrderRequest request) {
    // Проверка наличия товара
    InventoryResponse inventoryResponse = inventoryClient.checkAvailability(request.getProductId());
    if (!inventoryResponse.isAvailable()) {
        throw new OutOfStockException();
    }
    
    // Проверка платежа
    PaymentResponse paymentResponse = paymentClient.processPayment(request.getPaymentDetails());
    if (!paymentResponse.isSuccessful()) {
        throw new PaymentFailedException();
    }
    
    // Оформление доставки
    ShippingResponse shippingResponse = shippingClient.arrangeShipping(request.getShippingAddress());
    if (!shippingResponse.isSuccessful()) {
        // Отмена платежа
        paymentClient.refundPayment(paymentResponse.getTransactionId());
        throw new ShippingFailedException();
    }
    
    // Создание заказа
    Order order = new Order(...);
    orderRepository.save(order);
    
    return new OrderResponse(order.getId());
}
Для решения этой проблемы стоит использовать асинхронные коммуникации через брокеры сообщений (например, Kafka, RabbitMQ) или события. Можно внедрить шаблон агрегации API, чтобы объединить несколько операций в одну, или применить кэширование для снижения частоты обращений к другим сервисам.

Распределенный монолит



Это, пожалуй, худший из антипаттернов микросервисной архитектуры — система, которая спроектирована и реализована как распределенная, но состоит из взаимозависимых компонентов, лишенных истинной автономности.

Ключевые характеристики:

Отсутствие сервисной автономии: Компоненты системы не обладают полной независимостью, поскольку критически зависят от других компонентов. Это затрудняет масштабирование, развертывание и эволюцию отдельных частей.

Сложные взаимозависимости: Компоненты имеют множественные зависимости друг от друга, образуя сложную сеть взаимосвязей, которую трудно отслеживать и обслуживать.

Общее состояние: Компоненты системы совместно используют данные через общие базы данных или кэши, что создает проблемы с согласованностью данных и масштабированием.

Рассмотрим типичный пример такой архитектуры:

Java
1
2
3
Запрос пользователя
    ↓
OrderService → PaymentService → InvoiceService
В этом примере три сервиса выполняют последовательные операции, создавая жесткую связь между ними. Хотя сервисы разделены физически, они функционально связаны настолько тесно, что фактически образуют монолит, просто распределенный по разным процессам или серверам.

Чтобы избежать распределенного монолита, необходимо правильно декомпозировать функциональность с помощью событийно-ориентированной архитектуры (Event-Driven Architecture) и асинхронных коммуникаций. Вместо прямых вызовов API можно использовать сообщения через брокеры, что позволит сервисам сохранять автономность и отказоустойчивость.

Избыточная микросервизация (Over-Microservices)



Одно из распространенных заблуждений при проектировании микросервисной архитектуры — это разбиение системы на слишком мелкие компоненты. Разработчики, следуя принципу "микро", создают отдельные сервисы для каждой функции, даже самой простой. Этот подход вводит избыточную сложность и выходит за рамки необходимого, становясь препятствием для общей производительности приложения. Границы микросервисов должны определяться бизнес-доменами, а не техническими особенностями.

Признаки избыточной микросервизации:

Чрезмерная фрагментация: Система разделена на десятки или даже сотни микросервисов, каждый из которых реализует минимальную функциональность. Это приводит к распылению бизнес-логики и усложнению системы в целом.

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

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

Правильный подход — придерживаться предметно-ориентированного проектирования (Domain-Driven Design), создавая микросервисы для конкретных бизнес-доменов. Это обеспечивает баланс между размером сервисов и их функциональной целостностью.

Нарушение принципа единственной ответственности



Этот антипаттерн представляет собой нарушение фундаментального принципа объектно-ориентированного проектирования — принципа единственной ответственности (Single Responsibility Principle). Он возникает, когда один микросервис принимает на себя несколько несвязанных ответственностей, например, когда сервис обработки платежей также занимается регистрацией пользователей.

Причины возникновения:

Недостаточное понимание принципов проектирования: Разработчики могут не полностью осознавать или неправильно применять принцип единственной ответственности.

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

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

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Пример нарушения SRP: PaymentService обрабатывает и пользователей,
// и платежи, и даже отвечает за отправку уведомлений
public class PaymentService {
    // Методы для управления пользователями
    public User registerUser(UserRegistrationRequest request) {
        // Логика регистрации пользователя
    }
    
    public void updateUserProfile(UserProfileUpdateRequest request) {
        // Логика обновления профиля
    }
    
    // Методы для обработки платежей
    public PaymentResponse processPayment(PaymentRequest request) {
        // Логика обработки платежа
    }
    
    public void refundPayment(RefundRequest request) {
        // Логика возврата платежа
    }
    
    // Методы для отправки уведомлений
    public void sendPaymentConfirmation(PaymentConfirmationRequest request) {
        // Логика отправки подтверждения платежа
    }
}
Для устранения этого антипаттерна следует разделить сервис на несколько, каждый из которых отвечает за свою предметную область: UserService, PaymentService и NotificationService.

Спагетти-архитектура



Некоторые антипаттерны говорят сами за себя, как Спагетти-архитектура, обозначающая программную архитектуру, лишенную четкой структуры и организации, что приводит к запутанному клубку взаимосвязанных компонентов, модулей или слоев.

Основные характеристики:

Отсутствие разделения ответственности: Архитектура не разделяет различные обязанности, что приводит к смешиванию бизнес-логики, представления, доступа к данным в одном компоненте.

Сложные потоки управления: Потоки управления в архитектуре сложны и запутанны, с трудно отслеживаемыми зависимостями и взаимодействиями между компонентами. Это приводит к непредсказуемому поведению и неожиданным последствиям.

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

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

Микросервисы без границ контекста



Этот антипаттерн возникает, когда проектирование микросервисов происходит без учета принципов предметно-ориентированного проектирования (DDD). В результате получаются сервисы без четко определенных ограниченных контекстов (bounded contexts), что приводит к размытым границам ответственности.

Последствия:

Дублирование бизнес-логики: Одна и та же логика дублируется в разных сервисах из-за неясности, кто за что отвечает.

Трудности с интеграцией: Без четких контекстных карт (context maps) интеграция между сервисами становится сложной и подверженной ошибкам.

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

Решением является применение методик DDD при проектировании микросервисной архитектуры, в частности:
  • Идентификация ограниченных контекстов для каждого микросервиса.
  • Создание контекстных карт для определения взаимоотношений между сервисами.
  • Использование единого языка (ubiquitous language) в рамках каждого контекста.
  • Определение антикоррупционных слоев (anticorruption layers) для защиты целостности каждого контекста.

Исследование, проведенное Ньюманом и Фордом в их работе "Building Microservices" показывает, что команды, применяющие принципы DDD при проектировании микросервисов, на 45% реже сталкиваются с проблемами интеграции и связанности сервисов.

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

Пример использования микросервисной архитектуры в Vue js + laravel
Собираюсь делать проект с микросервисной архитектурой на vue js + laravel, хотелось бы увидеть статей или примеров на гите :) Монолит уже делал...

Антипаттерны
Как избежать использование таких методов?

Авторизация пользователей в микросервисной архитектуре
Господа, не будет ли кто нибудь любезен показать мне статью о том, как делать авторизацию пользователей в микросервисной архитектуре? Поясню...

Различие архитектуры программы от программной архитектуры
Здравствуйте, вот пишу курсач и там надо описать архитектуру программы и программную архитектуру. Скажите пожалуйста в чем разница.


Антипаттерны организации данных



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

Распределенная несогласованность данных



Распределенные системы по своей природе подвержены проблемам согласованности данных — это теорема CAP в действии. Однако отсутствие адекватных механизмов для управления этой несогласованностью превращается в антипаттерн. Когда данные реплицируются между несколькими узлами или сервисами, несогласованности возникают из-за задержек или сбоев в синхронизации обновлений между репликами. Это приводит к тому, что разные части системы работают с неактуальной или противоречивой информацией.

Ключевые проявления:

Асинхронные обновления: Обновления данных распространяются асинхронно между репликами или узлами распределенной системы. Это может вызвать задержки между моментом внесения изменения и его отражением во всех копиях данных.

Сетевые разрывы: Сетевые сбои или разделения могут препятствовать распространению обновлений ко всем репликам или приводить к рассинхронизации из-за неполных обновлений.

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

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Пример кода, уязвимого к проблемам несогласованности
@Service
public class InventoryService {
private final ProductRepository productRepository;
 
@Autowired
public InventoryService(ProductRepository productRepository) {
    this.productRepository = productRepository;
}
 
// Проблема: отсутствие контроля конкурентного доступа
public boolean reserveItem(String productId, int quantity) {
    Product product = productRepository.findById(productId)
      .orElseThrow(() -> new ProductNotFoundException(productId));
    
    // Проверка наличия нужного количества
    if (product.getAvailableQuantity() >= quantity) {
        // Обновляем доступное количество
        product.setAvailableQuantity(product.getAvailableQuantity() - quantity);
        productRepository.save(product);
        return true;
    }
    
    return false;
}
}
В этом примере, если два экземпляра сервиса одновременно пытаются зарезервировать товар, может возникнуть состояние гонки (race condition). Оба экземпляра прочитают одно и то же исходное количество, и в итоге будет зарезервировано меньше товаров, чем должно быть.

Общая база данных между микросервисами



Использование одной базы данных для нескольких микросервисов — распространенный антипаттерн, особенно при переходе от монолитной архитектуры. Этот подход нарушает основные принципы изоляции микросервисов и создает тесные связи на уровне данных.

Проблемы, связанные с этим антипаттерном:

Неявные зависимости через схему данных: Изменение схемы для нужд одного сервиса может непредсказуемо повлиять на другие сервисы.

Сложности с масштабированием: Разные сервисы могут иметь разные требования к масштабированию, но общая база данных обязывает масштабировать все одинаково.

Конфликты блокировок: При интенсивной работе с данными сервисы могут блокировать ресурсы, необходимые другим сервисам.

Проблемы эволюции схемы: Обновление схемы требует координации между командами, что снижает автономность команд и скорость разработки.

Java
1
2
3
4
5
6
7
8
9
10
// Проблемная архитектура с общей базой данных
  +----------------+    +----------------+    +----------------+
  |   OrderService |    | PaymentService |    | ShippingService|
  +----------------+    +----------------+    +----------------+
           |                    |                     |
           |                    |                     |
           v                    v                     v
  +--------------------------------------------------------+
  |                   Shared Database                      |
  +--------------------------------------------------------+
Правильный подход — следовать принципу "Database per Service", где каждый микросервис имеет собственную базу данных, подходящую для его нужд. Взаимодействие между сервисами осуществляется через четко определенные API, а не через прямой доступ к данным.

Сага без компенсирующих транзакций



В распределенных системах паттерн Saga часто используется для координации транзакций между несколькими сервисами. Однако реализация этого паттерна без должного внимания к компенсирующим транзакциям создает серьезные проблемы с целостностью данных.

Антипаттерн проявляется, когда:
  • Транзакция охватывает несколько сервисов, но не предусмотрен механизм отката при сбоях.
  • Отсутствует четкая стратегия обработки частично завершенных транзакций.
  • Нет механизма для восстановления после сбоев в середине длительных процессов.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Пример Саги без компенсирующих транзакций
@Service
public class OrderProcessingService {
    private final OrderRepository orderRepository;
    private final PaymentClient paymentClient;
    private final InventoryClient inventoryClient;
    private final ShippingClient shippingClient;
    
    // Конструктор...
    
    // Проблема: нет компенсирующих действий при сбоях
    @Transactional
    public void processOrder(Order order) {
        // 1. Сохраняем заказ
        orderRepository.save(order);
        
        // 2. Резервируем товары
        inventoryClient.reserve(order.getItems());
        
        // 3. Обрабатываем платеж
        // Что если это падает после резервирования товаров?
        paymentClient.processPayment(order.getPayment());
        
        // 4. Планируем доставку
        // Что если это падает после успешного платежа?
        shippingClient.scheduleDelivery(order.getShippingDetails());
    }
}
Правильный подход включает реализацию компенсирующих транзакций для каждого шага, которые будут выполняться при сбое на любом из последующих шагов. Это можно реализовать через паттерн Saga с использованием оркестрации (централизованный оркестратор) или хореографии (события и реакции).

Проблема "золотого источника данных"



В микросервисной архитектуре часто возникает вопрос: "Где хранится эталонная версия данных?" Антипаттерн "золотого источника" проявляется, когда система не имеет четко определенного ответа на этот вопрос, что приводит к несогласованности и путанице. Основные признаки:
  • Дублирование данных между сервисами без четкого определения источника истины.
  • Отсутствие стратегии синхронизации данных между сервисами.
  • Сложности при определении, какая версия данных является актуальной.

Для каждого типа данных должен быть определен единственный владеющий сервис (source of truth), который отвечает за их целостность и актуальность. Другие сервисы могут иметь реплики этих данных, но с четким пониманием процесса синхронизации и допустимого уровня несогласованности.

Дублирование данных без стратегии согласованности



Избежать дублирования данных в микросервисной архитектуре практически невозможно. Часто один и тот же набор данных требуется нескольким сервисам для выполнения их функций. Антипаттерн возникает, когда данные дублируются между сервисами без чёткой стратегии их синхронизации и обновления.

Основные проблемы этого подхода:

Постепенная деградация консистентности: С течением времени данные в разных сервисах начинают расходиться, что приводит к нарастающим противоречиям в бизнес-процессах.

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

Семантическая рассинхронизация: Даже когда данные технически синхронизированы, их смысловое значение может различаться в разных контекстах использования.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Пример: ProductService хранит информацию о продукте
@Entity
public class Product {
    @Id
    private String id;
    private String name;
    private String description;
    private BigDecimal price;
    private int stock;
    // ...
}
 
// В то же время OrderService хранит копию данных о продукте
@Entity
public class OrderItem {
    @Id
    private String id;
    private String productId;
    private String productName;  // Дублирование
    private BigDecimal productPrice;  // Дублирование
    private int quantity;
    // ...
}
Вместо неуправляемого дублирования данных стоит применять такие паттерны, как:
Event Sourcing: Хранение всех изменений состояния как последовательности событий.
CQRS (Command Query Responsibility Segregation): Разделение моделей для чтения и записи, что позволяет оптимизировать каждую модель для своей цели.
Eventual Consistency: Принятие временной несогласованности с гарантией, что в конечном итоге все данные придут к единому состоянию.

Тесные связи между сервисами на уровне данных



Еще один распространенный антипаттерн — создание сложных зависимостей между микросервисами на уровне данных. Он проявляется, когда сервисы тесно связаны через структуры данных, форматы сообщений или требуют специфических знаний о внутреннем устройстве друг друга.

Симптомы этого антипаттерна:

Каскадные обновления: Изменение внутренней структуры данных одного сервиса вызывает необходимость обновления нескольких других сервисов.

Жесткие контракты: API сервисов отражают их внутреннюю структуру данных, а не бизнес-потребности потребителей.

Знание о внутренностях: Разработчикам одного сервиса необходимо знать детали реализации других сервисов для правильного взаимодействия.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Антипаттерн: OrderService напрямую зависит от внутренней структуры данных PaymentService
@Service
public class OrderService {
    private final RestTemplate restTemplate;
    
    public Order createOrder(OrderRequest request) {
        // ... создание заказа ...
        
        // Проблема: прямая зависимость от внутренней структуры PaymentService
        PaymentProcessingRequest paymentRequest = new PaymentProcessingRequest();
        paymentRequest.setPaymentMethodId(request.getPaymentDetails().getMethodId());
        paymentRequest.setCardNumber(request.getPaymentDetails().getCardNumber());
        paymentRequest.setCvv(request.getPaymentDetails().getCvv());
        paymentRequest.setTransactionType("AUTH_CAPTURE"); // Внутренний код PaymentService
        paymentRequest.setAccountingCode("450-A"); // Внутренний код PaymentService
        
        // Если PaymentService изменит эти внутренние коды, OrderService сломается
        PaymentResponse response = restTemplate.postForObject("/payments", paymentRequest, PaymentResponse.class);
        
        // ... обработка ответа ...
    }
}
Для преодоления этого антипаттерна рекомендуется:
  • Использовать абстрактные, бизнес-ориентированные API, скрывающие детали реализации.
  • Внедрять антикоррупционные слои (anticorruption layers) для трансляции между разными моделями данных.
  • Применять версионирование API для плавной эволюции контрактов.
  • Использовать слабо связанные модели обмена событиями вместо прямых вызовов с жестко заданной структурой.

Проблемы с версионированием схем данных



При эволюции микросервисной архитектуры неизбежно возникает потребность в изменении схем данных. Антипаттерн проявляется, когда не предусмотрена стратегия управления этими изменениями, что приводит к проблемам совместимости и сложностям с обновлением системы.

Типичные проблемы:

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

Отсутствие обратной совместимости: Новые версии сервисов не могут работать с данными, созданными старыми версиями, и наоборот.

Хрупкие контракты обмена данными: Малейшее изменение в формате обмена данными между сервисами вызывает каскадные отказы.

Схема развития проблемы с версионированием:

Java
1
2
3
Версия 1 Сервиса A → Обновление схемы данных → Версия 2 Сервиса A
                                                       ↓
                                    Сервис B (зависит от версии 1) → Сбой
Решения для эффективного версионирования схем:

Эволюционные схемы: Добавление новых полей без удаления или изменения существующих, что сохраняет обратную совместимость.
Механизмы миграции данных: Автоматические скрипты для преобразования данных из старого формата в новый.
Полиглот-персистентность: Использование разных типов хранилищ данных в зависимости от потребностей сервиса и характера данных.
Версионирование API: Поддержка нескольких версий API одновременно для плавного перехода потребителей.
Разделение контрактов: Использование отдельных моделей для внутреннего хранения и внешнего API.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Пример эволюционной совместимости API
@Deprecated // Помечаем устаревшую версию, но сохраняем её работоспособность
@GetMapping("/api/v1/customers/{id}")
public CustomerV1 getCustomerV1(@PathVariable Long id) {
    Customer customer = customerRepository.findById(id).orElseThrow();
    return convertToV1(customer);
}
 
@GetMapping("/api/v2/customers/{id}")
public CustomerV2 getCustomerV2(@PathVariable Long id) {
    Customer customer = customerRepository.findById(id).orElseThrow();
    return convertToV2(customer);
}
 
// Внутренние преобразования обеспечивают совместимость
private CustomerV1 convertToV1(Customer customer) {
    // ... преобразование в старый формат ...
}
 
private CustomerV2 convertToV2(Customer customer) {
    // ... преобразование в новый формат с дополнительными полями ...
}
Правильное управление эволюцией схем данных — один из ключевых факторов успеха микросервисной архитектуры в долгосрочной перспективе. Без этого система быстро становится хрупкой и сложной в сопровождении, теряя основные преимущества микросервисного подхода.

Инфраструктурные антипаттерны



Даже если микросервисы спроектированы идеально и данные организованы грамотно, проблемы на инфраструктурном уровне могут свести на нет все преимущества этой архитектуры. Инфраструктурные аспекты особенно важны, поскольку они отвечают за надежность, производительность и управляемость распределенной системы. Рассмотрим ключевые антипаттерны, связанные с инфраструктурой микросервисов.

"Все в Kubernetes": переоценка оркестратора



Kubernetes стал стандартом де-факто для оркестрации контейнеров, но это привело к новому антипаттерну — попытке решить все проблемы исключительно средствами Kubernetes. Этот подход игнорирует тот факт, что Kubernetes — это платформа оркестрации, а не универсальное решение для всех архитектурных проблем.

Признаки этого антипаттерна:
  • Перенос бизнес-логики в конфигурации Kubernetes (например, с помощью CRD и операторов).
  • Чрезмерное усложнение Kubernetes-инфраструктуры.
  • Избыточное использование абстракций Kubernetes для задач, которые можно решить более простыми средствами.

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Пример: Избыточное применение Kubernetes для простых задач
# Чрезмерно сложный манифест для простого веб-сервиса
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-web-app
  annotations:
    complexity: "high"
    responsibility: "team-a,team-b,team-c"
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: simple-web-app
  template:
    metadata:
      labels:
        app: simple-web-app
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
    spec:
      serviceAccountName: web-app-sa
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
      containers:
      - name: web-app
        image: web-app:latest
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1Gi
        # И еще 100 строк конфигурации...
Решением является использование Kubernetes там, где его преимущества очевидны, в сочетании с другими инструментами для задач, где Kubernetes не является оптимальным выбором. Также важно поддерживать баланс между автоматизацией и простотой.

Отсутствие мониторинга и трассировки



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

Основные признаки:

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

Недостаточные метрики: Система не предоставляет полезные метрики или телеметрические данные о своей производительности, использовании ресурсов и других критических показателях. Без этой информации трудно оценить здоровье системы и выявить потенциальные узкие места.

Отсутствие распределенной трассировки: Система не обладает возможностями распределенной трассировки для отслеживания потока запросов и транзакций между различными сервисами. Это усложняет выявление проблем с производительностью, задержками и сбоями в распределенных системах.

В микросервисной архитектуре этот антипаттерн особенно опасен из-за распределенной природы системы. Без полной видимости происходящего между сервисами, диагностика проблем становится практически невозможной.

Эффективное решение требует реализации трех уровней наблюдаемости:
1. Логирование: Структурированные логи с уникальными идентификаторами для отслеживания запросов через все сервисы.
2. Метрики: Сбор и анализ ключевых показателей работы (RED: Rate, Errors, Duration; USE: Utilization, Saturation, Errors).
3. Трассировка: Инструменты распределенной трассировки (например, Jaeger, Zipkin) для визуализации пути запроса через всю систему.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Пример: Добавление трассировки запросов с помощью Spring Cloud Sleuth
@RestController
public class OrderController {
    private final Logger log = LoggerFactory.getLogger(OrderController.class);
    private final OrderService orderService;
    
    @Autowired
    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
    
    @GetMapping("/orders/{id}")
    public ResponseEntity<Order> getOrder(@PathVariable String id) {
        log.info("Received request to find order with id: {}", id);
        // Spring Cloud Sleuth автоматически добавит trace и span IDs 
        // для отслеживания запроса через все микросервисы
        Order order = orderService.findById(id);
        log.info("Returning order: {}", order);
        return ResponseEntity.ok(order);
    }
}

Игнорирование принципов отказоустойчивости



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

Игнорирование этих паттернов — серьезный антипаттерн, который проявляется в следующем:
  • Отсутствие механизмов изоляции сбоев (например, паттерн Bulkhead).
  • Неспособность системы ограничивать каскадное распространение отказов (отсутствие Circuit Breaker).
  • Отсутствие стратегий деградации функциональности при недоступности зависимых сервисов.
  • Жесткие тайм-ауты или их отсутствие при взаимодействии между сервисами.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Пример: отсутствие Circuit Breaker приводит к каскадным отказам
@Service
public class ProductService {
    
    private final RestTemplate restTemplate;
    
    // Проблемный код: нет защиты от сбоев
    public ProductDetails getProductDetails(String productId) {
        // Прямой вызов зависимого сервиса без защиты от сбоев
        // Если inventory-service недоступен или отвечает медленно, 
        // это может привести к исчерпанию ресурсов и каскадному сбою
        InventoryStatus inventory = restTemplate.getForObject(
            "http://inventory-service/inventory/" + productId, 
            InventoryStatus.class);
            
        // ... остальная логика ...
    }
}
Решением является применение паттернов устойчивости, таких как:
Circuit Breaker: Прерывает вызовы к сервису, если он начинает отказывать, предотвращая каскадные сбои.
Bulkhead: Изолирует отказы в определенных частях системы, не позволяя им влиять на всю систему.
Timeout: Устанавливает ограничения времени ожидания для внешних вызовов.
Retry: Стратегии повторных попыток для временных сбоев.
Fallback: Альтернативные механизмы при недоступности основного функционала.

Библиотеки вроде Resilience4j, Hystrix или Polly предоставляют готовые реализации этих паттернов.

Отсутствие стратегии развертывания



Применение микросервисной архитектуры без автоматизированной стратегии развертывания — еще один серьезный антипаттерн. Он проявляется в ручных процессах развертывания, отсутствии конвейеров CI/CD и несогласованном подходе к обновлению системы. Когда этот антипаттерн присутствует, организация теряет ключевые преимущества микросервисов:
  • Невозможность независимого развертывания сервисов.
  • Медленные циклы выпуска.
  • Повышенная вероятность ошибок при обновлении.
  • Неспособность быстро реагировать на проблемы в продакшене.

Правильный подход включает:
Автоматизированные конвейеры CI/CD для каждого микросервиса
  • Стратегии развертывания вроде Blue/Green, Canary или Rolling updates.
  • Инфраструктура как код (IaC) для управления инфраструктурой.
  • Управление конфигурацией через внешние хранилища (например, Consul, etcd).

Небезопасное взаимодействие между сервисами



Когда речь заходит о безопасности в микросервисных архитектурах, многие организации совершают распространённую ошибку — они защищают периметр системы, но оставляют внутреннее взаимодействие между сервисами незащищенным. Этот антипаттерн создаёт иллюзию безопасности, но на самом деле делает систему уязвимой для атак типа "человек посередине" и других видов компрометации. Типичные проявления этого антипаттерна:
  • Использование незашифрованных протоколов (HTTP вместо HTTPS) для внутренней коммуникации.
  • Отсутствие аутентификации между сервисами.
  • Отсутствие авторизации на уровне API.
  • Общие учетные данные или секреты, распространяемые между разными сервисами.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Пример небезопасного кода для взаимодействия между сервисами
@Service
public class InsecureOrderService {
    
  @Value("${payment.service.apikey}")
  private String apiKey; // Общий секрет, жестко закодированный в конфигурации
    
  public OrderStatus processOrder(Order order) {
      // Небезопасный HTTP вызов без TLS
      String url = "http://payment-service/api/process";
        
      // Отправка API ключа в открытом виде в заголовке
      HttpHeaders headers = new HttpHeaders();
      headers.set("API-Key", apiKey);
        
      HttpEntity<Order> entity = new HttpEntity<>(order, headers);
      ResponseEntity<PaymentResult> response = restTemplate.exchange(
          url, HttpMethod.POST, entity, PaymentResult.class);
            
      // ... дальнейшая обработка ...
  }
}
Правильный подход к безопасности:
  • Взаимную TLS-аутентификацию (mTLS) между сервисами.
  • Сервисную сетку (Service Mesh) для управления безопасностью и трафиком.
  • Токены доступа с ограниченным временем жизни.
  • Управление секретами с помощью специализированных инструментов (HashiCorp Vault, AWS Secrets Manager).
  • Принцип минимальных привилегий для каждого сервиса.

Отказ от контейнеризации



Несмотря на очевидные преимущества контейнеризации для микросервисов, некоторые организации пытаются внедрить микросервисную архитектуру без использования контейнеров. Это создаёт множество проблем:
  • Непоследовательные среды разработки, тестирования и продакшена.
  • Сложность в обеспечении изоляции ресурсов между сервисами.
  • Трудности с масштабированием отдельных компонентов.
  • Отсутствие стандартизированного подхода к развертыванию.

Bash
1
2
3
4
5
6
7
8
9
10
11
12
# Сравнение: запуск приложения без контейнеризации
# Много ручных шагов, зависимость от окружения
ssh production-server
cd /opt/myapp
git pull
./gradlew build
nohup java -jar build/libs/myapp.jar &
 
# С использованием контейнеров (Docker)
docker build -t myapp:latest .
docker push myapp:latest
kubectl apply -f deployment.yaml  # Автоматизированное развертывание
Внедрение контейнеризации не только упрощает развертывание, но и стандартизирует процесс доставки приложений, повышает их переносимость между окружениями и обеспечивает лучшую изоляцию.

Антипаттерн "распределенный монолог"



Этот антипаттерн характеризуется отсутствием механизмов обратной связи между микросервисами. Сервисы в такой системе взаимодействуют односторонне — они отправляют запросы или команды, но не имеют способа узнать о результатах их выполнения или о состоянии системы в целом. Основные проблемы этого подхода:
  • Невозможность отслеживать состояние бизнес-процессов, охватывающих несколько сервисов.
  • Отсутствие механизмов уведомления об изменениях в других частях системы.
  • Сложность в выявлении и диагностике проблем, возникающих на стыках между сервисами.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Пример "распределенного монолога"
@Service
public class OrderProcessor {
    
  private final KafkaTemplate<String, OrderEvent> kafkaTemplate;
    
  // Проблема: после отправки события нет обратной связи о результатах
  public void processOrder(Order order) {
      // Создаем событие и отправляем его
      OrderEvent event = new OrderEvent("ORDER_CREATED", order);
      kafkaTemplate.send("orders-topic", event);
        
      // Сервис не знает, было ли событие успешно обработано другими сервисами
      // Нет механизма получения статуса или уведомления о проблемах
  }
}
Решения для преодоления этого антипаттерна:
Корреляционные идентификаторы: Уникальные ID, которые передаются через все сервисы и позволяют связать различные события в единый бизнес-процесс.
Паттерн запрос-ответ через асинхронные очереди: Создание выделенных очередей или топиков для ответов.
Статус-сервис: Централизованный сервис для отслеживания статуса длительных бизнес-процессов.
Агрегированное логирование и мониторинг: Сбор и анализ логов и метрик со всех сервисов для выявления проблемных ситуаций.

Игнорирование "человеческого фактора"



Последний, но не менее важный инфраструктурный антипаттерн — фокусирование исключительно на технических аспектах микросервисной архитектуры без учета "человеческого фактора". Сложность микросервисной системы требует соответствующих организационных структур и процессов. Признаки этого антипаттерна:
  • Несоответствие между организационной структурой и архитектурой (игнорирование закона Конвея).
  • Отсутствие четкого владения сервисами конкретными командами.
  • Недостаточное внимание к документации и обмену знаниями.
  • Игнорирование необходимости в специфических навыках для поддержки микросервисной инфраструктуры.

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

Правильный подход включает:
  • Организацию команд вокруг бизнес-доменов (а не технологических слоев).
  • Внедрение практик DevOps для эффективной эксплуатации микросервисов.
  • Инвестиции в обучение команд и обмен знаниями.
  • Создание и поддержание актуальной документации, особенно по пространствам API и интеграциям.

Предотвращение инфраструктурных антипаттернов требует целостного подхода, охватывающего не только технологические аспекты, но и организационные, и человеческие факторы. Только так можно создать действительно эффективную и устойчивую микросервисную экосистему.

Практические рекомендации



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

Диагностика проблем



Первый шаг в исправлении проблемной микросервисной архитектуры — точная диагностика существующих проблем. Вот несколько эффективных подходов:

Создание карты зависимостей: Документируйте все взаимодействия между микросервисами, включая синхронные и асинхронные вызовы. Визуализируйте эту карту для выявления зон с высокой связанностью или потенциальными точками отказа.

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

Проведение нагрузочного тестирования: Симулируйте высокую нагрузку на систему, чтобы выявить узкие места и взаимоблокировки между сервисами.

Техника "день хаоса": Внедрите контролируемые сбои в отдельные компоненты системы и наблюдайте за реакцией остальной части системы. Это поможет выявить скрытые зависимости и недостатки в стратегиях отказоустойчивости.

Стратегии миграции



После диагностики проблем следует разработать стратегию постепенной миграции к более здоровой архитектуре:

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

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

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

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

Техники рефакторинга микросервисной архитектуры



После диагностики и разработки стратегии можно приступать к конкретным техникам рефакторинга проблемных областей архитектуры:

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

Объединение нано-сервисов: Чрезмерно мелкие сервисы объединяйте по бизнес-доменам. Используйте карту предметной области для выявления сервисов, которые логически связаны и часто изменяются вместе – именно их следует консолидировать.

Децентрализация данных: Для устранения проблемы общей базы данных внедряйте постепенную стратегию миграции. Создайте отдельные схемы в существующей базе, затем переместите данные в отдельные базы, используя адаптеры для совместимости на переходном этапе.

Асинхронизация взаимодействий: Для снижения связанности между сервисами внедряйте паттерны событийно-ориентированной архитектуры. Заменяйте прямые синхронные вызовы публикацией событий через брокеры сообщений.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// До рефакторинга: синхронный вызов
public OrderConfirmation createOrder(OrderRequest request) {
    // Синхронный вызов сервиса инвентаря
    InventoryResponse inventoryResponse = inventoryClient.checkInventory(request.getItems());
    if (!inventoryResponse.isAvailable()) {
        throw new OutOfStockException();
    }
    // Остальная логика...
}
 
// После рефакторинга: асинхронное взаимодействие
public OrderAcceptance createOrder(OrderRequest request) {
    // Создаем заказ в состоянии "ожидание проверки"
    Order order = new Order(request, OrderStatus.PENDING_INVENTORY_CHECK);
    orderRepository.save(order);
    
    // Публикуем событие для асинхронной проверки
    eventPublisher.publish(new OrderCreatedEvent(order.getId(), request.getItems()));
    
    // Возвращаем подтверждение принятия заказа
    return new OrderAcceptance(order.getId(), "Заказ принят и обрабатывается");
}
 
// В другом сервисе или компоненте:
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
    boolean available = inventoryService.checkAvailability(event.getItems());
    if (available) {
        eventPublisher.publish(new InventoryConfirmedEvent(event.getOrderId()));
    } else {
        eventPublisher.publish(new InventoryRejectedEvent(event.getOrderId()));
    }
}

Инструменты для анализа микросервисной архитектуры



Для эффективного выявления и устранения антипаттернов полезны различные инструменты:

Инструменты для визуализации зависимостей: Платформы вроде Istio с Kiali, Netflix Vizceral или Jaeger позволяют визуально представить взаимодействия между сервисами, выявляя области с высокой связанностью.

Средства автоматизированного анализа кода: Архитектурные линтеры могут обнаруживать нарушения принципов проектирования, например, SonarQube с правилами для микросервисной архитектуры.

Инструменты мониторинга производительности: APM-решения (Application Performance Monitoring) помогают выявлять узкие места и проблемы взаимодействия между сервисами.

Чек-лист для аудита микросервисной архитектуры



При проведении аудита существующей микросервисной системы обратите внимание на следующие вопросы:

1. Границы сервисов: Соответствуют ли границы микросервисов бизнес-доменам? Имеет ли каждый сервис четкую ответственность?
2. Независимость данных: Использует ли каждый сервис собственное хранилище данных? Если данные дублируются, есть ли четкая стратегия синхронизации?
3. Модели коммуникации: Как сервисы общаются между собой? Преобладают ли синхронные вызовы или используются асинхронные методы?
4. Устойчивость к сбоям: Реализованы ли паттерны отказоустойчивости (Circuit Breaker, Bulkhead, Retry)?
5. Наблюдаемость: Достаточно ли данных для мониторинга и диагностики проблем? Реализована ли распределенная трассировка?
6. Развертывание: Можно ли развертывать сервисы независимо друг от друга? Автоматизирован ли процесс CI/CD?
7. Организационная структура: Соответствует ли структура команд архитектуре системы (закон Конвея)?

Регулярный аудит по этому чек-листу поможет своевременно выявлять и устранять антипаттерны, не давая им превратиться в системные проблемы.

Эмуляция х86 архитектуры для работы borland 3.1
Тема в сабже, собственно. Подскажите хороший эмулятор. DosBox - не совсем устраивает. слишком много багов. либо посоветуйте альтернативный...

Сеть архитектуры 10Base-T + 100Base-TX
у кого-нибудь есть пример архитектуры сети с сегментами 10Base-T И 100Base-TX? (желательно с расчетом задержек)

Немного из архитектуры ЭВМ
Пусть заданы две квадратных матрицы A и B размером NxN. Они созданы с помощью двух подходов: 1 подход: int **A; A = new int*; for(int...

«Сведения о памятниках истории и архитектуры»
Люди доюрые!!! Помогите пожалуйста с разработкой такого приложения, или подскажите как это сделать!!! Разработка приложения для предметной...

GNGPU на видеокартах архитектуры R800
Собственно, хотелось бы узнать каким образом можно использовать видеокарту ATI Radeon архитектуры R800 для общих вычислений. Буду благодарен за...

Начало изучения архитектуры компьютера
Привет всем. У меня по учебному курсу в следующем году нужно будет создавать небольшую операционную систему. в этом году был ассемблер - я его с...

Критика архитектуры набора планов
Требуется создать систему похожую на Hierarchical task network то есть некоторая библиотека планов и каждый план может содержать подпланы,...

Проектирование ОО архитектуры
Интересно мнение публики. &quot;Программирование в терминах интерфейсов&quot; Вопрос такой: как правильно конструировать едино-образный интерфейс? По...

Выбор архитектуры FreeBSD
Всем привет! Хочу установить FreeBSD, но не знаю какую архитектуру выбрать. В чем разница? У меня ноут: Проц AMD Athlon II Dual-Core M340...

Нужна помощь в выборе архитектуры системы.
Стоит задача создать довольно сложную систему. Прошу помоч в выборе архетектуры. Примерное ТЗ: Есть много (150-200) компьютеров, разбросанных в...

Написание программы проверки знаний истории архитектуры
Написать программу проверки знания истории архитектуры. Программа должна вывести вопрос и три варианта ответа. Пользователь должен выбрать правильный...

Нужен самоучитель по изучению ассемблера для процессоров архитектуры MIPS
Здравствуйте. Необходимо подобрать подходящий самоучитель по изучению ассемблера для процессоров архитектуры MIPS. Свободно ориентируюсь в Си....

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru