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

Java:如何处理大约需要10秒的API调用,java,ios,spring,amazon-web-services,apache-kafka,Java,Ios,Spring,Amazon Web Services,Apache Kafka,我有一个要求,我对它的设计有点困惑 要求:iOS调用后端(java),后端调用云API,后者为将来的调用返回令牌。云API可能需要大约6到10秒才能返回实际结果,因此它不会等待6到10秒,而是返回一个令牌,让调用方(在我的例子中是后端java服务器)提取结果 当前方法:iOS调用后端(java服务器),后端调用cloud API并获取令牌,然后休眠线程1秒,一旦调用线程,它就会点击cloud API以获取状态,如果状态为not completed,则会再次调用thread.sleep,并一直持续

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

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

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

这种方法是不可伸缩的,是为了测试云API而做的,但现在我们需要一种更具伸缩性的方法

这就是我所想的iOS调用后端,后端调用API并将结果发送回iOS(它显示一些静态屏幕只是为了让用户参与),同时它将对象放入Spring线程池执行器中。执行器每隔一秒钟点击一次API,并通过推送通知更新iOS,这将一直持续到我们从云API获得最终结果为止

这比现有的方法要好,但即使这样看起来也不可伸缩,线程池执行器在一段时间后会耗尽(使其变慢),而且thread.sleep也不是一个好的选择

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

我还在探索ApacheKafka,并试图了解它是否适合我的用例

请告诉我是否有人处理过类似的用例。

如果使用了Spring 4.2(或更新版本),则可以在这里与一起使用

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

public class APIResult extends ApplicationEvent {   
    public APIResult(Object result) { 
        super(source);      
    } 
}
接下来为发布为
apireult

@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
}
@组件
公共类MyScheduled{
私有最终应用程序ventpublisher publisher;
私有列表标记=新的ArrayList();
@自动连线
public MyScheduled(ApplicationEventPublisher发布者){
this.publisher=publisher;
}
@计划(initialDelay=1000,fixedRate=5000)//根据需要修改
public void callAPIForResult(){
//调用API并获取每个令牌的结果。。。。
this.publisher.publishEvent(新的apireult(result));
}
//方法来添加和删除令牌
}
整个流程应该如下所示

  • 应用程序向API提交请求并收集相应的令牌
  • 令牌被传递给定时服务以获取结果
  • 在下一次运行中,计划服务迭代可用令牌并调用API以获取结果(如果结果可用,则发布事件,否则继续)
  • 已注册的侦听器截获已发布的事件;自行处理结果或委托(如适用)
  • 这种方法将透明地获取结果,而不会干扰业务逻辑,同时利用标准框架特性,即。调度和异步事件发布与处理

    虽然我还没有测试过,但它应该可以工作,至少给出了如何实现的想法。该设置使用Spring boot ver进行测试<代码>1.5.1.版本由Spring的
    4.3.6.版本支持

    如果需要更多信息,请在评论中告知


    引用-Spring中的应用程序事件()

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

    您是否考虑过使用消息队列系统(ActiveMQ)。使用使用者和生产者,您可以让API在队列上生成消息,让使用者运行以检查消息何时到达,然后在客户端上执行必要的操作。不确定这对您的实例有多实际。。。只要在这里吐痰就行了。可以使用WebSocket并在java后端完成api请求时推送到客户端。卡夫卡在这里可能有道理。你说它不可伸缩,但你测试过吗?Java可以毫无问题地处理1000个线程,特别是空闲线程。如果您的服务器也在做其他事情,您可能会发现线程数量可能不是第一个瓶颈,但可能是内存消耗或CPU负载。云提供商是否提供了一个没有令牌的API,只是等待它返回?因为这样,您就可以使用标准API进行异步调用,而不会占用线程。@john16384我们希望有大量的客户,如果我们让线程长时间打开,我们可能会缺少线程,是的,正确的内存消耗也是一个问题。没有一个云提供商没有这个选项。谢谢你的回复!!谢谢你的评论。问题