Spring Boot — использование Resilience4j-Circuitbreaker для реализации режима автоматического выключателя_предотвращения каскадных сбоев
Spring Boot — использование Resilience4j-Circuitbreaker для реализации режима автоматического выключателя_предотвращения каскадных сбоев

Pre

Spring Boot — использование Resilience4j-RateLimiter для управления потоком и ухудшения качества обслуживания

Обзор устойчивости4j

Resilience4J — это легкая библиотека отказоустойчивости и отказоустойчивости для приложений Java 8. Он предназначен для обеспечения устойчивости и отказоустойчивости между службами в распределенной системе. Название Resilience4J происходит от его основной функциональности, которая заключается в том, чтобы сделать системы (сервисы) «устойчивыми» к различным ситуациям сбоев, включая проблемы с сетью, сбои сторонних служб и т. д.

Resilience4J предоставляет следующие возможности:

  1. Автоматический выключатель:при обнаружении Служить Исключение или тайм-аут,Автоматический выключатель разомкнется,Блокирует дальнейшую отправку запросов на этот Служить. Через некоторое время (обычно да секунд),Автоматический выключатель перейдет в полуоткрытое состояние.,Разрешить прохождение тестового запроса, чтобы проверить, восстановлена ​​ли Служитдада. Если запрос успешен,В случае неисправности автоматический выключатель замыкается;,Автоматический выключатель снова включится.
  2. Ограничитель скорости:ограниченный доступсистемаиз Запросить ставку,Предотвращение перегрузки системы. Этого можно достичь с помощью алгоритма корзины токенов или алгоритма скользящего окна.
  3. Изоляция:Изолировать разные по семафору или пулу потоковиз Служитьвызов,Не допускать, чтобы отказ одной Служитьиз влиял на другую Служить.
  4. Таймауты:для Служитьвызов设置超时时间,Исключение тайм-аута будет вызвано после превышения времени.
  5. Повторить попытку:Автоматически повторять попытку при обнаружении определенных исключений Служитьвызов,МожетConfiguration 重试Номер второго порядка и интервал.
  6. Кэширование:Обеспечить механизм кэширования,Чтобы избежать повторного выполнения ресурсоемких или удаленных вызовов.

Основной особенностью Resilience4J является его легковесность. Он использует только библиотеку Vavr (библиотеку функционального программирования) и не имеет других зависимостей от внешних библиотек. Это делает очень удобной интеграцию в существующие системы с небольшими затратами на производительность.

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

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

Официальный адрес Resilence4j

https://resilience4j.readme.io/

https://github.com/resilience4j/resilience4j

Resilience4j-Circuitbreaker

CircuitBreaker в Resilience4j — это основной инструмент для защиты распределенных систем от сбоев.

Принцип его работы в основном заключается вконечный автоматвыполнить,В том числе CLOSED (закрыт), OPEN (открыт) и HALF-OPEN (полуоткрыт).

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

Resilience4j предоставляет различные механизмы отказоустойчивости, включая автоматический выключатель (CircuitBreaker), ограничитель тока (RateLimiter), повторную попытку (Retry), стратегию изоляции (Bulkhead) и управление тайм-аутом (TimeLimiter). Среди них CircuitBreaker является важной частью Resilience4j.

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

Принцип реализации CircuitBreaker Resilience4j заключается в следующем:

  1. Статус автоматического выключателя: CircuitBreaker Имеет три нормальных состояния: CLOSED (закрыто), OPEN (открыто) и HALFOPEN (полуоткрыто) и два особых состояния: DISABLED (отключено) и FORCEDOPEN (принудительное открытие). Эти статусы передаются конечным автомат для управления.
  2. Логика размыкания и замыкания: когда защищенный излужит или ресурс выходит из строя или недоступен в течение длительного времени, автоматический выключатель быстро переключается в OPEN статус, предотвращая отправку дальнейших запросов на этот Служить или ресурс. существовать OPEN статус, система будет периодически отправлять тестовые запросы, чтобы проверить, устранена ли неисправность. Если тестовый запрос успешен, автоматический выключатель переключается в режим HALFOPEN Статус, позволяющий отправить запрос на этот Служить или ресурс. Если этот запрос успешен, автоматический выключатель переключается в режим CLOSED статус, в противном случае он переключится обратно на OPEN состояние.
  3. Расчет интенсивности отказов: чтобы определить, следует ли размыкать автоматический выключатель, необходимо собрать определенный объем данных запроса. существовать Resilience4j , вам необходимо заполнить хотя бы один кольцевой буфер (Ring Bit Buffer),Только после этого мы сможем приступить к расчету частоты отказов.。кольцевой буфериз Размер определяет необходимое количество Второсортный Запрос на определение частоты отказовизвычислить。
  4. Кольцевой буфер: Resilience4j Используйте кольцевой буфер для хранения структуры данных состояния запроса, которая аналогична Hystrix Раздвижные окна используются разные. Кольцевой буфер реализован с помощью набора битов (BitSet), каждый бит представляет собой статус запроса (успех или неудача). Размер кольцевого буфера определяет количество запросов, которые можно сохранить. Например, размер 10 Буфер может хранить 1024 запросысостояние.
  5. Варианты конфигурации: Resilence4j Обеспечивает богатыйиз Конфигурация Параметры,Например, порог частоты отказов, время ожидания в открытом состоянии, максимальное количество запросов, разрешенных в полуоткрытом состоянии и т. д.,Разработчики могут гибко настроить его под свои нужды.

Благодаря вышеуказанным принципам CircuitBreaker Resilience4j может эффективно защитить распределенные системы от сбоев и повысить доступность и надежность системы.


Сценарии применения

Служба A вызывает службу B, но, к сожалению, служба B недоступна или не отвечает. Таким образом, служба A может дождаться ответа службы B или обработать возникшее исключение. Последующие запросы к Сервису B столкнутся с аналогичными проблемами, что приведет к ухудшению пользовательского опыта.

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

Автоматические выключатели имеют три состояния: замкнуто, разомкнуто и полуоткрыто.

  • Замкните автоматический выключатель да в исходное состояние. Когда микро Служить работает и взаимодействие плавное.,Автоматический выключатель выключен. Он постоянно отслеживает количество неисправностей, возникших за определенный период времени. Если частота отказов превышает указанный порог,Его статус изменится на «Открытое состояние».,Это сбросит счетчик сбоев и период ожидания.
  • В открытом состоянии,Автоматический выключатель блокирует поток взаимодействий между микросетями. Вызов запроса не удастся,и будет выброшено исключение. Open Состояние сохраняется до истечения времени ожидания, затем меняется на Half_Open состояние.
  • В состоянии Half_Open,Автоматический выключатель пропустит ограниченное количество запросов. Если частота отказов превышает указанный порог,Затем Второсортный переключается на Открытоесостояние. В противном случае — Закрытоесостояние.

Демонстрация микросервисов

Существует 2 службы: адресная служба и служба заказов.

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

Address service

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

POM
Язык кода:javascript
копировать
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.edu</groupId>
    <artifactId>address-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>address-service</name>

    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Model
Язык кода:javascript
копировать
package com.edu.addressservice.model;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "addresses")
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String postalCode;
    private String state;
    private String city;
}

Repository
Язык кода:javascript
копировать
package com.edu.addressservice.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.edu.addressservice.model.Address;

@Repository
public interface AddressRepository extends JpaRepository<Address, Integer> {
    Optional<Address> findByPostalCode(String postalCode);
}

Service
Язык кода:javascript
копировать
public interface AddressService {
    Address getAddressByPostalCode(String postalCode);
}
Язык кода:javascript
копировать
@Service
public class AddressServiceImpl implements AddressService {
    @Autowired
    private AddressRepository addressRepository;
    public Address getAddressByPostalCode(String postalCode) {
        return addressRepository.findByPostalCode(postalCode)
                .orElseThrow(() -> new RuntimeException("Address Not Found: " + postalCode));
    }
}

Controller
Язык кода:javascript
копировать
package com.edu.addressservice.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.edu.addressservice.model.Address;
import com.edu.addressservice.service.AddressService;

@RestController
@RequestMapping("addresses")
public class AddressController {
    @Autowired
    private AddressService addressService;
    @GetMapping("/{postalCode}")
    public Address getAddressByPostalCode(@PathVariable("postalCode") String postalCode) {
        return addressService.getAddressByPostalCode(postalCode);
    }
}

Data Init

использовать@PostConstructаннотацияизметод。 Spring будет инициализирован bean Этот метод вызывается после заполнения свойства данными.

Язык кода:javascript
копировать
package com.edu.addressservice.config;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import com.edu.addressservice.model.Address;
import com.edu.addressservice.repository.AddressRepository;

import jakarta.annotation.PostConstruct;

@Configuration
public class DataSetup {
    @Autowired
    private AddressRepository addressRepository;
    @PostConstruct
    public void setupData() {
        addressRepository.saveAll(Arrays.asList(
                Address.builder().id(1).postalCode("1000001").state("SD").city("JN")
                        .build(),
                Address.builder().id(2).postalCode("1100000").state("JS").city("NJ").build(),
                Address.builder().id(3).postalCode("2100001").state("ZJ").city("HZ")
                        .build()));
    }
}

Properties
Язык кода:javascript
копировать
server:
  port: 9090
spring:
  application:
    name: address-service
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: create-drop
  datasource:
    url: jdbc:h2:mem:address-db
    username: admin
    password: 1111
    driverClassName: org.h2.Driver
  h2:
    console:
      enabled: true

тест

Запустите и перейдите по ссылкеhttp://localhost:9090/addresses/1000001,Ожидаемый ответ должен выглядеть так

На этом построение адресной службы завершено.

Order service

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

Model
Язык кода:javascript
копировать
public interface Type {
}
Язык кода:javascript
копировать
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "orders")
public class Order implements Type {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;
    private String orderNumber;
    private String postalCode;
    private String shippingState;
    private String shippingCity;
}
Язык кода:javascript
копировать
@Data
public class Failure implements Type {
    private final String msg;
}

Repository
Язык кода:javascript
копировать
package com.edu.orderservice.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.edu.orderservice.model.Order;

@Repository
public interface OrderRepository extends JpaRepository<Order, Integer> {
    Optional<Order> findByOrderNumber(String orderNumber);
}

Service

Вся бизнес-логика здесь.

  • Получить информацию о заказе из таблицы «Заказы».
  • Позвоните во внешнюю Служить (адрес Служить), чтобы получить информацию об адресе доставки.
  • Обновите информацию о заказе, указав адрес доставки и верните товар.

нравиться何вызов外部API---------------------> Spring предоставил RestTemplate

Язык кода:javascript
копировать
package com.edu.orderservice.service;

import com.edu.orderservice.model.Type;

public interface OrderService {
    Type getOrderByPostCode(String orderNumber);
}
Язык кода:javascript
копировать
package com.edu.orderservice.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.edu.orderservice.dto.AddressDTO;
import com.edu.orderservice.model.Failure;
import com.edu.orderservice.model.Order;
import com.edu.orderservice.model.Type;
import com.edu.orderservice.repository.OrderRepository;
import com.edu.orderservice.service.OrderService;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private RestTemplate restTemplate;
    private static final String SERVICE_NAME = "order-service";
    private static final String ADDRESS_SERVICE_URL = "http://localhost:9090/addresses/";

    @Override
    @CircuitBreaker(name = SERVICE_NAME, fallbackMethod = "fallbackMethod")
    public Type getOrderByPostCode(String orderNumber) {
        Order order = orderRepository.findByOrderNumber(orderNumber)
                .orElseThrow(() -> new RuntimeException("Order Not Found: " + orderNumber));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<AddressDTO> entity = new HttpEntity<>(null, headers);
        ResponseEntity<AddressDTO> response = restTemplate.exchange(
                (ADDRESS_SERVICE_URL + order.getPostalCode()), HttpMethod.GET, entity,
                AddressDTO.class);
        AddressDTO addressDTO = response.getBody();
        if (addressDTO != null) {
            order.setShippingState(addressDTO.getState());
            order.setShippingCity(addressDTO.getCity());
        }
        return order;
    }

    private Type fallbackMethod(Exception e) {
        return new Failure("Address service is not responding properly");
    }
}

@CircuitBreaker свойство

  • name”被分配для“order-service”,Имя таблицы «заказ-услуга», экземпляр каждого Конфигурация подходит для этого метода.
  • fallbackMethod”свойство,Цель вызывает метод понижения версии, когда зависимость Служить (адрес Служить) не отвечает правильно.

Set Up
Язык кода:javascript
копировать
@Configuration
public class RestConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
Язык кода:javascript
копировать
package com.edu.orderservice.config;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import com.edu.orderservice.model.Order;
import com.edu.orderservice.repository.OrderRepository;

import jakarta.annotation.PostConstruct;

@Configuration
public class DataSetup {
    @Autowired
    private OrderRepository orderRepository;
    @PostConstruct
    public void setupData() {
        orderRepository.saveAll(Arrays.asList(
                Order.builder().id(1).orderNumber("0c70c0c2").postalCode("1000001").build(),
                Order.builder().id(2).orderNumber("7f8f9f15").postalCode("1100000").build(),
                Order.builder().id(3).orderNumber("394627b2").postalCode("2100001").build()));
    }
}

Properties
Язык кода:javascript
копировать
server:
  port: 1010
spring:
  application:
    name: order-service
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: create-drop
  datasource:
    url: jdbc:h2:mem:order-db
    username: root
    password: 123
    driverClassName: org.h2.Driver
  h2:
    console:
      enabled: true
management:
  endpoint:
    health:
      show-details: always
  endpoints:
    web:
      exposure:
        include: health
  health:
    circuitbreakers:
      enabled: true
resilience4j:
  circuitbreaker:
    instances:
      order-service:
        sliding-window-type: COUNT_BASED
        failure-rate-threshold: 50
        minimum-number-of-calls: 5
        automatic-transition-from-open-to-half-open-enabled: true
        wait-duration-in-open-state: 5s
        permitted-number-of-calls-in-half-open-state: 3
        sliding-window-size: 10
        register-health-indicator: true

Конфигурация предназначена для Resilience4j Конфигурация библиотеки

Далее идет пара order-service Пояснения к каждому элементу конфигурации экземпляра автоматического выключателя:

  • Тип скользящего окна: COUNT_BASED:этот指定了использовать于跟踪неудачаизраздвижное окнодаоснованный на неудачеизвызов Второсортныйчисло。Resilience4j Поддерживает два типаизраздвижное окно:COUNT_BASED(на основе Второсортныйчисло)и TIME_BASED(на основе时间)。
  • Порог частоты отказов: 50:Это приводит к размыканию автоматического выключателя.из Порог частоты отказов。в этом случае,Если процент отказов достигает 50%,тогда автоматический выключатель разомкнется,и блокирует дальнейшие запросы на Служитьиз.
  • Минимальное количество звонков во Второсортный: 5:этот设置了在вычислить故障率之前必须执行извызов Второсортныйчисло。если меньше, чем 5 Второсортный вызов, автоматический выключатель не отключится из-за интенсивности отказов.
  • Автоматический переход из открытого состояния в полуоткрытое: true:этот Конфигурацияавтоматический выключатель в указанномиз Автоматический переход из открытого состояния в полуоткрытое после периода ожидания.состояние.в полуоткрытом состоянии,Через Служить разрешено ограниченное количество запросов на получение.
  • Время ожидания в открытом состоянии: 5 с.:этотдаавтоматический выключатель остается разомкнутымиз秒число,После этого он переходит в полуоткрытое состояние.
  • В полуоткрытом состоянии допускается вызов номера Второсортного: 3:этот设置了в полуоткрытом состоянии允许извызов Второсортныйчисло。если во времяиметь Превосходить 3 Если вызов Второсортировки не удался, автоматический выключатель вернется в состояние размыкания.
  • Размер раздвижного окна: 10:этот Конфигурация了использовать于跟踪请求инеудачаизраздвижное окноизразмер。раздвижное окноизразмер必须大于вычислить故障率所需из最小вызов Второсортныйчисло。
  • Зарегистрировать показатели здоровья: верно:этот个标志指示да否для断路器注册健康指标。健康指标использовать于提供关于组件健康状况изинформация,Включает автоматический выключатель.

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


тест

Последовательно запустите адресную службу и службу заказов и перейдите по ссылке http://localhost:1010/orders?orderNumber=0c70c0c2.

Если служба адресов отвечает неправильно (служба не работает), мы получим следующий ответ

На этом построение сервиса заказов завершено.

Изучите автоматические выключатели

Убедитесь, что обе службы запущены, перейдите по ссылке http://localhost:1010/actuator/health Посмотреть подробную информацию о автоматическом выключателе

Мы видим следующие ключевые конфигурации:

  • bufferedCalls(缓冲вызов Второсортныйчисло)для0,Это означает, что вызовы API от службы заказа к службе адреса не выполняются.
  • failedCalls(неудачавызов Второсортныйчисло)也для0,Это означает, что все вызовы прошли успешно.,Нет возможности неудачного звонка.
  • failureRate(неудача率)для-1.0%,Это аномалия значения,Потому что процент отказов не может быть отрицательным. в целом,Процент неудач должен быть частью процента успеха.,То есть 0% означает 100% вероятности успеха. Это может быть так, потому что 0 используется в качестве знаменателя при расчете частоты отказов.,В результате получаются отрицательные числа из.
  • state(состояние)для"CLOSED"(закрытие),Это указывает на то, что автоматический выключатель в данный момент замкнут.,Механизм автоматического выключателя не срабатывает.

Вызов API сервиса заказов 2 раза

Вызов API сервиса заказов 2 разаhttp://localhost:1010/orders?orderNumber=0c70c0c2,

Затем обновите ссылку на привод.

  • “bufferedCalls”: 2, // Total number of API calls now is 2

Закройте адресную службу и вызовите API службы заказа 3.

Закройте адресную службу и вызовите API службы заказа 3.Второсортныйhttp://localhost:1010/orders?orderNumber=0c70c0c2,Затем обновите ссылку исполнителя.

Мы заметили, что сработал автоматический выключатель. Причина в том, что «failureRate» теперь больше, чем «failure-rate-threshold».

  • “status”: “CIRCUIT_OPEN”, // CircuitBreaker is triggered
  • “failureRate”: “60.0%”, // this rate now is greater than “failureRateThreshold”
  • “bufferedCalls”: 5, // Total number of API calls from order-service to address-service
  • “failedCalls”: 3, // Number of failed API calls from order-service to address-service

Подождите 5 секунд, чтобы обновить исполнителя.

В состоянии HALF_OPEN разрешаем запросы «разрешенного количества вызовов в полуоткрытом состоянии» (мы настраиваем его значение равным 3), а затем снова вычисляем частоту отказов, если частота отказов все еще превышает «порог интенсивности отказов», автоматический выключатель сработает снова.


Продолжайте вызывать API службы заказов 3 раза.

Продолжайте вызывать API службы заказов 3 раза. http://localhost:1010/orders?orderNumber=0c70c0c2,Затем обновите ссылку исполнителя.

  • “status”: “CIRCUIT_OPEN”, // // CircuitBreaker is triggered again

Запустите адресную службу, а затем продолжайте вызывать API службы заказов 3 раза.

Запустите адресную службу, а затем продолжайте вызывать API службы заказов 3 раза.http://localhost:1010/orders?orderNumber=0c70c0c2,Обновить ссылку исполнителя

Автоматический выключатель замкнут.

краткое содержание

Схема устойчивости4j breakerспециальный режимиметьиспользовать,Может не вызвать Служить после достижения определенного количества Второсортный,Автоматический разрыв цепи,Избегайте дальнейших звонков,Это защищает приложение от сбоев. Когда Служить выздоровеет,Цепь снова замкнется,Разрешить выполнение обычных вызовов.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose