ืฉืืื ืืืืื, ืื ื ืืคืืกื ืืฉืืืฉื ืืกืืจืช Quarkus!
ืืืฉืจ ืืคืชืืื ืฉืืจืืชื ืืืงืจื ืฉื Java, ืืืืื ืื ืื
ืืคืืจืื ืงืื ืืืชืจ, ืชืืืื ื ืืื ืืช ืืืืงืฃ ืืืคืจืืื ืฉื ืืืืคื ืฉืื Quarkus ืชืืื ืืืืฉืงื API ืฉื Spring ืืื ืืืจืืืช ืืืคืชืื Spring ืืืฆื ืืืฉืชืืฉ ื-MicroProfile API ืืขืืืื ืืืืืืืืืช ืฉืืื. ืืืืจ ืืื ื ืกืงืืจ ืืช ืืืฉืงื ื-API ืฉื MicroProfile, ืฉืืืืฉืืื ืขืืืจ ืืคืชืื Spring ืืขืช ืืฆืืจืช ืืืงืจื-ืฉืืจืืชืื.
ืืื ืงืืืงืืก? ืจืืฉืืช, ืืื ืงืืืื ืื, ืืืืืจ, ืืขืื ื ืืืืฉ ืืืืืืืืช ืฉื ืื ืฉืื ืื ื-MicroProfile API, Spring API ืืืืฉืงื API ืืืจืื ืฉื Java, ืฉืืชืืฆืขืช ืืคืงืืื ืืืช ืืืื: mvn quarkus:dev. ืฉื ืืช, ื ืืฉื ื
ืื ื ืคืจื ืขื MicroProfile, ืืืื ืืขืืืจ ืืืคืชืื Spring ืืืืื ืืืฆื ืื ืืืืืื ืืืฉืชืืฉ ืืืืฉืงื Spring API ืขื ืืืฉืงื API ืฉื MicroProfile ื-Quarkus.
ืืืืืืช ื-Kubernetes
ืืื ืืฉืืืจ ืขื ืืืืจ ืื ืคืฉืื, ื ืกืงืืจ ืืื ืจืง ืืช ืืืืืืื ืืืืืืื ืฉื ืชืืืื.
ืื ืงืืืงืืก
ืืืกืืฃ, ืขื ืืื ืืชืืงืืืช ื-Kubernetes ืืกืืืืช ืคืจืืกืช ืืืขื, Quarkus ืืื ื ืืฉืชืืฉ ืืืกืืจืืช Java ืืืงืจืื ืืื ืืืืฉืืช ืคืื ืงืฆืืื ืืืืช ืืืื ืืจืืช ืคืืืคืืจืืช Kubernetes ืขืฆืื. ืืืื 1 ืืกืคืงืช ืืคื ืฉื ืืืชืืื ืืคืื ืงืฆืืื ืืืช ืืื Kubernetes ืืืื ืืกืืจืืช Java ืืืคืืกืืืช ืืืฉืืฉืืช ืืคืชืื Spring.
ืืืื 1. ืืคื ืฉื ืืชืืื ืคืื ืงืฆืืื ืืืช ืืื ืืกืืจืืช Java ื-Kubernetes.
ืคืื ืงืฆืืื ืื
ืืืฃ ืืืื ืืกืืจืชื
ืงืืืจื ื
ืืืืื ืฉืืจืืช
ืืืจืืงื
DNS
ืชึฐืฆืึผืจึธื
ืชืฆืืจืช ืขื ื ืืืื
ืืืืจืช ืืคืืช/ืกืืืืช
ืืืืื ืขืืืกืื
ืกืจื (ืฆื ืืืงืื)
ืฉืืจืืช, ืืงืจ ืฉืืคืื (ืฆื ืืฉืจืช)
ืงืืืคืืืฆืื ืืืจืฆื ืฉื ืืงืื ืืืืืืื
ืืืืืจ ืื ืื ื ืืชืืืืกืื
ืืืฉืงื API ืฉื Spring Framework
ืืืจืงืช ืชืืืช
Quarkus ืชืืื ืืืืืื ืฉื
ะ
ืืืื 2. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ื ืชืืืื ืฉื Spring DI.
ืชืืื ืืช 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. ืืืืื ื-Spring DI, ืืืืจื ืืขืืงืจืืช ืฉื ืชืืืืช Spring Web API ืืื ืืืคืฉืจ ืืืคืชืื Spring ืืืฉืชืืฉ ืืืืฉืงื Spring Web ืืฉืืืื ืขื ืืืฉืงื API ืฉื MicroProfile. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื ื-API ืื ืชืืืื ืฉื Spring Web ืืกืืคืงืืช ืืืืื 3, ืื ืืชื ืืืฆืื ืืืืข ืืืืืืืืช ื ืืกืคืืช ืื ืืฉื ืื ืืืืจืื ืฉื Quarkus ืื ืงืจื
ืืืื 3. ืืืืืืืช ืืฉืืืืฉ ื-Spring Web APIs ืื ืชืืืื.
ืชืืื ืืช ืืื ืืจื ื ื ืชืืืืช ืฉื ืืืื
ืืืืืืืช
@ RestController
@ืืงืฉืช ืืืคืื
@RestController
@RequestMapping("/person")
public class PersonSpringController {
...
...
...
}
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@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 ืืืืฆืขืืช ORM Hibernate. ืืฉ ืื ืืืฉืืช ืืืืืช ืืืคืชืื Spring: Quarkus ืชืืื ืืืขืจืืช ืืืกืืืื ื ืคืืฆืื ืฉื Spring Data JPA. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ืฉื Spring Data JPA ื ืชืืืื ืืืืื 4.
ะ
ืืืื 4. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ื ืชืืืื ืฉื Spring Data JPA.
ืชืืื ืืช Spring Data JPA ื ืชืืืืช
ืืืืืืืช
CrudRository
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
Repository
ืืืืจ Jpa
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);
}
ืืืฉืงื API ืฉื MicroProfile
ืกืืืื ืืช ืืชืงืืืช
ืืื ืื ืืกืืืื ืืช ืชืงืืืช ืืฉืืืื ืืืื ืืื ืืขืช ืืฉืืื ืืืืจืืื ืืืืฆืืจืช ืืจืืืืงืืืจืืช ืืืงืจื-ืฉืืจืืช ืืืื ืืช. ืืคืชืื ืงืคืืฆืื ืืฉืชืืฉืื ืืืคืกืงืื ืืกืืืืืช ืชืงืืืช ืืืจ ืฉื ืื ืจืืืช.
ืืืื 5. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ื ืชืืืื ืฉื MicroProfile Fault Tolerance.
ืชืืื ืืช ืกืืืื ืืช ืชืงืืืช ืฉื MicroProfile
ืชืืืืจ
ืืืืืืืช
@ืืกืื ืืจืื ื
ืืืฆืืข ืืืืืื ืืฉืจืฉืืจ ื ืคืจื
@Asynchronous
@Retry
public Future<String> getSalutation() {
...
return future;
}
@ืืืืฆื
ืืืื ืืช ืืกืคืจ ืืืงืฉืืช ืื-ืืื ืืช
@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(); //...
}
ืฉืืจืืชื ืืืืงื (ืฉืืจืืช ืืจืืืืช)
ืคืืืคืืจืืืช Kubernetes ืขืืงืืืช ืืืจ ืชืงืื ืืช ืืืืืืืช ืืืืฆืขืืช ืฉืืจืืชืื ืืืืืืื. ืืื ืืืคืฉืจ ืืคืืืคืืจืื ืืืกืืกืืช ืื ืืจ ืฉืืจืืชืื, ืืคืชืื Spring ืืฉืชืืฉืื ืืืจื ืืื ื-HealthIndicator ืืืชืื ืืืฉืืช ืื-Spring Boot Actuator. ื-Quarkus, ื ืืชื ืืขืฉืืช ืืืช ืืืืฆืขืืช MicroProfile Health, ืืฉืจ ืืืจืืจืช ืืืื ืืืฆืขืช ืืืืงืช ืืืื ืืืช, ืื ื ืืชื ืืืืืืจ ืืืช ืื ืฉืชืืืืง ืื-ืืื ืืช ืืช ืืคืขืืืืช ืืืืืื ืืช. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื ื-API ืื ืชืืืื ืฉื MicroProfile Health ืืกืืคืงืืช ืืืืื 6, ืืืืืข ื ืืกืฃ ืืกืืคืง ืืืืจืื ืฉื Quarkus
ืืืื 6: ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ื ืชืืืื ืฉื MicroProfile Health.
ืชืืื ืืช MicroProfile Health
ืชืืืืจ
ืืืืืืืช
@ืืืืช
ืืชืืื ืืืืฉ ืฉื ืืคืืืคืืจืื ื ืืฉื ืืืฉืืื ืืืืืืช
ื ืงืืืช ืกืืื:
ืืืจื:8080/health/live
@Liveness
public class MyHC implements HealthCheck {
public HealthCheckResponse call() {
...
return HealthCheckResponse
.named("myHCProbe")
.status(ready ? true:false)
.withData("mydata", data)
.build();
}
@ื ึฐืืึนื ืึผืช
ืืคืืืคืืจืื ืื ืชืฉืื ืชืขืืืจื ืืืืฉืืืื ืืืืืืื ืื ืืื ืื ืืืื ื
ื ืงืืืช ืกืืื:
ืืืจื:8080/health/ready
@Readiness
public class MyHC implements HealthCheck {
public HealthCheckResponse call() {
...
return HealthCheckResponse
.named("myHCProbe")
.status(live ? true:false)
.withData("mydata", data)
.build();
}
ืืืืื
ืืืฉืืืื ืืกืคืงืื ืืืืื ืืืืจืืช ืชืคืขืืืืืช (ืืื ืืคืงื ืขื SLAs ืืืฆืืขืื) ืื ืืืืจืืช ืื ืชืคืขืืืืืช (SLAs ืขืกืงืืืช). ืืคืชืื Spring ืืกืคืงืื ืืืืื ืืืืฆืขืืช Spring Boot Actuator ืืืืงืจืืืืจ. ืืชืืจื, Quarkus ืืฉืชืืฉ ื-MicroProfile Metrics ืืื ืืกืคืง ืืืื ืืกืืก (JVM ืืืขืจืืช ืืคืขืื), ืืืื ืกืคืงืื (Quarkus) ืืืืื ืืืฉืืืื. MicroProfile Metrics ืืืจืฉ ืฉืืืืฉืื ืชืืื ืืชืื ืืืช ืคืื ืฉื JSON ื-OpenMetrics (Prometheus). ืืืืืืืช ืืฉืืืืฉ ื-MicroProfile Metrics API ื ืืชื ืืช ืืืืื 7.
ะ
ืืืื 7. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ืฉื MicroProfile Metrics.
ืชืืื ืืช ืืืื MicroProfile
ืชืืืืจ
ืืืืืืืช
@ื ืกืคืืจ
ืืฆืืื ืืื ื ืืื ื ืฉืกืืคืจ ืืช ืืกืคืจ ืืคืขืืื ืฉื ืงืจื ืืืืืืงื ืืืขืจ
@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 Rest Client
ืฉืืจืืชื ืืืงืจื ืืกืคืงืื ืืขืชืื ืงืจืืืืช ื ืงืืืืช ืงืฆื RESTful ืฉืืืจืฉืืช ืืืฉืงื API ืชืืืืื ืฉื ืืงืื ืืขืืื ืืืชื. ืืื ืืืฉืชืืฉ ืื ืงืืืืช ืงืฆื ืฉื RESTful, ืืคืชืื Spring ืืฉืชืืฉืื ืืืจื ืืื ื-RestTemplate. Quarkus ืืฆืืขื ืืืฉืงื API ืฉื MicroProfile Rest Client ืืื ืืคืชืืจ ืืขืื ืื, ืืืืืืืืช ืืฉืืืืฉ ืืื ื ืืชื ืืช ืืืืื 8.
ะ
ืืืื 8. ืืืืืืืช ืืฉืืืืฉ ืืืืฉืงื API ืฉื MicroProfile Rest Client.
ืชืืื ืืช ืืงืื MicroProfile Rest
ืชืืืืจ
ืืืืืืืช
@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 API ืขื ืืืฉืงื API ืฉื MicroProfile ื-Quarkus ืืื ืืคืชื ืฉืืจืืชื ืืืงืจื ืฉื Java ืืืืืจ ืืื ืืงืืคื ืืืชื ืืงืื ืืื ืืจื ืืงืืจื ืฉืืืกื ืืืืช ืืื-ืืืื ืฉื ืืืืจืื RAM ืืืฉืืง ื- ืขื ืืื ืฉื ืืืคืืืช ืฉื ืืืช.
ืืคื ืฉืืืจ ืืื ืช, ืืืืข ื ืืกืฃ ืขื ืชืืืื ืืืืฉืงื ื-Spring ื-MicroProfile, ืืื ืื ืืืืข ืฉืืืืฉื ืจื ืืืจ, ื ืืชื ืืืฆืื ื-
ืืงืืจ: www.habr.com