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- .
« ».