调用第三方接口优化点
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.concurrent.*;
/*
https://www.bilibili.com/video/BV1YV41147wb?p=7
b栈上面学习到的。
链接:https://www.bilibili.com/video/BV1YV41147wb?p=7
当我们去请求第三方的接口时。我们每次请求只需要传入一个id拿到对应的数据。
但如果我们请求量很大。可能将第三方搞崩溃。
如果第三方有提供批量接口。 我们可以将请求的id先存在本地。 然后10ms,批量请求一次。
结果放入CompletableFuture里面。 然后通过其get()方法,complete() 唤醒get()。等待结果的返回。
注意点:
1. 批量接口有返回一个全局的id。 这样可以对应的单id的请求。
2.如果没有返回某一个id的值。一直ConcurrentLinkedQueue.get(), 感觉最好加一个过期时间。
*/
@Service
public class NextService {
ConcurrentLinkedQueue<Request> queue = new ConcurrentLinkedQueue<>();
class Request<T> {
Integer id;
String res;
CompletableFuture<T> future;
}
public String get(Integer id) throws ExecutionException, InterruptedException {
// 原: 每次调第三方,单个接口
// return "第三方接口" + id;
CompletableFuture<String> completableFuture = new CompletableFuture();
Request<String> request = new Request();
request.id = id;
request.future = completableFuture;
queue.add(request);
return completableFuture.get();
}
@PostConstruct
public void dealQueueTask(){
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
scheduledThreadPoolExecutor.scheduleWithFixedDelay(()->{
if(queue.size() == 0){
return;
}
// 批量拿出数据 拼装批量参数 批量请求
/*
放入结果
Request poll = queue.poll();
poll.future.complete("结果");*/
}, 0, 10, TimeUnit.MILLISECONDS);
}
}
hystrix 请求合并
依赖 springboot、maven、jdk版本有要求
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类
@EnableHystrix
请求合并配置
import app.cn.in.StringService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
@Service
public class StringServiceImpl implements StringService {
@Override
@HystrixCollapser(batchMethod = "more",
// 控制请求合并的作用域,默认是REQUEST,就是不会跨越多个请求会话的,只在当前用户请求中合并多次请求为 //批处理请求。这里改成GLOBAL,就是可以跨越request context,合并不同用户的请求为一次批处理请求。
scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
// 此属性设置创建批处理后触发其执行的毫秒数。
collapserProperties = {@HystrixProperty(name ="timerDelayInMilliseconds",value = "100"),
// 此属性设置在触发批处理执行之前批处理中允许的最大请求数。
@HystrixProperty(name ="maxRequestsInBatch",value = "10")
// requestCache.enabled
//此属性指示是否为HystrixCollapser.execute()和HystrixCollapser.queue()调用启用请求高速缓存。
})
public Future<String> one(Integer id) {
return null;
}
@Override
@HystrixCommand
public List<String> more(List<Integer> ids) {
System.out.println(ids + "=================== ");
if(CollectionUtils.isEmpty(ids)){
return null;
}
List<String> res = new ArrayList<>(ids.size());
ids.forEach(id->{
res.add(id + UUID.randomUUID().toString());
});
return res;
}
}
测试
@RequestMapping("/order")
@RestController
public class StrController {
@Resource
private StringService stringService;
@GetMapping("/one")
public String getOrders() throws ExecutionException, InterruptedException {
this.stringService.one(1);
this.stringService.one(2);
Future<String> one = this.stringService.one(3);
return one.get();
}
效果是调用one方法 多个请求会合并去请求 more方法