# 舱壁模式

**如果不使用舱壁模式，默认行为是使用为整个Java容器处理请求而保留的相同线程去执行这些调用。**&#x5728;高负载情况下，多个服务中的一个性能问题可能导致用于Java容器的所有线程都被用满并等待处理工作，而新的工作请求则排队等待。**Java容器最终会崩溃**。

<mark style="color:blue;">**舱壁模式将远程资源调用隔离在它们自己的线程池中，以便单个不良行为的服务可以被隔离并且不会使容器崩溃。**</mark>Resilience4j提供了舱壁模式的两种不同实现。

* <mark style="color:blue;">**信号量舱壁（Semaphore bulkhead）**</mark>**：** 使用信号量隔离方法，限制对服务的并发请求数量。一旦达到限制，它就开始拒绝请求。
* <mark style="color:blue;">**线程池舱壁（Thread pool bulkhead）**</mark>**：** 使用有界队列和固定线程池。这种方法只有在线程池和队列都满时才拒绝请求。

**Resilience4j默认使用信号量舱壁。**

## 配置

```yaml
resilience4j.bulkhead:
  instances:
    licenseService:
      maxWaitDuration: 10ms # The maximum amount of time to block a thread
      maxConcurrentCalls: 20 # The maximum number of concurrent calls

resilience4j.thread-pool-bulkhead:
  configs:
    shared:
      maxThreadPoolSize: 4 # The maximum number of threads in the thread pool
      coreThreadPoolSize: 2 # The core thread pool size
      queueCapacity: 2 # The queue’s capacity
      # The maximum time that idle threads wait for new tasks before terminating
      keepAliveDuration: 20ms 
  instances:
    organizationService:
      baseConfig: shared
```

* <mark style="color:blue;">**maxWaitDuration**</mark>**（最大等待时间）**：&#x20;
  * 设置进入舱壁时阻塞线程的最长时间。
  * 默认值为0。
* <mark style="color:blue;">**maxConcurrentCalls**</mark>**（最大并发调用数）**：&#x20;
  * 设置舱壁允许的最大并发调用数。
  * 默认值为25。
* <mark style="color:blue;">**maxThreadPoolSize**</mark>**（最大线程池大小）**：
  * &#x20;设置最大线程池大小。
  * 默认值为 Runtime.getRuntime().availableProcessors()。
* <mark style="color:blue;">**coreThreadPoolSize**</mark>**（核心线程池大小）**：
  * &#x20;设置核心线程池大小。
  * 默认值为 Runtime.getRuntime().availableProcessors()。
* <mark style="color:blue;">**queueCapacity**</mark>**（队列容量）**：&#x20;
  * 设置队列的容量。
  * 默认值为100。
* <mark style="color:blue;">**keepAliveDuration**</mark>**（保持存活时间）**：&#x20;
  * 设置空闲线程在终止之前等待新任务的最长时间。当线程数量高于核心线程数量时会发生。
  * 默认值为20毫秒。

> ## 一个自定义线程池的适当大小可以通过以下公式确定：
>
> $$
> (\text{服务健康时的峰值每秒请求数} \times \text{第99百分位延迟（以秒为单位）}) + \ \text{一小部分额外线程以应对潜在的开销或负荷波动}
> $$
>
> 通常，在服务承受负载之前，我们往往不了解服务的性能特性。<mark style="color:blue;">**线程池属性可能需要调整的一个重要信号是：即使目标远程资源处于健康状态，服务调用也处于超时的过程中。**</mark>
>
> 根据给定的公式调整线程池有助于确保线程池足够大，能够处理预期的负载并保持响应性，避免出现超时和服务性能下降等问题。

## 使用

### @Bulkhead 注解

```java
@Override
@Bulkhead(name = ORGANIZATION_SERVICE, fallbackMethod = "getOrgBackup")
@CircuitBreaker(name = ORGANIZATION_SERVICE, fallbackMethod = "getOrgBackup")
public Organization getOrganizationByAnnotation(String organizationId) {
    return organizationFeignClient.getOrganization(organizationId);
}
```

### CircuitBreakerFactory

```java
Organization organization = circuitBreakerFactory.create(ORGANIZATION_SERVICE).run(
        () -> organizationFeignClient.getOrganization(organizationId),
        throwable -> getOrganizationBackup(organizationId, throwable)
);
```

> ### <mark style="color:blue;">circuitBreakerFactory 自动注入了与 circuitbreaker 同名的 bulkhead。</mark>

## Actuator 端点查看

<details>

<summary><mark style="color:purple;">http://localhost:8080/actuator/bulkheads</mark></summary>

```json
{
    "bulkheads": [
        "licenseService",
        "organizationService"
    ]
}
```

</details>

<details>

<summary><mark style="color:purple;">http://localhost:8080/actuator/bulkheadevents</mark></summary>

```json
{
    "bulkheadEvents": [
        {
            "bulkheadName": "organizationService",
            "type": "CALL_PERMITTED",
            "creationTime": "2023-12-10T15:33:44.013023100+08:00[Asia/Shanghai]"
        },
        {
            "bulkheadName": "organizationService",
            "type": "CALL_FINISHED",
            "creationTime": "2023-12-10T15:33:59.058528600+08:00[Asia/Shanghai]"
        }
    ]
}
```

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bohans.gitbook.io/ji-chu/spring/group-1/spring-cloud/ke-hu-duan-tan-xing-mo-shi-resilience4j/ke-hu-duan-tan-xing-mo-shi/cang-bi-mo-shi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
