【问题标题】:Best way to close async resteasy client call关闭异步 resteasy 客户端调用的最佳方法
【发布时间】:2020-05-14 09:22:43
【问题描述】:

我有以下代码:

var threadsWaiter = new CountDownLatch(customers.size());
for(var c: List<Customer> customers) {
   sendSms(c.phoneNr, threadsWaiter)
}
threadsWaiter.await();

public void sendSms(String phoneNr, CountDownLatch threadsWaiter) {
  ResteasyClientBuilder.newClient()
            .target(smsUrl)                
            .queryParam("to", phoneNr)
            .queryParam("message", message)
            .request()
            .async()
            .get(new InvocationCallback<String>() {
                @Override
                public void completed(String res) {
                    threadsWaiter.countDown();
                    if (res != null && !res.contains("code=ok") {
                        logger.error("Received sms response for '{}'\n{}", phoneNr, res);
                    } else {                            
                        logger.debug("Sms sent to '{}'", phoneNr);
                    }
                }

                @Override
                public void failed(Throwable throwable) {
                    threadsWaiter.countDown();
                    logger.error("Error sending sms for {}: \n{}", phoneNr, throwable.getMessage());
                }
            });
}

我从控制台收到以下警告:

RESTEASY004687: Closing a class org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine instance for you. Please close clients yourself.

关闭此客户呼叫的正确方法是什么?因为这可能是应用程序中潜在内存泄漏的来源。甚至我从 RestEasy 收到警告,它会自动为我关闭客户端,但我有一种强烈的感觉,它不会关闭所有客户端,因为我看到指标中的内存大幅增加,而且这不会“去一段时间后“下来”。

我已经在 try-finally 之间放置了其余的客户端调用,但这样做的问题是您可以在调用完成之前关闭客户端。 InvocationCallback 中的completed(..)failed(..) 方法中关闭客户端是否可以,还是有更好的方法?

【问题讨论】:

    标签: resteasy quarkus


    【解决方案1】:

    如果通过 JaxRS 接口的客户端定义对您来说没问题,那么上面rowing-goul 的答案就是要走的路。 Quarkus Arc 在 bean 销毁过程中自动关闭注入的客户端。如果您手动创建客户端,则必须明确关闭它们 - 最好的方法是 try - finally

    【讨论】:

      【解决方案2】:

      使用 Quarkus 执行此操作的最佳方法是使用 REST client with async support示例:

          /**
           * This is the client stub.
           */
          @Path("/sms/response") // base URL is set in application.yml
          @RegisterRestClient
          public interface SmsServiceClient {
              
              @GET
              @Produces(MediaType.TEXT_PLAIN)
              CompletionStage<String> sendSms(
                  @QueryParam("to") String phoneNr,
                  @QueryParam("message") String message);
          }
      

      在以下示例中,我使用SmallRye MutinyCompletionStage 转换为具有更精简API 的Uni。但是您可以使用CompletionStage 实现相同的目的。通常,我不会使用 CountDownLatch.await() 方法阻止执行。我把它卡在那里以保持代码与您的示例相似。

          /**
           * This class will actually use the client.
           */
          @Slf4J
          @ApplicationScoped
          public class MySomething {
              
              @Inject
              @RestClient
              SmsServiceClient smsClient;
      
              public void sendSmsInLoop() {
                  var waiter = new CountDownLatch(customers.size());
                  customers.forEach(customer -> {
                      Uni.createFrom().completionStage(
                          smsClient.sendSms(customer.getPhoneNr(), "Lorem Ipsum...")
                      ).onItem().invoke(responseString -> {
                          if (responseString == null || !responseString.contains("code=ok")) {
                              log.error("Unexpected sms response for '{}'\n{}", customer.getPhoneNr(), responseString); 
                          } else {
                              log.debug("Sms sent to '{}'", customer.getPhoneNr());
                          }
                      }).onFailure().invoke(throwable -> {
                          log.error("Error sending sms to '{}'\n{}", customer.getPhoneNr(), throwable.getMessage());
                      }).eventually(() -> waiter.countDown());
                  });
                  waiter.await();
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2012-04-28
        • 1970-01-01
        • 2010-09-22
        • 1970-01-01
        • 1970-01-01
        • 2015-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多