Quarkus如何集成MicroProfile和Spring

大家好,还有Quarkus系列的第三篇文章! (顺便说一下,注册并进入我们的网络研讨会“ 这是Quarkus-Kubernetes本机Java框架 ”,该会议将于5月27日举行。我们将展示如何从头开始或转移现成的解决方案。)



在开发Java微服务时,人们通常相信Eclipse MicroProfileSpring引导是独立的独立API。默认情况下,程序员通常会使用他们惯用的API,因为学习新框架和运行时组件会花费很多时间。今天,我们将尝试简化一些针对Spring开发人员的流行MicroProfile API的开发。并演示如何同时使用Spring API和Quarkus的新有用功能

如果要更详细一点,我们将首先查看Quarkus如何支持Spring API的范围和细节,以向Spring开发人员展示如何在日常工作中使用MicroProfile API。然后,我们将讨论MicroProfile API,这对于Spring开发人员在创建微服务时很有用。

为什么是夸夸斯?首先,这是实时编码,即对MicroProfile API,Spring API和其他Java API的任何更改的自动重新加载,只需使用以下命令即可执行:mvn quarkus:dev。其次,在我们的示例中考虑Person服务(使用本机GraalVM映像从Spring,MicroProfile和JPA API编译成二进制文件)仅需0.055秒即可启动,并在RESTful应用程序的端点占用约90 MB的RAM(RSS)。而且,它的编译本身仅用一个命令执行:mvn package -Pnative。

我们不会详细介绍MicroProfile,而只会尝试帮助Spring开发人员了解如何在Quarkus中将Spring API与MicroProfile API一起使用。

容器和Kubernetes


为了不使本文过多,我们仅在此处查看Kubernetes支持的高级方面,因为这很重要。 Quarkus被定位为Kubernetes的Java堆栈,它旨在最大程度地减少Java应用程序和服务的内存消耗和启动时间,并因此提高它们在主机上的放置密度并降低总体成本。

Quarkus还支持 Kubernetes 自动生成资源,并在Kubernetes和Red Hat OpenShift平台上提供部署指南。另外,Quarkus自动生成创建容器所需的Dockerfile.jvm(JVM打包)和Dockerfile.native(本地二进制打包)文件。

最后,以Kubernetes作为目标部署环境为重点,当在Kubernetes平台本身的级别上实现类似功能时,Quarkus不使用Java框架。表1显示了Kubernetes的功能对应关系以及Spring开发人员使用的典型Java框架的映射。

表1. Java框架和Kubernetes的功能映射图。
功能性传统春靴Kubernetes
服务发现尤里卡域名解析
组态春季云配置配置地图/秘密
负载均衡功能区(客户端)服务,复制控制器(服务器端)

编译并运行示例中的代码


在本文中,我们引用一个示例项目,其中共享Spring和MicroProfile API甚至同一Java类。可以编译此示例中的代码并从命令行运行,有关更多详细信息,请参见README.md文件。

Spring Framework API


依赖注入


Quarkus支持各种上下文和依赖注入(CDI) API和Spring依赖注入(Spring DI)API。如果您使用MicroProfile,Java EE和Jakarta EE,则您已经熟悉CDI。另一方面,Spring开发人员可以使用Quarkus Extension for Spring DI API来确保与Spring DI的兼容性。表2中给出了使用受支持的Spring DI API 的示例。我们示例中

项目同时使用CDI和Spring Dependency Injection。有关此主题的更多信息和示例,请参见《 Quarkus指南》(称为《Spring DI指南》)

表2.使用受支持的Spring DI API的示例。
支持的Spring DI功能
Constructor Injection
public PersonSpringController(
   PersonSpringRepository personRepository,  // injected      
   PersonSpringMPService personService) {    // injected
      this.personRepository = personRepository;
      this.personService = personService;
}
Field Injection
Autowired
Value
@Autowired
@RestClient
SalutationRestClient salutationRestClient;

@Value("${fallbackSalutation}")
String fallbackSalutation;
Bean
@Configuration
@Configuration
public class AppConfiguration {
   @Bean(name = "capitalizeFunction")
   public StringFunction capitalizer() {
      return String::toUpperCase;
   }
}
Component
@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {
   @Override
   public String apply(String s) {
      return s;
   }
}
Service
@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作为其主要的Web编程模型。Spring开发人员将对Quarkus中最近对Spring Web API的支持(特别是REST接口)感到满意。与Spring DI相似,支持Spring Web API的主要目标是让Spring开发人员将Spring Web API与MicroProfile API一起使用。表3中给出了使用受支持的Spring Web API的示例,有关该主题的更多信息和示例可以在Quarkus指南(称为Spring Web Guide)中找到

表3.使用受支持的Spring Web API的示例。
支持的Spring Web功能例子
@RestController
@RequestMapping
@RestController
@RequestMapping("/person")
public class PersonSpringController {
   ...
   ...
   ...
}
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@RequestHeader
@MatrixVariable
@PathVariable
@CookieValue
@RequestBody
@ResponseStatus
@ExceptionHandler
@RestControllerAdvice (partial)
@GetMapping(path = "/greet/{id}",
   produces = "text/plain")
   public String greetPerson(
   @PathVariable(name = "id") long id) {
   ...
   ...
   ...
}

Spring Data JPA


MicroProfile用户还希望Quarkus使用Hibernate ORM支持JPA。对于Spring开发人员来说也有个好消息:Quarkus支持通用注释和Spring Data JPA类型。表4中给出了使用受支持的Spring Data JPA API 的示例。在我们示例
项目中,使用了Spring Data JPA API ,并且在Quarkus指南(称为Spring Data JPA Guide)中提供了更多信息

表4.使用受支持的Spring Data JPA API的示例。
支持的Spring Data JPA功能例子
储库
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- MicroProfile


(Fault tolerance)


容错设计对于防止级联故障和构建健壮的微服务体系结构至关重要。春季开发人员已经将Hystrix断路器用于容错已有多年了但是,Hystrix尚未更新很长时间,但是MicroProfile的Fault Tolerance现在正在积极开发中,并且已经在生产中使用了数年。因此,为了提高Quarkus中服务的可靠性,建议使用MicroProfile Fault Tolerance API,其示例在表5中给出。有关此的更多信息,请参见Quarkus Fault Tolerance Guide

表5.使用受支持的MicroProfile Fault Tolerance API的示例。
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(); //...
}
@Fallback

@Timeout(500) // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

public String fallback() {
   return "hello";
}
Retry

@Retry(maxRetries=3)
public String getSalutation() {
   makeRemoteCall(); //...
}
Timeout

@Timeout(value = 500 )   // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

(Service Health)


Kubernetes平台使用特殊服务监视容器的运行状况。为了使基础平台可以监视服务,Spring开发人员通常使用自定义的HealthIndicator和Spring Boot Actuator。在Quarkus中,可以使用MicroProfile Health完成此操作,默认情况下,MicroProfile Health执行活动检查,但可以将其配置为同时检查活动和准备情况。表6中显示了使用受支持的MicroProfile Health API的示例,《 Quarkus Health Guide》中提供了更多信息

表6.使用受支持的MicroProfile Health API的示例。
MicroProfile运行状况功能描述例子
@Liveness

Endpoint:
host:8080/health/live
@Liveness
public class MyHC implements HealthCheck {
  public HealthCheckResponse call() {

   ...
   return HealthCheckResponse
     .named("myHCProbe")
     .status(ready ? true:false)
     .withData("mydata", data)
     .build();  
}
@Readiness

Endpoint:
host: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 Metrics提供基本指标(JVM和操作系统),供应商指标(Quarkus)和应用程序指标。 MicroProfile Metrics要求实现支持JSON和OpenMetrics(Prometheus)输出格式。表7中提供了使用MicroProfile Metrics API 的示例

我们示例项目中, MicroProfile Metrics用于提供应用程序指标。有关更多信息,请参见Quarkus Metrics Guide

7. API- MicroProfile Metrics.
MicroProfile Metrics
@Counted
counter-,
@Counted(name = "fallbackCounter", 
  displayName = "Fallback Counter", 
  description = "Fallback Counter")
public String salutationFallback() {
   return fallbackSalutation;
}
@ConcurrentGauge
gauge-,
@ConcurrentGuage(
  name = "fallbackConcurrentGauge", 
  displayName="Fallback Concurrent", 
  description="Fallback Concurrent")
public String salutationFallback() {
   return fallbackSalutation;
}
@Gauge
gauge-,
@Metered(name = "FallbackGauge",
   displayName="Fallback Gauge",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}
@Metered
meter-,
@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}
Metric
, ,
@Metric
@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}
Timed
,
@Timed(name = "TimedFallback",
   displayName="Timed Fallback",
   description="Fallback delay")
public String salutationFallback() {
   return fallbackSalutation;
}

端点度量标准(Metrics Endpoints)

度量标准应用程序localhost:8080 /度量标准/应用程序
基本度量标准localhost:8080 /度量标准/基本
供应商度量标准localhost:8080 /度量标准/供应商
所有度量标准localhost:8080 /度量标准

MicroProfile Rest客户端


微服务通常提供需要适当客户端API的RESTful端点。为了使用RESTful端点,Spring开发人员通常使用RestTemplate。Quarkus还提供了用于解决此问题的MicroProfile Rest Client API,其使用示例在表8中给出。

我们示例项目中,RESTful端点使用是通过MicroProfile Rest Client执行的。有关此主题的更多信息和示例,请参见《 Quarkus Rest客户端指南》

表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 /网址
指定REST端点
application.properties:
org.example.MyRestClient/mp-rest/url=
   http://localhost:8081/myendpoint

摘要


在这个对Spring开发人员主要有用的博客中,我们简要介绍了如何在Quarkus中结合使用Spring API和MicroProfile API来开发Java微服务,然后将它们编译为本地二进制代码,从而节省了数百兆的RAM。并在几毫秒内开始。

如您所知,可以在Quarkus手册中找到有关支持Spring和MicroProfile API的其他信息,以及许多其他有用的信息

All Articles