優化吞吐量目前我能想到的有3點。web
Docker隔離就不說了,很簡單,先來看一下異步執行吧,不少人作異步執行的時候都寫的千奇百怪的,其實JDK 8自己有一個很是好用的Future類——CompletableFuture。api
先大概說一下CompletableFuture的用法tomcat
@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線程將會繼續執行。app
執行結果:異步
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(守護)線程,因此,當主線程結束時,這些線程不管執行完畢都會退出系統。this
運行結果:線程
"2500" (因爲流式計算,此處是字符串)server
這樣,咱們就能夠在咱們的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倍。