首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何并发进行API调用

如何并发进行API调用
EN

Stack Overflow用户
提问于 2019-07-21 21:11:32
回答 2查看 194关注 0票数 2

我有大约40万个员工id,.I一次可以传递一个员工id。

如何使用线程并行调用PI,从而提高性能。需要一些指点。

saveInDatabase()方法将对象保存在数据库表中。

代码语言:javascript
复制
private void callApi(List<Long> employeeList, HttpEntity<String> requestEntity) {
        Long employeeId;
        for (Long i : employeeList) {

            employeeId = i;// url

            String url = "http://dummy.restapiexample.com/api/v1/employee/" + employeeId;

            ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity,
                    String.class);

            saveInDatabase(responseEntity);

        }
    }
EN

回答 2

Stack Overflow用户

发布于 2019-07-21 21:33:23

直接使用Thread API很容易出错,因为它的级别较低。

使用parallelStream()可能很有趣,但它也可能是一个问题,因为处理后的流可能会消耗应用程序可用的所有CPU核心。

这意味着您的应用程序的其他HTTP客户端请求可能最近才会得到处理。

And note also that the number of threads used in parallelStream() is a JVM implementation detail and doesn't make part of the public API

允许指定池中可用线程数量的ExecutorService API看起来是一个更好/更健壮的替代方案。

Spring Boot提供了一个包装它的built-in feature

您可以将要调用的单个任务提取到方法中,如下所示:

代码语言:javascript
复制
@Async
public Future<ResponseEntity<String>> getEmployee(long employeeId,  HttpEntity<String> requestEntity) {

       String url = "http://dummy.restapiexample.com/api/v1/employee/" + employeeId;
       ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity,
                String.class);
       return new AsyncResult<ResponseEntity<String>>(responseEntity);
   }

现在叫它:

代码语言:javascript
复制
private void callApi(List<Long> employeeList, HttpEntity<String> requestEntity) {

        // Do async calls and store futures in a List
        List<Future<ResponseEntity<String>>> futures = new ArrayList<>();
        for (Long id : employeeList) {
            futures.add(getEmployee(id, requestEntity));    
        }

        // Then process list of future 
        for (Future<ResponseEntity<String>> future : futures) 
            try{ 
                saveInDatabase(future.get());
               }
               catch(Exception e){ 
                  //handle the exception
              }

         }    
    }

顺便说一下,在循环中执行saveInDatabase()操作不是一种正确的方法。

您希望批处理数据库插入,而不是批处理,因为您有许多数据库插入要做。类似于:

代码语言:javascript
复制
private void callApi(List<Long> employeeList, HttpEntity<String> requestEntity) {

  List<ResponseEntity<String>> responseEntities = 
        employeeList.stream()
                    .map(id -> getEmploye(id))
                    .map(future -> {
                          try{return future.get();}
                            catch(Exception e){ 
                                //handle the exception
                                }
                             }
                     )
                    .collect(toList()); 
   saveInDatabase(responseEntities);            
}

要使@Asynch功能正常工作,必须在应用程序的@Configuration类上添加@EnableAsync

您还可以选择使用适合您需要的池/队列配置来定义Executor bean。注意:如果您没有定义Spring,Executor将创建一个SimpleAsyncTaskExecutor并使用它(它通过任务创建一个Thread,并且不重用它们)。

例如:

代码语言:javascript
复制
@SpringBootApplication
@EnableAsync
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("GithubLookup-");
        executor.initialize();
        return executor;
    }


}
票数 3
EN

Stack Overflow用户

发布于 2019-07-21 21:16:36

您可以使用parallelStream()并发调用API。

代码语言:javascript
复制
List<ResponseEntity<String>> result = employeeList.parallelStream()
            .map(id->restTemplate.exchange("http://dummy.restapiexample.com/api/v1/employee/"+id, HttpMethod.GET, requestEntity, String.class))
            .collect(Collectors.toList());

result.forEach(entity->saveInDatabase(entity));

但要注意,parallelStream()可能会耗尽您的应用程序可用的CPU核心。如果应用程序不只执行此任务,而是设计为服务于其他请求,则可能会出现问题。

因此,按照@davidxxx建议,使用saveAll进行批量插入

代码语言:javascript
复制
saveAll(result)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57133548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档