前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Springboot2吞吐量优化的一些解决方案

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

作者头像
算法之名
发布2019-08-20 09:57:45
1.9K0
发布2019-08-20 09:57:45
举报
文章被收录于专栏:算法之名

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

  • Docker隔离
  • 异步执行
  • 增加内嵌Tomcat的最大连接数

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

先大概说一下CompletableFuture的用法

代码语言:javascript
复制
@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 (此处是一个整数)

代码语言:javascript
复制
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中,比如

代码语言:javascript
复制
CompletableFuture.runAsync(() ->
   this.afterBetProcessor(betRequest,betDetailResult,appUser,id)
);

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

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

代码语言:javascript
复制
#server:
#  port: 8005
#  servlet:
#    context-path: /api-g

写一个专门的tomcat的配置类

代码语言:javascript
复制
@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倍。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档