Improving the performance of a Java microservice with a couple of simple tricks

Hello, Habr. For future students of the "Highload Architect" course we prepared a translation of the material.



We also invite you to an open webinar on the topic
"Replication as a Pattern of Horizontal Storage Scaling" . In the lesson, the participants, together with an expert, will disassemble replication - one of the database scaling techniques, discuss the meaning and its purpose, consider the advantages and disadvantages of various types of replication.






The great thing about microservices in Java is that they can be used to build large and complex systems from many independent components. Instead of a single app, you end up with multiple widgets or services. Components can be tested, deployed, and maintained independently of each other. So, if you remove one brick, then the building will not collapse completely.





. Java, , . , .





Spring Boot — Java. , Spring Boot-.





:





  • External-service ( ): "" , HTTP.





  • Facade-service (): , external-service . .





  • Java 8





  • Jmeter 5.3





  • Java IDE





  • Gradle 6.6.1





, , , .





External service

Spring Initializer. , :





@RestController 
public class ExternalController { 
 
 @GetMapping(“/external-data/{time}”) 
 public ExternalData getData(@PathVariable Long time){ 
 try { 
 Thread.sleep(time); 
 } catch (InterruptedException e) { 
 // do nothing 
 } 
 return new ExternalData(time); 
 } 
}
      
      



ExternalServiceApplication



. https://localhost:8543/external-data/300





Facade service

Spring Initializer. : ExternalService



ExternalServiceClient



.





ExternalService



External Service externalServiceClient



.





@Service 
public class ExternalService { 
 
 @Autowired 
 private ExternalServiceClient externalServiceClient; 
 
 public ResultData load(List<Long> times) { 
 Long start = System.currentTimeMillis(); 
 LongSummaryStatistics statistics = times 
 .parallelStream() 
 .map(time -> externalServiceClient.load(time).getTime()) 
 .collect(Collectors.summarizingLong(Long::longValue)); 
 Long end = System.currentTimeMillis(); 
 return new ResultData(statistics, (end — start)); 
 } 
}
      
      



external service ExternalServiceClient



openfeign. HTTP- OKHttp :





@FeignClient( 
name = “external-service”, 
url = “${external-service.url}”, 
configuration = ServiceConfiguration.class) 
public interface ExternalServiceClient { 
 
 @RequestMapping( 
 method = RequestMethod.GET, 
 value = “/external- data/{time}”, 
 consumes = “application/json”) 
 Data load(@PathVariable(“time”) Long time); 
}
      
      



FacadeServiceApplication



  http://localhost:8080/data/1,500,920,20000.





:





{ 
 “statistics”: { 
 “count”: 4, 
 “sum”: 1621, 
 “min”: 1, 
 “max”: 920, 
 “average”: 405.25 
 }, 
 “spentTime”: 1183 
}
      
      



Jmeter 5.3.1 perfomance-testing.jmx .





:





URL-: http://localhost:8080/data/1,500,920,200 





Jmeter .





Jmeter

. , ExternalService



parallelStream()



. Stream API ForkJoinPool



. ForkJoinPool



. . - . , ForkJoinPool



1000.





-Djava.util.concurrent.ForkJoinPool.common.parallelism=1000
      
      



Jmeter .





Jmeter

, (throughput) 6 26 . . , . (average time) 9 . , HTTP-. :





@Configuration 
public class ServiceConfiguration { 
 
 
 @Bean 
 public OkHttpClient client() 
 throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, NoSuchProviderException { 
 
 
 okhttp3.OkHttpClient client = new okhttp3.OkHttpClient.Builder() 
 .sslSocketFactory(sslContext.getSocketFactory(), trustManager) 
 .hostnameVerifier((s, sslSession) -> true) 
 .connectionPool(new ConnectionPool(2000, 10, TimeUnit.SECONDS)) 
 .build(); 
 
 OkHttpClient okHttpClient = new OkHttpClient(client); 
 
 return okHttpClient; 
 }
      
      



, 2000 HTTP- 10 .





Jmeter

: 26 71 .





10 : 6 71 / , , (maximum time) 7 . , UI.





. , Tomcat application.properties



:





server.tomcat.accept-count=80
server.tomcat.max-connections=80 
server.tomcat.max-threads=160
      
      



"Connection refused" ( ) , 160.





Jmeter

71 94 . 29%. "Connection refused". 





15 6 94 / - . , , AWS. , . — , .





Java-, . , . Java- .






"Highload Architect".





« ».








All Articles