Java:如何处理可能需要大约10秒的API调用

时间:2017-02-28 07:58:17

标签: java ios spring amazon-web-services apache-kafka

我有一个要求,我对它的设计感到有点困惑。

要求:iOS调用后端(java),后端调用云API,返回令牌以供将来调用。云API可能需要大约6到10秒来返回实际结果,因此它不会等待6到10秒,而是返回一个令牌并让调用者(在我的情况下是后端java服务器)来提取结果。

当前方法:iOS调用后端(java服务器),后端调用云API并获取令牌,然后它将线程休眠1秒钟并调用线程它命中云API以获取状态,如果状态未完成,则再次调用thread.sleep并继续,直到云API调用给出完整的结果。一旦云API返回结果,后端就会将结果返回给iOS。

该方法不具有可扩展性,是为了测试云API,但现在我们需要一种更具可扩展性的方法。

这就是我在考虑的问题 iOS调用后端,后端调用API并将结果发送回iOS(它显示一些静态屏幕只是为了让用户保持参与),同时它将对象放在Spring Thread pool Executor中。执行者每秒钟点击一次API并通过推送通知更新iOS,这一直持续到我们从云API获得最终结果。

这比现有的方法更好,但即使这看起来不可扩展,并且线程池执行器在一段时间后会变得疲惫(使其变慢)并且thread.sleep也不是一个好的选择。

我考虑过使用AWS SQS,但它没有提供实时处理,并且每1秒运行后台作业似乎不是一个好选择。

我也正在探索Apache Kafka并尝试了解它是否适​​合我的用例。

如果有人提到类似的用例,请告诉我。

2 个答案:

答案 0 :(得分:1)

如果使用Spring 4.2(或更新)版本,可以使用@EventListener@Scheduled同时使用。

首先创建一个事件对象,说APIResult,它将保存API结果

public class APIResult extends ApplicationEvent {   
    public APIResult(Object result) { 
        super(source);      
    } 
}

接下来为发布为APIResult

的事件注册一个监听器
@Component
public class MyListener {

    @EventListener
    public void handleResult(APIResult result) {
       // do something ... 
    }
}

接下来创建一个计划进程,该进程将保存尚未检索结果的令牌

@Component
public class MyScheduled {

    private final ApplicationEventPublisher publisher;

    private List<String> tokens = new ArrayList<>();    

    @Autowired
    public MyScheduled (ApplicationEventPublisher publisher) { 
        this.publisher = publisher;
    }

    @Scheduled(initialDelay=1000, fixedRate=5000) // modify it as per requirement
    public void callAPIForResult() {
        // call the API and get result for each token(s) ....
        this.publisher.publishEvent(new APIResult(result)); 
    }

    // method to add & remove tokens
}

整个流程应该像

  1. 应用程序向API提交请求并收集相应的令牌。
  2. 将令牌传递给预定服务以获取结果。
  3. 在下一次运行中,计划的服务会迭代可用的令牌并调用API来获取结果(如果结果可用则发布事件,否则继续
  4. 已发布的事件被注册听众拦截;它本身处理结果或代表适用
  5. 这种方法将透明地获取结果,而不会弄乱业务逻辑,同时利用标准框架功能即。调度和异步事件发布&amp;处理

    虽然我没有对此进行测试,但它应该可以工作,至少可以了解如何实现。使用Spring boot ver测试设置。由1.5.1.RELEASE

    支持的4.3.6.RELEASE

    如果需要进一步的信息,请在评论中告知。

    参考 - Spring中的应用程序事件(link

答案 1 :(得分:0)

我正在考虑使用Spring ConcurrentTaskExecutor(让我们称之为cloudApiCall),一旦我从Cloud API收到令牌,我就会将未来的工作提交给执行者并将令牌返回给移动客户端。与ConcurrentTaskExecutor关联的线程将选择作业,调用Cloud API并将响应提交给另一个ConcurrentTaskExecutor(让它称之为pushNotification),该响应将负责将静默通知推送到Mobile客户端。与ConcurrentTaskExecutor(cloudApiCall)相关联的线程也会检查调用的状态,如果将来调用是必需的,它会将作业提交回ConcurrentTaskExecutor(cloudApiCall)。这将持续到我们得到完整的回复为止。