如何在Java中以同步方式处理异步回调?

Tah*_*raf 11 java architecture multithreading asynchronous integration-patterns

我有一个与架构有关的问题.这是一个与语言无关的问题,但是当我来自Java背景时,如果有人用Java方式引导我,对我来说会更容易.

基本上,我正在编写的中间件与基于SOAP的第三方服务进行通信.调用是异步的 - 在某种程度上,当一个服务被调用时,它返回一个响应01 - 处理; 意味着第三方已成功收到请求.在原始SOAP请求中,每次都必须提交一个回调URL,其中第三方实际发送结果.因此,调用特定服务实际上不会立即返回结果; 结果在中间件的单独HTTP端点中接收.

现在在我们的前端,我们不希望使用户体验复杂化.我们希望我们的用户调用中间件功能(通过菜单项/按钮),并立即获得结果; 并将肮脏的工作留给中间件.

请注意,从前端调用的中间件函数(比如说X())和第三方推送结果的中间件端点URL(让我们称之为Y)完全是彼此分开的.X()不得不等待,然后获取Y中抓取的结果,然后将结果返回到前端.

在此输入图像描述

如何构建一个强大的解决方案来实现上述行为?图片完美地描绘了我的情况.任何建议将受到高度赞赏.

ern*_*t_k 8

这个问题可能更多地是关于集成模式而不是多线程模式.但是,可以使用异步调用和观察者模式的组合来编排同一应用程序/ JVM中的请求:

使用示例(利用Java知识)可以更好地完成此操作.检查尝试复制方案的以下简单组件:

第三方服务:它公开一个返回相关ID并开始长时间执行的操作

class ExternalService {
    public String send() {
        return UUID.randomUUID().toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

面向客户的服务:收到请求,调用第三方服务,然后向结果接收者注册后等待响应:

class RequestProcessor {
    public Object submitRequest() {
        String correlationId = new ExternalService().send();

        return new ResultReceiver().register(correlationId).join();
    }
}
Run Code Online (Sandbox Code Playgroud)

结果接收器:它向第三方服务公开操作,并维护内部关联注册表:

class ResultReceiver {

    Map<String, CompletableFuture<Object>> subscribers;

    CompletableFuture<Object> register(String responseId) {
        CompletableFuture<Object> future = new CompletableFuture<Object>();
        this.subscribers.put(responseId, future);

        return future;
    }

    public void externalResponse(String responseId, Object result) {
        this.subscribers.get(responseId).complete(result);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,期货,承诺,回拨都很方便.初始请求处理器完成同步,以强制执行阻止客户端.

现在,这可能引发一些在这个简单的类集中没有解决的问题.其中一些问题可能是:

  • new ExternalService().send()和之间的竞争条件new ResultReceiver().register(correlationId).这是可以解决的问题,ResultReceiver如果它不能确定某些响应可以非常快(双向等待,可以这么说)
  • 永无止境的结果:结果可能需要很长时间或者只是遇到错误.这些未来的API通常会提供超时以强制取消请求.例如:

    new ResultReceiver().register(correlationId)
        .get(10000, TimeUnit.SECONDS);
    
    Run Code Online (Sandbox Code Playgroud)