çããããã«ã¡ã¯ãQuarkus ã·ãªãŒãºã® XNUMX çªç®ã®æçš¿ã§ãã
Java ãã€ã¯ããµãŒãã¹ãéçºããå Žåã次ã®ããã«èããããããšããããããŸãã
ããå°ã詳ãã説æãããšããŸããQuarkus ã Spring API ããµããŒãããç¯å²ãšè©³çŽ°ãèŠãŠãSpring éçºè
ã«æ¥åžžã®äœæ¥ã§ MicroProfile API ã䜿çšããæ¹æ³ã瀺ããŸãã 次ã«ãSpring éçºè
ããã€ã¯ããµãŒãã¹ãäœæãããšãã«åœ¹ç«ã€ MicroProfile API ã玹ä»ããŸãã
ãªãã¯ã©ãŒã«ã¹ãªã®ãïŒ ãŸããããã¯ã©ã€ã ã³ãŒãã£ã³ã°ã§ããã€ãŸããMicroProfile APIãSpring APIãããã³ãã®ä»ã® Java API ã®å€æŽãèªåçã«åããŒãããŸããããã¯ãmvn quarkus:dev ãšãã XNUMX ã€ã®ã³ãã³ãã ãã§å®è¡ãããŸãã 第äºã«ãã§è°è«ãããŠãã
Spring éçºè ã Quarkus ã® MicroProfile API 㧠Spring API ã䜿çšããæ¹æ³ãç解ããããšãç®çãšããŠãMicroProfile ã«ã€ããŠã¯è©³ãã説æããŸããã
ã³ã³ãããšKubernetes
ãã®èšäºãç°¡æœã«ããããã«ãããã§ã¯ãµããŒãã®é«ã¬ãã«ã®åŽé¢ã®ã¿ã説æããŸãã
ã¯ã©ãŒã«ã¹ã
æåŸã«ãQuarkus ã¯ã¿ãŒã²ãã ãããã€ã¡ã³ãç°å¢ãšã㊠Kubernetes ã«çŠç¹ãåœãŠãŠãããããåæ§ã®æ©èœã Kubernetes ãã©ãããã©ãŒã èªäœã®ã¬ãã«ã§å®è£ ãããå Žåã«ã¯ Java ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŸããã è¡š 1 ã¯ãKubernetes ãš Spring éçºè ã䜿çšããå žåç㪠Java ãã¬ãŒã ã¯ãŒã¯éã®æ©èœç察å¿é¢ä¿ã®ãããã瀺ããŠããŸãã
è¡š 1. Java ãã¬ãŒã ã¯ãŒã¯ãš Kubernetes ã®éã®æ©èœã®å¯Ÿå¿é¢ä¿ã®ãããã
æ©èœç
äŒçµ±çãªã¹ããªã³ã°ããŒã
Kubernetes
ãµãŒãã¹ã®çºèŠ
Eureka
DNS
ã
æ¥ã®ã¯ã©ãŠãæ§æ
æ§æããã/ã·ãŒã¯ã¬ãã
ããŒããã©ã³ã·ã³ã°
ãªãã³ïŒã¯ã©ã€ã¢ã³ãåŽïŒ
ãµãŒãã¹ãã¬ããªã±ãŒã·ã§ã³ ã³ã³ãããŒã©ãŒ (ãµãŒããŒåŽ)
ãµã³ãã«ã®ã³ãŒããã³ã³ãã€ã«ããŠå®è¡ãã
ãã®èšäºã§åç
§ããã®ã¯ã
Spring ãã¬ãŒã ã¯ãŒã¯ API
äŸåæ§æ³šå ¥
Quarkus ã¯ããŸããŸãªæ©èœããµããŒãããŠããŸã
Ð
è¡š 2. ãµããŒããããŠãã Spring DI API ã®äœ¿çšäŸã
ãµããŒããããŠãã 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;
}
}
Webãã¬ãŒã ã¯ãŒã¯
MicroProfile ãŠãŒã¶ãŒã¯ãQuarkus ãäž»èŠãª Web ããã°ã©ãã³ã° ã¢ãã«ãšã㊠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 API ã®äœ¿çšæ¹æ³ã®äŸãè¡š 3 ã«ç€ºããŸãããã®ãããã¯ã«é¢ãã詳现ãšäŸã¯ãQuarkus ãã¥ãŒããªã¢ã«ã§åç
§ã§ããŸãã
è¡š 3. ãµããŒããããŠãã Spring Web API ã®äœ¿çšäŸã
ãµããŒããããŠãã Spring Web æ©èœ
äŸ
@RestController
@RequestMapping
@RestController
@RequestMapping("/person")
public class PersonSpringController {
...
...
...
}
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@ãªã¯ãšã¹ãããããŒ
@MatrixVariable
@ãã¹å€æ°
@CookieValue
@RequestBody
@ResponseStatus
@ExceptionHandler
@RestControllerAdvice (éšåç)
@GetMapping(path = "/greet/{id}",
produces = "text/plain")
public String greetPerson(
@PathVariable(name = "id") long id) {
...
...
...
}
æ¥ã®ããŒã¿JPA
MicroProfile ãŠãŒã¶ãŒã¯ãQuarkus ã Hibernate ORM ã䜿çšã㊠JPA ããµããŒãããŠããããšãé«ãè©äŸ¡ããã§ãããã Spring éçºè
ã«ãšã£ãŠã¯æå ±ããããŸããQuarkus ã¯äžè¬ç㪠Spring Data JPA ã¢ãããŒã·ã§ã³ãšåããµããŒãããŠããŸãã ãµããŒããããŠãã Spring Data JPA API ã®äœ¿çšäŸãè¡š 4 ã«ç€ºããŸãã
Ð
è¡š 4. ãµããŒããããŠãã Spring Data JPA API ã®äœ¿çšäŸã
ãµããŒããããŠãã Spring Data JPA æ©èœ
äŸ
Crudãªããžããª
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
å庫
Jpaãªããžããª
ããŒãžã³ã°ãšãœãŒããªããžããª
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
ãã©ãŒã«ããã¬ã©ã³ã¹
ãã©ãŒã«ã ãã¬ã©ã³ã¹æ§é ã¯ãé£éçãªé害ãé²æ¢ããä¿¡é Œæ§ã®é«ããã€ã¯ããµãŒãã¹ ã¢ãŒããã¯ãã£ãäœæããããã«éåžžã«éèŠã§ãã Spring éçºè
ã¯é·å¹Žã«ããããã©ãŒã«ã ãã¬ã©ã³ã¹ã®ããã«ãµãŒããã ãã¬ãŒã«ãŒã䜿çšããŠããŸããã
è¡š 5. ãµããŒããããŠãã MicroProfile Fault Tolerance API ã®äœ¿çšäŸã
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(); //...
}
ãµãŒãã¹ã®ç¢ºèª (Service Health)
Kubernetes ãã©ãããã©ãŒã ã¯ãç¹å¥ãªãµãŒãã¹ã䜿çšããŠã³ã³ãããŒã®ç¶æ
ãç£èŠããŸãã åºç€ãšãªããã©ãããã©ãŒã ããµãŒãã¹ãç£èŠã§ããããã«ããããã«ãSpring éçºè
ã¯éåžžãã«ã¹ã¿ã ã® HealthIndicator ãš Spring Boot Actuator ã䜿çšããŸãã Quarkus ã§ã¯ããã㯠MicroProfile Health ã䜿çšããŠå®è¡ã§ããŸããMicroProfile Health ã¯ããã©ã«ãã§æŽ»æ§ãã§ãã¯ãå®è¡ããŸããã掻æ§ãšæºåç¶æ³ãåæã«ãã§ãã¯ããããã«æ§æã§ããŸãã ãµããŒããããŠãã MicroProfile Health API ã®äœ¿çšæ¹æ³ã®äŸãè¡š 6 ã«ç€ºããŸããè¿œå æ
å ±ã¯ Quarkus ããã¥ã¢ã«ã«èšèŒãããŠããŸãã
è¡š 6: ãµããŒããããŠãã MicroProfile Health API ã®äœ¿çšäŸã
MicroProfile Health æ©èœ
説æ
äŸ
@Liveness
ãã©ãããã©ãŒã ã¯å€±æããã³ã³ããåã¢ããªã±ãŒã·ã§ã³ãåèµ·åããŸã
çµç¹ïŒ
ãã¹ã:8080/å¥åº·/ã©ã€ã
@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();
}
ã¡ããªã¯ã¹
ã¢ããªã±ãŒã·ã§ã³ã¯ãéçšç®ç (ããã©ãŒãã³ã¹ SLA ãç£èŠãããã) ãŸãã¯ééçšç®ç (ããžãã¹ SLA) ã®ããããã®ã¡ããªãã¯ãæäŸããŸãã Spring éçºè ã¯ãSpring Boot Actuator ãš Micrometer ã䜿çšããŠã¡ããªã¯ã¹ãæäŸããŸãã 次ã«ãQuarkus 㯠MicroProfile ã¡ããªã¯ã¹ã䜿çšããŠãããŒã¹ã©ã€ã³ ã¡ããªã¯ã¹ (JVM ããã³ãªãã¬ãŒãã£ã³ã° ã·ã¹ãã )ããã³ã㌠ã¡ããªã¯ã¹ (Quarkus)ãããã³ã¢ããªã±ãŒã·ã§ã³ ã¡ããªã¯ã¹ãæäŸããŸãã MicroProfile Metrics ã§ã¯ãå®è£ ã JSON ããã³ OpenMetrics (Prometheus) åºå圢åŒããµããŒãããŠããå¿ èŠããããŸãã MicroProfile Metrics API ã®äœ¿çšäŸãè¡š 7 ã«ç€ºããŸãã
Ð
è¡š 7. MicroProfile Metrics API ã®äœ¿çšäŸã
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
泚éä»ããªããžã§ã¯ãã®åŒã³åºãé »åºŠãç£èŠããã¡ãŒã¿ãŒã»ã³ãµãŒã瀺ããŸã
@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 ã¯ã©ã€ã¢ã³ã
ãã€ã¯ããµãŒãã¹ã¯ãå€ãã®å Žåã察å¿ããã¯ã©ã€ã¢ã³ã API ã®æäœãå¿ èŠãšãã RESTful ãšã³ããã€ã³ããæäŸããŸãã RESTful ãšã³ããã€ã³ãã䜿çšããã«ã¯ãSpring éçºè ã¯éåžžãRestTemplate ã䜿çšããŸãã Quarkus ã¯ããã®åé¡ã解決ããããã« MicroProfile Rest Client API ãæäŸããŠããŸãããã®äœ¿çšäŸãè¡š 8 ã«ç€ºããŸãã
Ð
è¡š 8. MicroProfile Rest ã¯ã©ã€ã¢ã³ã API ã®äœ¿çšäŸã
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 ãš Quarkus ã® MicroProfile API ã䜿çšã㊠Java ãã€ã¯ããµãŒãã¹ãéçºããããããã€ãã£ã ãã€ã㪠ã³ãŒãã«ã³ã³ãã€ã«ããŠæ°çŸã¡ã¬ãã€ãã® RAM ãç¯çŽããæ°ããªç§ã®åé¡ã§ãã
ãã§ã«ç解ãããŠããããã«ãSpring ããã³ MicroProfile API ã®ãµããŒãã«é¢ãã詳现æ
å ±ãããã³ãã®ä»ã®å€ãã®åœ¹ç«ã€æ
å ±ã«ã€ããŠã¯ã次㮠URL ãåç
§ããŠãã ããã
åºæïŒ habr.com