Java EE的断路器API设计,Java岗面试题总结

断路器

与电气工程中的断路器类似,软件中的断路器检测故障或响应缓慢,并通过抑制注定要失败的动作来防止进一步损坏。我们可以指定断路器应该根据先前的执行中断某些功能的执行情况。

有多个第三方库可用于实现断路器,包括MicroProfile Fault Tolerance项目,该项目与Java EE非常好地集成,并得到少数应用程序容器供应商的支持。以下声明该类的printInstrument方法MakerBot由具有默认行为的MicroProfile断路器保护:

<span style="color:#333333">@CircuitBreaker

<strong>public</strong> <strong>void</strong> printInstrument(InstrumentType type) {

    JsonObject requestBody = createRequestBody(type);

    Response response = sendRequest(requestBody);

    validateResponse(response);

}

</span>

如果@CircuitBreaker方法执行失败,那么注释将导致方法执行被中断 - 也就是说,如果它在20次调用中超过50%的时间抛出异常 - 默认情况下。电路打开后,执行将默认中断至少5秒。可以使用注释覆盖这些默认值。

可以使用@Fallback注释定义回退行为,注释分别引用回退处理程序类或方法。

重试

重试背后的动机是通过立即重试失败的操作来消除暂时的失败。此重试对调用功能透明地发生。

使用MicroProfile Fault Tolerance实现技术动机重试很简单。@Retry如果发生异常,注释将导致方法调用最多重新执行三次。我们可以使用注释值进一步配置行为,例如延迟时间或异常类型。

与断路器类似,@Fallback如果在最大重试次数后调用仍然失败,也可以定义行为。

隔板

与船上的隔间类似,隔板旨在将软件功能划分为可单独失效的部分,而不会导致整个应用程序无响应。它们可以防止错误进一步级联,同时应用程序的其余部分保持正常运行。

在企业Java中,通过定义多个池(例如数据库连接池或线程池)来应用Bulkhead模式。对于多个线程池,如果另一个线程池当前用尽,我们可以确保应用程序的特定部分不受影响。

但是,企业Java应用程序不应该启动或管理自己的线程; 相反,他们必须使用平台功能来提供托管线程。为此,Java EE附带一个ManagedExecutorService提供容器管理线程的线程,通常基于单个线程池。

由Java EE专家Adam Bien提供的Porcupine库支持进一步定义可以单独配置的容器管理线程池。以下显示了两个专用ExecutorService的检索和创建工具的定义和用法:

<span style="color:#333333">@Inject

@Dedicated(<span style=“color:#00bb00”>“instruments-read”</span><span style=“color:black”>)

ExecutorService readExecutor;

@Inject

@Dedicated(</span><span style=“color:#00bb00”>“instruments-write”</span><span style=“color:black”>)

ExecutorService writeExecutor;

</span><span style=“color:#0000aa”><em>// usage within method body …</em></span><span style=“color:black”>

CompletableFuture.supplyAsync(() -> instrumentCraftShop.getInstruments(), readExecutor);

</span><span style=“color:#0000aa”><em>// usage within method body …</em></span><span style=“color:black”>

CompletableFuture.runAsync(() -> instrumentCraftShop.craftInstrument(instrument), writeExecutor)

</span></span>

通常,这些执行程序服务可以在我们的整个应用程序中使用。但是,在使用HTTP资源时需要考虑另一种情况。

应用程序服务器通常使用单个线程池来处理传入请求的HTTP请求线程。当然,单个请求线程池使我们很难在我们的应用程序中构建多个隔板。

因此,我们可以使用异步JAX-RS资源来立即管理对专用执行程序服务的传入请求的处理:

<span style="color:#333333">@Path(<span style="color:#00bb00">"instruments"</span><span style="color:black">)

@Consumes(MediaType.APPLICATION_JSON)

@Produces(MediaType.APPLICATION_JSON)

<strong>public</strong> <strong>class</strong> InstrumentsResource {

    @Inject

    InstrumentCraftShop instrumentCraftShop;

    @Inject

    @Dedicated(</span><span style=“color:#00bb00”>“instruments-read”</span><span style=“color:black”>)

    ExecutorService readExecutor;

    @Inject

    @Dedicated(</span><span style=“color:#00bb00”>“instruments-write”</span><span style=“color:black”>)

    ExecutorService writeExecutor;

    @GET

    <strong>public</strong> CompletionStage<List<Instrument>> getInstruments() {

        <strong>return</strong> CompletableFuture

                .supplyAsync(() -> instrumentCraftShop.getInstruments(), readExecutor);

    }

    @POST

    <strong>public</strong> CompletionStage<Response> createInstrument(@Valid @NotNull Instrument instrument) {

        <strong>return</strong> CompletableFuture.runAsync(

                () -> instrumentCraftShop.craftInstrument(instrument), writeExecutor)

                .thenApply(c -> Response.noContent().build())

                .exceptionally(e -> Response.status(Response.Status.INTERNAL_SERVER_ERROR)

                        .header(</span><span style=“color:#00bb00”>“X-Error”</span><span style=“color:black”>, e.getMessage())

                        .build());

    }

}

</span></span>

检索和创建工具的传入请求将传递到单独的线程池。从JAX-RS 2.1开始,返回一个CompletionStage或兼容的类型就足以将JAX-RS资源声明为异步。异步处理完成后,请求将被暂停并恢复。

如果分别用于检索或创建工具的这两个功能中的一个将被重载并且池中的线程用完,则另一个将不受此影响。共享请求线程池不太可能用完线程,因为请求的处理会立即传递给其他受管线程。

我们使用Porcupine库而不是MicroProfile Fault Tolerance的Bulkhead功能的原因是:前者使我们能够直接访问和控制我们与异步JAX-RS资源连接的托管执行程序服务。

背压

负载较重的应用程序可以通过向客户通知其当前状态来应用背压。这可以通过多种方式实现,例如,通过向响应添加元数据或者通过返回失败响应来更加彻底地添加元数据。

如果我们认为应用程序保持响应更为重要,尤其是它能够在其服务级别协议(SLA)内响应而不是延迟响应,那么我们将希望实现背压。关于满足整个系统的SLA,立即响应错误以使客户端可以调用不同的应用程序或实例,而不是消耗所有SLA时间并且仍然无法正常运行可能更有帮助处理请求。

为了指示我们的执行程序服务在所有线程都忙的情况下立即拒绝超过执行程序等待队列的调用,我们需要进一步配置行为。ExecutorConfigurator是Porcupine使用的托管bean,我们可以使用CDI专门使用它:

<span style="color:#333333">@Specializes

<strong>public</strong> <strong>class</strong> CustomExecutorConfigurator <strong>extends</strong> ExecutorConfigurator {

    @Override

    <strong>public</strong> ExecutorConfiguration forPipeline(String name) {

        <strong>if</strong> (<span style=“color:#00bb00”>“instruments-read”</span><span style=“color:black”>.equals(name))

            <strong>return</strong> <strong>new</strong> ExecutorConfiguration.Builder()

                    .abortPolicy()

                    .queueCapacity(4)

                    .build();

        <strong>return</strong> <strong>new</strong> ExecutorConfiguration.Builder()

                .abortPolicy()

                .build();

    }

}

</span></span>

覆盖方法forPipeline用于为限定名称构造执行程序服务。该abortPolicy调用将指示底层的线程池立即拒绝与超过资源的新的调用RejectedExecutionException。这是我们的目的所期望的行为。

为了通知客户端我们的应用程序不可用,我们将此异常映射到HTTP 503响应:

<span style="color:#333333">@Provider

<strong>public</strong> <strong>class</strong> RejectedExecutionHandler implements ExceptionMapper<RejectedExecutionException> {

    @Override

    <strong>public</strong> Response toResponse(RejectedExecutionException exception) {

        <strong>return</strong> Response.status(Response.Status.SERVICE_UNAVAILABLE).build();

    }

}

总结

面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。

以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考

一份还热乎的蚂蚁金服面经(已拿Offer)面试流程4轮技术面+1轮HR

nse.Status.SERVICE_UNAVAILABLE).build();

    }

}

总结

面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。

以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考

[外链图片转存中…(img-ZtNnrlI3-1630460395160)]

CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值