Mejorar el rendimiento de un microservicio de Java con un par de trucos simples

Hola, Habr. Para los futuros alumnos del curso "Highload Architect" preparamos una traducción del material.



También lo invitamos a un seminario web abierto sobre el tema
"La replicación como patrón de escalamiento de almacenamiento horizontal" . En la lección, los participantes, junto con un experto, desensamblarán la replicación, una de las técnicas de escalado de la base de datos, discutirán el significado y su propósito, considerarán las ventajas y desventajas de varios tipos de replicación.






Lo mejor de los microservicios en Java es que se pueden usar para construir sistemas grandes y complejos a partir de muchos componentes independientes. En lugar de una sola aplicación, terminas con múltiples widgets o servicios. Los componentes se pueden probar, implementar y mantener de forma independiente entre sí. Entonces, si quita un ladrillo, el edificio no colapsará por completo.





. 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