ααααΆααα½αα’αααααΆααα’ααααααΆ αααααΆαααααΆαααΈααΈαα αααα»ααααααΈ Quarkus!
αα
αααα’αα·αααα Java microservices ααΆααααΌαααΆαααααΏααΆααΆααΉαααΆαα
αα
αααα»αααααααΆααααα’α·αααααα·α
ααΎαααΉααα·αα·αααααΎααα·ααΆαααΆα αα·αααααααΆααααα’α·αα’αααΈααααααα Quarkus ααΆαααα Spring APIs ααΎααααΈαααα αΆαα’αααα’αα·αααααα Spring ααΈααααααααΎααααΆαα MicroProfile API αα
αααα»αααΆαααΆααααα
αΆααααααααααα½αααα αααααΆαααα ααΎαααΉααααααααααα MicroProfile APIs αααααΆααααααααααααααΆααα’αααα’αα·αααααα Spring αα
ααααααααΎα microservicesα
α ααα»α’αααΈααΆαααΆ Quarkus? ααΈαα½α αααααΊααΆααΆααααααααΌαααααααααΆαα αααααΊααΆααααα»αα‘αΎααα·ααααααααααααααααα·ααΌαααΆαααααΆααααααΌαααΆαα½ααα
αααα»α MicroProfile API, Spring API αα·α Java APIs αααααααα αααααααΌαααΆαα’αα»αααααααααααΎααΆααααααααΆαααα½αααα»αααααα mvn quarkus:dev α ααΈααΈααα·α
αΆαααΆαα
αααα»α
ααΎαααΉααα·ααααα’α·αα’αααΈ MicroProfile αα αααα ααΈαα½αα’αααα’αα·αααααα Spring α±αααααααΈααααααααα½αααα’αΆα ααααΎ Spring APIs ααΆαα½α MicroProfile APIs αα αααα»α Quarkus α
αα»αααΊααα αα·α Kubernetes
ααΎααααΈαααααΆα’ααααααααα±ααααΆαααα ααΎαααΉααααααααααααααα·αααααΆαααααα·ααααααααααΆαααΆαααααα
ααΈαααα
Quarkus αααααα
ααΆα α»αααααα ααααααααααΎ Kubernetes ααΆααα·ααΆααΆαααΆαααααααΆαααααα Quarkus αα·αααααΎααααααααα Java αααα»αααααΈααααα»αααΆαααααααααααΆαααααααΌαααΆαα’αα»αααααα ααααα·ααααααα·ααΆ Kubernetes αααα½αα―αα ααΆααΆαααΈ 1 αααααααΌααααααΈααααΆαααααΎααααααα»αααΆααααΆα Kubernetes αα·αααααααααα Java ααααααΆαααααααΎαααα’αααα’αα·αααααα Spring α
ααΆααΆαααΈ 1. αααααΈααααΆαααααΎααααααα»αααΆααααΆα Java frameworks αα·α Kubernetes α
αα»αααΆαα
αααααααΎααα·ααΆααααΌααααααααΈ
Kubernetes
ααΆαααααΎαααααΆαααα
α’ααΌααΈ
ααααα DNS
ααΆααααααβαα
ααΆαααααααα
ααΆαααααααα
ααΆααααααααααααα·ααΆααααΌα
ααααααα
ααΆαααααααααααααΈ/α’αΆααααααΆαα
αααα»ααα»αααααΆα
ααααααΌ (ααΆαα’αα·αα·αα)
ααααΆαααα, α§ααααααααα½ααα·αα·αααααΆαα
αααα (αααααααΆααααΆαααΈααα)
ααΆαα ααααα αα·αααααΎαααΆαααΌαααΈα§ααΆα ααα
αα
αααα»αα’ααααααααααΎααααα
αα
ααΎ
Spring Framework APIs
ααΆαα αΆαααααα αΌαααΆαα’αΆααααα
Quarkus ααΆαααααα½ααα
Π
ααΆααΆα 2. α§ααΆα αααααααΆαααααΎααααΆαα Spring DI APIs αααααΆααααα
αααααααα·ααα Spring DI αααααΆαααα
α§αα ααα
ααΆαα αΆαααααα αΌαααααα
public PersonSpringController(
PersonSpringRepository personRepository, // injected
PersonSpringMPService personService) { // injected
this.personRepository = personRepository;
this.personService = personService;
}
ααΆαα
αΆααααΆαααΆα
@Autowired
@RestClient
SalutationRestClient salutationRestClient;
@Value("${fallbackSalutation}")
String fallbackSalutation;
@ααΆααααααβαα
ααΆαααααααα
@Configuration
public class AppConfiguration {
@Bean(name = "capitalizeFunction")
public StringFunction capitalizer() {
return String::toUpperCase;
}
}
@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {
@Override
public String apply(String s) {
return s;
}
}
@Service
public class MessageProducer {
@Value("${greeting.message}")
String message;
public String getPrefix() {
return message;
}
}
αααααααΆααααααααΆα
α’αααααααΎααααΆαα MicroProfile ααΉαα
αΌαα
α·αααααΆ Quarkus ααΆαααα JAX-RS, MicroProfile Rest Client, JSON-P αα·α JSON-B ααΆααααΌαααααα·ααΈααα αααααα
ααααα α’αααα’αα·αααααα Spring ααΉααααα
α·αααααΆαα½αααΉαααΆαααΆααααααααΈααααα Quarkus αααααΆαα Spring Web API ααΆαα·ααα REST interfacesα αααααααα
ααΉα Spring DI ααα ααααα
α
ααααααααΆαααΆαααα Spring Web API ααΊααΎααααΈα±ααα’αααα’αα·αααααα Spring ααααΎ Spring Web APIs αααααααΆααααΆαα½α MicroProfile APIsα α§ααΆα αααααααααααααΎ Spring Web APIs αααααΆααααααααΌαααΆααααααααΌααα
αααα»αααΆααΆαααΈ 3 α αΎαααααααΆααααααα αα·αα§ααΆα αααα’αααΈαααααΆααααααα’αΆα
ααααΌαααΆαααααΎααα
αααα»αααΆααααααα Quarkus αααα α
ααΆ
ααΆααΆαααΈ 3. α§ααΆα αααααααΆαααααΎααααΆαα Spring Web APIs αααααΆααααα
αααααααα·αααααα ααααααα·ααΆααααΌααααααΆαααα
α§αα ααα
@α’ααααααα½ααα·αα·ααααααααΆα
@RequestMapping
@RestController
@RequestMapping("/person")
public class PersonSpringController {
...
...
...
}
@GetMapping
@PostMapping
@PutMapping
@ αα»ααααααΈ
@PatchMapping
@RequestParam
@RequestHeader
@MatrixVariable
@PathVariable
@CookieValue
@ααααΎαα»αααΆαααΆα
@ααααΆαααΆαααααΎααα
@ExceptionHandler
@RestControllerAdvice (ααααα)
@GetMapping(path = "/greet/{id}",
produces = "text/plain")
public String greetPerson(
@PathVariable(name = "id") long id) {
...
...
...
}
αα·αααααααα·ααΆααααΌα JPA
α’αααααααΎααααΆαα MicroProfile ααααΉαααΉααα»ααααααααα Quarkus ααΆαααα JPA αααααααΎ Hibernate ORM α ααΆααααΆαααααΉαααα’αααααΆααα’αααα’αα·αααααα Springα Quarkus ααΆααααααΆαα
αααΆααααααα αα·ααααααα Spring Data JPA ααΌαα
α α§ααΆα αααααααΆαααααΎααααΆαα Spring Data JPA APIs ααααΌαααΆααααααα±αααααα»αααΆααΆαααΈ 4 α
Π
ααΆααΆα 4. α§ααΆα αααααααΆαααααΎααααΆαα Spring Data JPA APIs α
αααααααα·ααα JPA αα·αααααααα·ααΆααααΌααααααΆαααΆαααα
α§αα ααα
ααααΆαα Crud
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
ααααΆαα
JpaRepository
PagingAndSortingRepository
public class PersonRepository extends
Repository {
Person save(Person entity);
Optional findById(Person entity);
}
αααααααααααΆαα
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
αα·ααΈααΆααααααααα½ααααααΆαααααΈ
public interface PersonRepository extends CrudRepository {
List findByName(String name);
Person findByNameBySsn(String ssn);
Optional
findByNameBySsnIgnoreCase(String ssn);
Boolean existsBookByYearOfBirthBetween(
Integer start, Integer end);
}
αααα½αααααααααα’αααααααΎααααΆαα
public interface MovieRepository
extends CrudRepository {
Movie findFirstByOrderByDurationDesc();
@Query("select m from Movie m where m.rating = ?1")
Iterator findByRating(String rating);
@Query("from Movie where title = ?1")
Movie findByTitle(String title);
}
MicroProfile APIs
ααΆαα’ααα±αα ααααααα α»α
ααΆαααΆααααααΆαα’ααα±αα
ααααααα α»αααΆαααΆααααααΆααααααΆααααΆαααααααΆααααΆααααααααΆααααΆααααΆαααααΆαααααΎαα αα·ααααααΎαααααΆααααααααααΈααααΌααααΆαααααααα’αΆα
αα»αα
α·αααααΆαα α’αααα’αα·αααααααα·ααΆααααΌαααΆαααααΎα§ααααααααααααααααΈαααααΆααααΆαα’ααα±αααα α»αα’ααααααααααΆα
αααΎαααααΆαα
ααΆααΆα 5. α§ααΆα αααααααΆαααααΎααααΆαα MicroProfile Fault Tolerance APIs αααααΆααααα
αααααααα·αααααΆαα’ααα±αααα α»ααααα MicroProfile
ααα·ααΆα
α§αα ααα
@Asynchronous
ααΆαααααα·ααααα·αααααα·ααααΆαα αααα»ααααααααα‘αΆαααΆα ααααα‘αα
@Asynchronous
@Retry
public Future<String> getSalutation() {
...
return future;
}
@Bulkhead
αααααα ααα½αααααΎαααα»ααααααααΆαααααΆα
@Bulkhead(5)
public void fiveConcurrent() {
makeRemoteCall(); //...
}
@CircuitBreaker
ααΆααααααααααααΆααααΆαααααααααΆααα αα·αααΆαααΎαα‘αΎααα·αααΈααΆααααΆααα
@CircuitBreaker(delay=500 // milliseconds
failureRatio = .75,
requestVolumeThreshold = 20,
successThreshold = 5)
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
@ααααΆααβα α»αβααβαα·α
α α αααααα·ααααΆαααα½ααααα»αααααΈαααΆααα
@Timeout(500) // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
public String fallback() {
return "hello";
}
ααααΆααΆαααααααααα αααααααΎαααΆααα
@Retry(maxRetries=3)
public String getSalutation() {
makeRemoteCall(); //...
}
α’ααααααααααααααααΆααααΆααα
@Timeout(value = 500 ) // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
ααααΆαα·αα·ααααα»αααΆα (Service Health)
αααα·ααΆ Kubernetes αααα½ααα·αα·ααααα»αααΆααααααα»ααααααααΎααααΆααααααΆαααααα·αααα ααΎααααΈα’αα»ααααΆαα±αααααα·ααΆααΌαααααΆααααα½ααα·αα·αααααααΆαααα α’αααα’αα·αααααα Spring ααΆααααααΆααααΎ HealthIndicator αα·α Spring Boot Actuator ααααΆαααααα½αα αα
αααα»α Quarkus αααα’αΆα
ααααΌαααΆαααααΎαααααααΎ MicroProfile Health αααααΆαααααΆαααΎαααααΎααΆααα·αα·αααααΆαααααααΎα ααα»ααααα’αΆα
ααααΌαααΆαααααααα
ααΆααααααααααΎααααΈαα·αα·αααααΎαααΆαααααααΎα αα·αααΆαααααααααα½ααααα»ααααααααΆαααααΆα α§ααΆα αααααααααααααΎααααΆαα MicroProfile Health APIs αααααΆααααααααΌαααΆααααααααΌααα
αααα»αααΆααΆαααΈ 6 α αΎαααααααΆαααααααααααΌαααΆααααααααΌααα
αααα»αααααα
αα Quarkus
ααΆααΆαααΈ 6α ααΆαααααΎααααΆααα§ααΆα ααααα MicroProfile Health APIs αααααΆααααα
αα»αααΆααα»αααΆα MicroProfile
ααα·ααΆα
α§αα ααα
@ααΆαααααααΎα
αααα·ααΆα
αΆααααααΎαα‘αΎααα·αααΌααααααα·ααΈααααα·αααΆααααα»α
α
ααα»α
αααα
ααα
αααΆαααΈαα 8080/αα»αααΆα/ααααααααΆαα
@Liveness
public class MyHC implements HealthCheck {
public HealthCheckResponse call() {
...
return HealthCheckResponse
.named("myHCProbe")
.status(ready ? true:false)
.withData("mydata", data)
.build();
}
@ααΆαααααααααα½α
αααα·ααΆαααααΉααα·ααααααΌαα
ααΆα
ααααα
ααΆαααααααα·ααΈαααααΆααα»αααΊααααα ααααα·αααΎααΆαα·ααα½α
ααΆαα
α
ααα»α
αααα
ααα
αααΆαααΈα: 8080 / αα»αααΆα / αα½α
ααΆαα
@Readiness
public class MyHC implements HealthCheck {
public HealthCheckResponse call() {
...
return HealthCheckResponse
.named("myHCProbe")
.status(live ? true:false)
.withData("mydata", data)
.build();
}
αααααα
αααααα·ααΈααααααααααααααααΆαααααααααααααα·ααααα·ααΆα (ααΎααααΈααΆαααΆαααΆαα’αα»αααα SLAs) α¬ααααααααα·αααααΎαααΆα (SLAs α’αΆααΈααααα)α α’αααα’αα·αααααααα·ααΆααααΌααααααααΌααααααααααααααΎ Spring Boot Actuator αα·α Micrometer α αα αααα»αααα Quarkus ααααΎ MicroProfile Metrics ααΎααααΈαααααααΌαααΆαααΆαααααααΌαααααΆα (JVM αα·αααααααααααααα·ααααα·ααΆα) αααααΆααα’αααααα (Quarkus) αα·ααααααααααααα·ααΈα MicroProfile Metrics αααααΌαα±ααααΆαα’αα»ααααααΆαααααααααααααΆααααααα JSON αα·α OpenMetrics (Prometheus) α α§ααΆα αααααααΆαααααΎααααΆαα MicroProfile Metrics API ααααΌαααΆααααααα±αααααα»αααΆααΆαααΈ 7 α
Π
ααΆααΆαααΈ 7. α§ααΆα αααααααΆαααααΎααααΆαα MicroProfile Metrics APIs α
ααααααβαα·ααα MicroProfile Metrics
ααα·ααΆα
α§αα ααα
@ ααΆαα
ααααΆαβα’αααβααΆααβααΆααβα ααα½αβααβαααβααααα»βα αααΆαβαα½αβααααΌαβααΆαβα α
@Counted(name = "fallbackCounter",
displayName = "Fallback Counter",
description = "Fallback Counter")
public String salutationFallback() {
return fallbackSalutation;
}
@ConcurrentGauge
ααααΆαβα±ααβαααααΆααβαααβααΆααβα ααα½αβααβααΆαβα α βααααβααααΆβαα βααΆααβααααα»βαααβααΆαβαααβαααααΆαα
@ConcurrentGuage(
name = "fallbackConcurrentGauge",
displayName="Fallback Concurrent",
description="Fallback Concurrent")
public String salutationFallback() {
return fallbackSalutation;
}
@ αααααΆαα
αααααΆααα§αααααα αΆαααααααΆαααααΆαααααααΆαααααααααααααα»αααααΆααααααα αααΆα
@Metered(name = "FallbackGauge",
displayName="Fallback Gauge",
description="Fallback frequency")
public String salutationFallback() {
return fallbackSalutation;
}
@αααααα
αααααΆααα§αααααα αΆαααααααΆααααααααααααα½ααα·αα·ααααααααααα α ααΌαααααααααααααα»αααααΆααααααα αααΆα
@Metered(name = "MeteredFallback",
displayName="Metered Fallback",
description="Fallback frequency")
public String salutationFallback() {
return fallbackSalutation;
}
α αααΆααααααααααααΆαααααααΆαα’αααΈαα·ααααααααααΆ αα αααααααΎααααΌαααΆαααα½αααΎααααΈαααα αΌα α¬ααα·ααααααα
@Metric
@Metered(name = "MeteredFallback",
displayName="Metered Fallback",
description="Fallback frequency")
public String salutationFallback() {
return fallbackSalutation;
}
α ααα’α»ααααα αΆααααααα·ααΈααααααααααααααΆαααΆαααααααααααααα»αααααΆααααααα αααΆα
@Timed(name = "TimedFallback",
displayName="Timed Fallback",
description="Fallback delay")
public String salutationFallback() {
return fallbackSalutation;
}
α ααα»α αααα αααααααααα
αααααΆααααααΆαααΆααααΆααα
αααααΆααααΌαααααΆα
αααααΆααααα’αααααα
αααααΆααααΆααα’ααα
α’αα·αα·αααααααΆα MicroProfile
Microservices ααΆααΉαααΆαααααααααΌα RESTful endpoints αααααααΌαααΆα APIs α’αα·αα·αααααααααΌαααααΆααΎααααΈααααΎααΆαααΆαα½αα ααΎααααΈααααΎ RESTful endpoints α’αααα’αα·αααααα Spring ααΆααααααΆααααΎ RestTemplateα Quarkus αααααααΌα MicroProfile Rest Client APIs ααΎααααΈαααααααΆααααα αΆααα α§ααΆα αααααααΆαααααΎααααΆαααααααααΌαααΆααααααα±αααααα»αααΆααΆαααΈ 8 α
Π
ααΆααΆαααΈ 8. α§ααΆα αααααααΆαααααΎααααΆαα MicroProfile Rest Client APIs α
αααααααα·αααααααα’αα·αα·αααααααΆα MicroProfile
ααα·ααΆα
α§αα ααα
@RegisterRestClient
α α»ααααααα ααα»α αααααΆαα Java αααααΆαααΆααααα αΌαααΆαααΆαααΈαααααα REST
@RegisterRestClient
@Path("/")
public interface MyRestClient {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getSalutation();
}
@RestClient
αααααΆααααΆαα’αα»ααααααα ααα»α αααααΆαααααΆαααΈαααααα REST αααααΆαααΆααααα αΌα
@Autowired // or @Inject
@RestClient
MyRestClient restClient;
ααΆαα α
α α αα α ααα»α αααα αα REST
System.out.println(
restClient.getSalutation());
mp-rest/url
αααααΆααβα ααα»α βαααα αα REST
application.properties:
org.example.MyRestClient/mp-rest/url=
http://localhost:8081/myendpoint
αααααα
αα αααα»ααααααααααααααΆααααααααααΆα αααααα ααΎα’αααα’αα·αααααα Spring ααΎαααΆαααΎααααΆααα ααα’αααΈααααααααΎ Spring APIs ααΆαα½α MicroProfile APIs αααα»α Quarkus ααΎααααΈαααααΎα microservices Java α αΎααααααΆααααα αααααααΆαα ααΆααΌααααααΈαααΎαααααααααΆαα»α RAM ααΆααααααα αααΆαα α αΎαα αΆααααααΎααα αααα»α αααα αΆααααΈααΈαα·ααΆααΈα
ααΌα
αααα’αααααΆαααααα½α
α αΎα ααααααΆαααααααα’αααΈααΆαααΆαααααααααΆαα Spring αα·α MicroProfile APIs ααααΌα
ααΆααααααΆαααΆαααααααααααΆα
αααΎααααα’αΆα
ααααΌαααΆαααααΎααα
αααα»α
ααααα: www.habr.com