Springboot2吞吐量优化的一些解决方案

优化吞吐量目前我能想到的有 3 点。

  • Docker 隔离

  • 异步执行

  • 增加内嵌 Tomcat 的最大连接数

Docker 隔离就不说了,很简单,先来看一下异步执行吧,很多人做异步执行的时候都写的千奇百怪的,其实 JDK 8 本身有一个非常好用的 Future 类——CompletableFuture。

先大概说一下 CompletableFuture 的用法

@AllArgsConstructor
public class AskThread implements Runnable{
    private CompletableFuture<Integer> re = null;

    public void run() {
        int myRe = 0;
        try {
            myRe = re.get() * re.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(myRe);
    }

    public static void main(String[] args) throws InterruptedException {
        final CompletableFuture<Integer> future = new CompletableFuture<>();
        new Thread(new AskThread(future)).start();
        //模拟长时间的计算过程
        Thread.sleep(1000);
        //告知完成结果
        future.complete(60);
    }
}

在该示例中,启动一个线程,此时 AskThread 对象还没有拿到它需要的数据,执行到 myRe = re.get() * re.get() 会阻塞。我们用休眠 1 秒来模拟一个长时间的计算过程,并将计算结果告诉 future 执行结果,AskThread 线程将会继续执行。

执行结果:

3600   (此处是一个整数)

public class Calc {
    public static Integer calc(Integer para) {
        try {
            //模拟一个长时间的执行
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return para * para;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        final CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> calc(50))
                .thenApply((i) -> Integer.toString(i))
                .thenApply((str) -> "\"" + str + "\"")
                .thenAccept(System.out::println);
        future.get();
    }
}

CompletableFuture.supplyAsync 方法构造一个 CompletableFuture 实例,在 supplyAsync() 方法中,它会在一个新线程中,执行传入的参数。在这里它会执行 calc() 方法,这个方法可能是比较慢的,但这并不影响 CompletableFuture 实例的构造速度,supplyAsync() 会立即返回。而返回的 CompletableFuture 实例就可以作为这次调用的契约,在将来任何场合,用于获得最终的计算结果。supplyAsync 用于提供返回值的情况,CompletableFuture 还有一个不需要返回值的异步调用方法 runAsync(Runnable runnable), 一般我们在优化 Controller 时,使用这个方法比较多。这两个方法如果在不指定线程池的情况下,都是在 ForkJoinPool.common 线程池中执行,而这个线程池中的所有线程都是 Daemon(守护)线程,所以,当主线程结束时,这些线程无论执行完毕都会退出系统。

运行结果:

"2500"    (由于流式计算,此处是字符串)

这样,我们就可以在我们的 Controller 要异步执行的代码写成一个方法,放到 CompletableFuture 中,比如

CompletableFuture.runAsync(() ->
   this.afterBetProcessor(betRequest,betDetailResult,appUser,id)
);

最后就是增加内嵌 Tomcat 的最大连接数,此处只针对 Springboot 2 的,Springboot 1.x 的是不同的,请勿使用。

首先在资源文件中注释掉 Server 下的配置

#server:
#  port: 8005
#  servlet:
#    context-path: /api-g

写一个专门的 tomcat 的配置类

@Configuration
public class TomcatConfig {
    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory tomcatFactory = new TomcatServletWebServerFactory();
        tomcatFactory.addConnectorCustomizers(new MyTomcatConnectorCustomizer());
        tomcatFactory.setPort(8005);
        tomcatFactory.setContextPath("/api-g");
        return tomcatFactory;
    }
    class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
        public void customize(Connector connector) {
            Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
            //设置最大连接数               
            protocol.setMaxConnections(20000);
            //设置最大线程数               
            protocol.setMaxThreads(2000);
            protocol.setConnectionTimeout(30000);
        }
    }

}

经过以上的优化,Controller 的吞吐量大概可以提升 2 到 3 倍。


作者:算法之名

来源链接:

https://my.oschina.net/u/3768341/blog/3001731

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值