没有人愿意承认自己是孤独的,孤独很可耻。


前言

大家好,我是GMaya。

本文是解决一个业务上访问慢的痛点,整体是这样的。有一个汇总微服务a,现在需要调用其他b,c,d等多个微服务接口,然后整体将数据进行整合。如果是串行调用,每个接口需要1秒,那么三个接口也要3秒了。。。

设计思路

使用CompleteFuture方法,并行调用,然后数据汇总整合。

具体实现

模拟场景:

1、pay支付微服务有三个接口,每个接口中模拟访问过慢的场景。
2、order分别串行方式和并行方式进行调用。

pay微服务代码


/**
 * @ Description   :  支付接口
 * @ Author        :  GMaya
 * @ CreateDate    :  2020/3/16 10:53
 * @ Version       :  1.0
 */
@RestController
@Slf4j
public class PayController {

    @RequestMapping("/getPay1")
    public JSONObject getPay1() {
        log.info("getPay=============");
        try {
            Thread.sleep(1000L);
        }; catch (InterruptedException e) {
            throw new RuntimeException(e);
        };
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code",200);
        jsonObject.put("data","支付成功1");
        log.info("getPay========返回结果为1:{};",jsonObject);
        // 返回支付信息
       return jsonObject;
    };
    @RequestMapping("/getPay2")
    public JSONObject getPay2() {
        log.info("getPay=============");
        try {
            Thread.sleep(2000L);
        }; catch (InterruptedException e) {
            throw new RuntimeException(e);
        };
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code",200);
        jsonObject.put("data","支付成功2");
        log.info("getPay========返回结果为2:{};",jsonObject);
        // 返回支付信息
       return jsonObject;
    };
    @RequestMapping("/getPay3")
    public JSONObject getPay3() {
        log.info("getPay=============");
        try {
            Thread.sleep(3000L);
        }; catch (InterruptedException e) {
            throw new RuntimeException(e);
        };
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code",200);
        jsonObject.put("data","支付成功3");
        log.info("getPay========返回结果为3:{};",jsonObject);
        // 返回支付信息
       return jsonObject;
    };

};

order微服务代码


/**
 * @ Description   :  订单接口接口
 * @ Author        :  GMaya
 * @ CreateDate    :  2020/3/16 11:03
 * @ Version       :  1.0
 */
@RestController
@Slf4j
public class OrderController {

    @Autowired
    private PayClient payClient;

    /**
     *
     * @return
     */
    @RequestMapping("/addOrder")
    public JSONObject addOrder() {
        log.info("order...............");
        TimeInterval timer = DateUtil.timer();
        // 访问支付微服务1
        JSONObject pay = payClient.getPay1();
        long interval = timer.interval();
        log.info("pay......{};.........{};", interval, pay);
        // 访问支付微服务2
        JSONObject pay2 = payClient.getPay2();
        long interval2 = timer.interval();
        log.info("pay2......{};.........{};", interval2, pay2);
        // 访问支付微服务1
        JSONObject pay3 = payClient.getPay3();
        long interval3 = timer.interval();
        log.info("pay3......{};.........{};", interval3, pay3);

        // 模拟.模拟.模拟
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 200);
        jsonObject.put("data", "订单添加成功");
        long interval4 = timer.interval();
        log.info("pay4......{};.........", interval4);
        return jsonObject;
    };

    /**
     * CompletableFuture 异步调用 并行处理
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @RequestMapping("/addOrder2")
    public JSONObject addOrder2() throws ExecutionException, InterruptedException {
        log.info("order2...............");
        TimeInterval timer = DateUtil.timer();

        CompletableFuture<JSONObject> payFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                return payClient.getPay1();
            }; catch (Exception e) {
                throw new RuntimeException(e);
            };
        };);
        CompletableFuture<JSONObject> payFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                return payClient.getPay2();
            }; catch (Exception e) {
                throw new RuntimeException(e);
            };
        };);
        CompletableFuture<JSONObject> payFuture3 = CompletableFuture.supplyAsync(() -> {
            try {
                return payClient.getPay3();
            }; catch (Exception e) {
                throw new RuntimeException(e);
            };
        };);

        JSONObject pay1 = payFuture1.get();
        long interval = timer.interval();
        log.info("pay1......{};.........{};", interval, pay1);
        JSONObject pay2 = payFuture2.get();
        long interval2 = timer.interval();
        log.info("pay2......{};.........{};", interval2, pay2);
        JSONObject pay3 = payFuture3.get();
        long interval3 = timer.interval();
        log.info("pay3......{};.........{};", interval3, pay3);

        // 模拟.模拟.模拟
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 200);
        jsonObject.put("data", "订单添加成功");
        long interval4 = timer.interval();
        log.info("pay4......{};.........", interval4);
        return jsonObject;
    };
};

PayClient 代码

/**
 * @description   :  支付接口声明
 * @author        :  GMaya
 * @createDate    :  2020/3/16 14:28
 * @version       :  1.0
 */
@FeignClient(name = "pay")
public interface PayClient {
    @RequestMapping("/getPay1")
    JSONObject getPay1();
    @RequestMapping("/getPay2")
    JSONObject getPay2();
    @RequestMapping("/getPay3")
    JSONObject getPay3();
};

调用结果:

串行调用结果展示:


整体下来6秒多,因为中间Thread.sleep 了6秒。

并行调用结果展示:



整体下来3秒多,因为中间Thread.sleep最大时间为3秒。

效果已经很明显了。

思考总结

在开发中,不要光想着实现这个功能,有时候还要考虑一下有没有其他的实现方式,或者偶然看到一篇文章,给了一个启发,有可能就解决了一个项目中的痛点。

启发已经有了, 具体更复杂的CompleteFuture使用方法就看jdk中的api吧。

最后

如果这篇文章对您有所帮助,或者有所启发的话,求点赞、收藏,您的支持是我坚持写作最大的动力。