Using the Cassandra Client

Apache Cassandra® 是一款免费且开源的分布式宽列式存储、NoSQL 数据库管理系统,旨在跨多个商用服务器处理海量的数据,并提供高可用性,且无单点故障。 在本指南中,我们将了解如何让您的 REST 服务使用 Cassandra 数据库。 :iokays-category: quarkus :iokays-path: modules/ROOT/pages/_includes/platform-include.adoc :keywords: Quarkus, 中文文档, 编程技术

此扩展由第三方开发并属于 Quarkus Platform。

Prerequisites

include::./_includes/prerequisites.adoc[]* 正在运行的 Apache Cassandra, DataStax Enterprise (DSE) 或 DataStax Astra 数据库;或者,干净的 Docker 安装。

Architecture

本快速入门指南显示了如何使用 Cassandra Quarkus extension构建 REST 应用程序,此应用程序允许您连接到 Apache Cassandra、DataStax Enterprise (DSE) 或 DataStax Astra 数据库,使用 DataStax Java driver

本指南还将使用 DataStax Object Mapper– 一个功能强大的 Java 到 CQL 映射框架,通过避免您手动编写 CQL 查询的麻烦,极大地简化了您的应用程序数据访问层代码。

在本快速入门指南中构建的应用程序非常简单:用户可以使用表单在列表中添加元素,然后更新项目列表。浏览器和服务器之间所有信息都采用 JSON 格式,并且这些元素存储在 Cassandra 数据库中。

Solution

我们建议您按照以下部分中的说明进行操作,并逐步创建应用程序。但是,您可以直接转到完成的示例。

该解决方案位于 Cassandra Quarkus 扩展 GitHub 存储库的 quickstart directory中。

Creating a Blank Maven Project

首先,创建一个新的 Maven 项目,并复制 `pom.xml`中存在的 `quickstart`目录中的文件。

`pom.xml`将导入您所需的所有 Quarkus 扩展和依赖项。

Creating the Data Model and Data Access Objects

在此示例中,我们将创建一个应用程序来管理水果列表。

首先,让我们创建我们的数据模型(由 `Fruit`类表示),如下所示:

@Entity
@PropertyStrategy(mutable = false)
public class Fruit {

    @PartitionKey
    private final String name;

    private final String description;

    public Fruit(String name, String description) {
      this.name = name;
      this.description = description;
    }
  // getters, hashCode, equals, toString methods omitted for brevity
}

如上所述,我们正在使用 DataStax Object Mapper。换句话说,我们不会手动编写我们的 CQL 查询;相反,我们将使用一些注释对我们的数据模型进行注释,映射器会在下面生成适当的 CQL 查询。

这就是 `Fruit`类使用 `@Entity`注释的原因:此注释将其标记为映射到 Cassandra 表的 entity class。它的实例不会主动持久到 Cassandra 数据库,或从其检索。此处,表名称将从类名称 `fruit`中推断。

此外,`name`字段表示 Cassandra 分区键,因此我们使用来自 Object Mapper 库的另一个注释 `@PartitionKey`对其进行注释。

实体类通常需要有一个默认的无参数构造函数,除非它们使用 `@PropertyStrategy(mutable = false)`注释(此处即采用这种方式)。

下一步是创建一个 DAO(数据访问对象)接口,此接口将管理`Fruit`实体的实例:

@Dao
public interface FruitDao {
  @Update
  void update(Fruit fruit);

  @Select
  PagingIterable<Fruit> findAll();
}

此接口公开将在我们的 REST 服务中使用的操作。同样,注释`@Dao`来自 DataStax Object Mapper,它还将自动为您生成此接口的一个实现。

另请注意 findAll 方法的特殊返回类型 PagingIterable: 它是驱动程序返回的结果集的基本类型。

最后,让我们创建一个 Mapper 接口:

@Mapper
public interface FruitMapper {
  @DaoFactory
  FruitDao fruitDao();
}

@Mapper 注解是 DataStax Object Mapper 识别的另一个注解。amapper 负责构建 DAO 实例——本例中,我们的 mapper 正在构建我们唯一的 DAO FruitDao 的实例。

将 mapper 接口视为 DAO bean 的工厂。如果你打算在自己的代码中构建和注入特定的 DAO bean,那么首先必须在 @Mapper 接口中为其添加 @DaoFactory 方法。

@DaoFactory 方法名称无关紧要。

@DaoFactory 方法应返回以下类型的 bean:

  • 任何 @Dao 注解的接口,例如 FruitDao

  • 任何 @Dao 注解的接口的 CompletionStage,例如 CompletionStage&lt;FruitDao&gt;

  • 任何 @Dao 注解的接口的 Uni,例如 Uni&lt;FruitDao&gt;

Uni 是 Mutiny 库中的一个类型,它是 Quarkus 使用的响应式编程库。有关详情,请参见下方的“响应式编程”部分。

Generating the DAO and mapper implementations

你可能已经猜到了,我们不会实现上述接口。相反,Object Mapper 将为我们生成此类实现。

Object Mapper 由 2 部分组成:

  1. (编译时)注释处理器,它扫描类路径中注释有 @Mapper@Dao@Entity 的类,并为它们生成代码和 CQL 查询;

  2. 一个包含执行生成查询的逻辑的运行时模块。

因此,启用 Object Mapper 需要两个步骤:

  1. 声明 cassandra-quarkus-mapper-processor 注解处理器。使用 Maven,可以通过以下方式修改项目 pom.xml 文件中的编译器插件配置来完成此操作:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.10.1</version>
  <configuration>
    <source>${java.version}</source>
    <target>${java.version}</target>
    <annotationProcessorPaths>
      <path>
        <groupId>com.datastax.oss.quarkus</groupId>
        <artifactId>cassandra-quarkus-mapper-processor</artifactId>
        <version>${cassandra-quarkus.version}</version>
      </path>
    </annotationProcessorPaths>
  </configuration>
</plugin>

使用 Gradle,可以通过向 build.gradle 文件添加以下行来完成此操作:

annotationProcessor "com.datastax.oss.quarkus:cassandra-quarkus-mapper-processor:${cassandra-quarkus.version}"

验证你是否正在启用正确的注解处理器!Cassandra 驱动程序附带称为 java-driver-mapper-processor 的 Object Mapper 注解处理器。但是,Cassandra Quarkus 扩展也附带其自己的注解处理器: cassandra-quarkus-mapper-processor ,它比驱动程序的注解处理器有更多功能。此注解处理器是唯一适用于 Quarkus 应用程序的注解处理器,因此请检查正在使用的是否是此注解处理器。此外,切勿同时使用两个注解处理器。

  1. 在项目的 pom.xml 文件中声明编译范围内的 java-driver-mapper-runtime 依赖项,如下所示:

<dependency>
  <groupId>com.datastax.oss</groupId>
  <artifactId>java-driver-mapper-runtime</artifactId>
</dependency>

尽管这个模块称为“运行时”,但它必须在编译范围内声明。

如果正确设置了项目,现在你应该能够毫无错误地编译它,并且你应该能看到生成的代码位于 target/generated-sources/annotations 目录(如果你使用 Maven 的话)。你不必熟悉生成的代码,因为它主要是与数据库交互的内部机制。

Creating a service & JSON REST endpoint

现在让我们创建一个 FruitService 为我们应用程序的业务层,以及从 Cassandra 数据库存储/加载水果。

@ApplicationScoped
public class FruitService {

  @Inject FruitDao dao;

  public void save(Fruit fruit) {
    dao.update(fruit);
  }

  public List<Fruit> getAll() {
    return dao.findAll().all();
  }
}

注意服务如何注入一个 FruitDao 实例。由于生成的实现,DAO 实例会自动注入。

Cassandra Quarkus 扩展允许你在组件中注入下列任何 Bean:

  • 项目中所有用 @Mapper 注解的接口。

  • 你可以注入任意用 @Mapper 注解的接口的 CompletionStageUni

  • 任何由 @DaoFactory 方法返回的 Bean(有关可能的 Bean 类型,请参阅上文)。

  • QuarkusCqlSession Bean:此应用程序范围内的单例 Bean 是你连接 Cassandra 客户端的主要入口点;它是一个专门的 Cassandra 驱动程序会话实例,有几个针对 Quarkus 量身定制的方法。仔细阅读其 Java 文档!

  • 你还可以注入 CompletionStage&lt;QuarkusCqlSession&gt;Uni&lt;QuarkusCqlSession&gt;

在我们的示例中,FruitMapperFruitDao 都可以在任何地方注入。我们选择在 FruitService 中注入 FruitDao

最后缺失的部分是公开 GET 和 POST 方法的 REST API:

@Path("/fruits")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class FruitResource {

  @Inject FruitService fruitService;

  @GET
  public List<FruitDto> getAll() {
    return fruitService.getAll().stream().map(this::convertToDto).collect(Collectors.toList());
  }

  @POST
  public void add(FruitDto fruit) {
    fruitService.save(convertFromDto(fruit));
  }

  private FruitDto convertToDto(Fruit fruit) {
    return new FruitDto(fruit.getName(), fruit.getDescription());
  }

  private Fruit convertFromDto(FruitDto fruitDto) {
    return new Fruit(fruitDto.getName(), fruitDto.getDescription());
  }
}

注意 FruitResource 如何自动注入一个 FruitService 实例。

一般不建议在 REST API 和数据访问层之间使用同一实体对象。这些层实际上应该分离,并使用不同的 API,以允许每个 API 独立于另一个 API 发展。这就是我们的 REST API 使用不同对象的原因:FruitDto 类——DTO 一词代表“数据传输对象”。该 DTO 对象会在 HTTP 消息中自动转换为 JSON,反之亦然:

public class FruitDto {

  private String name;
  private String description;

  public FruitDto() {}

  public FruitDto(String name, String description) {
    this.name = name;
    this.description = description;
  }
  // getters and setters omitted for brevity
}

将 JSON 转换为 JSON 或反之亦然的过程由 Quarkus REST(原名 RESTEasy Reactive)扩展自动完成,它包含在本指南的 pom.xml 文件中。如果你想将其手动添加到应用程序,请将以下片段添加到应用程序的 pom.xml 文件中:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-rest-jackson</artifactId>
</dependency>

JSON 序列化层使用的 DTO 类需要有一个默认的无参数构造函数。

从 DTO 转换为 JSON 的过程对我们来说是自动处理的,但我们仍然必须从 Fruit 转换为 FruitDto ,反之亦然。这必须手动完成,这就是为什么我们在 FruitResource 中声明了两个转换方法:convertToDtoconvertFromDto

在我们的示例中,FruitFruitDto 非常相似,所以你可能会想为什么不在所有地方都使用 Fruit 。但是在实际情况下,看到 DTO 和实体具有非常不同的结构并不少见。

Connecting to the Cassandra Database

Connecting to Apache Cassandra or DataStax Enterprise (DSE)

要配置的主要属性是:contact-points,用于访问 Cassandra 数据库;local-datacenter,这是驱动程序所必需的;以及——可选择——要绑定的键空间。

示例配置如下所示:

quarkus.cassandra.contact-points={cassandra_ip}:9042
quarkus.cassandra.local-datacenter={dc_name}
quarkus.cassandra.keyspace={keyspace}

在这个示例中,我们使用在本地主机上运行的单个实例,并且包含我们数据的键空间是 k1

quarkus.cassandra.contact-points=127.0.0.1:9042
quarkus.cassandra.local-datacenter=datacenter1
quarkus.cassandra.keyspace=k1

如果你的集群需要纯文本身份验证,你必须还提供更多两个设置: usernamepassword

quarkus.cassandra.auth.username=john
quarkus.cassandra.auth.password=s3cr3t

Connecting to a DataStax Astra Cloud Database

当连接到 DataStax Astra 时,应该提供所谓的 secure connect bundle,而不是提供一个联系点和一个数据中心,这应该指向 Astra 安全连接束文件的一个有效路径。你可以在 Astra 网页控制台中下载你的安全连接束。

你还需要提供一个用户名和密码,因为 Astra 集群总是需要身份验证。

适用于 DataStax Astra 的一个示例配置应该是这样的:

quarkus.cassandra.cloud.secure-connect-bundle=/path/to/secure-connect-bundle.zip
quarkus.cassandra.auth.username=john
quarkus.cassandra.auth.password=s3cr3t
quarkus.cassandra.keyspace=k1

Advanced Driver Configuration

你可以使用 application.confapplication.json 文件配置其他 Java 驱动程序设置。它们需要位于你的应用程序的类路径中。所有设置都将自动传递给底层驱动程序配置机制。在 application.properties 中用 quarkus.cassandra 前缀定义的设置将优先于在 application.confapplication.json 中定义的设置。

要查看全部设置列表,请参阅 driver settings reference

Running a Local Cassandra Database

默认情况下,Cassandra 客户端被配置为访问端口 9042 上的本地 Cassandra 数据库(默认 Cassandra 端口)。

确保设置 quarkus.cassandra.local-datacenter 匹配你的 Cassandra 集群的数据中心。

如果你不知道本地数据中心的名称,可以通过运行以下 CQL 查询找到这个值: SELECT data_center FROM system.local

如果你想使用 Docker 运行 Cassandra 数据库,你可以使用以下命令在后台启动一个:

docker run --name local-cassandra-instance -p 9042:9042 -d cassandra

接下来,你需要创建你的应用程序将使用的键空间和表。如果你使用 Docker,运行以下命令:

docker exec -it local-cassandra-instance cqlsh -e "CREATE KEYSPACE IF NOT EXISTS k1 WITH replication = {'class':'SimpleStrategy', 'replication_factor':1}"
docker exec -it local-cassandra-instance cqlsh -e "CREATE TABLE IF NOT EXISTS k1.fruit(name text PRIMARY KEY, description text)"

你也可以使用 CQLSH 实用程序交互地询问你的数据库:

docker exec -it local-cassandra-instance cqlsh

Testing the REST API

在项目根目录中:

  • 运行 mvn clean package,然后 java -jar ./target/cassandra-quarkus-quickstart-*-runner.jar 以启动应用程序;

  • 或者更好的是,以开发模式运行应用程序: mvn clean quarkus:dev

现在,你可以使用 curl 命令与底层的 REST API 交互。

要创建一个水果:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"name":"apple","description":"red and tasty"}' \
  http://localhost:8080/fruits

要检索水果:

curl -X GET http://localhost:8080/fruits

Creating a Frontend

现在,让我们添加一个简单的网页来与我们的 FruitResource 进行交互。

Quarkus 会自动提供位于 META-INF/resources 目录下的静态资源。在 src/main/resources/META-INF/resources 目录中,添加一个 fruits.html 文件,其中包含 this file 中的内容。

你现在可以与你的 REST 服务进行交互:

  • 如果您还没有这样做,请使用 mvn clean quarkus:dev 启动您的应用程序;

  • 将浏览器指向 http://localhost:8080/fruits.html

  • 通过表单向列表中添加新水果。

Reactive Programming with the Cassandra Client

QuarkusCqlSession interface 可以使用一系列响应式方法,这些方法可以与 Quarkus 及其响应式框架 Mutiny 无缝集成。

如果您不熟悉 Mutiny,请查看 Mutiny - an intuitive reactive programming library

让我们使用 Mutiny 的响应式编程重写我们的应用程序。

首先,让我们声明另一个以响应式方式工作的 DAO 接口:

@Dao
public interface ReactiveFruitDao {

  @Update
  Uni<Void> updateAsync(Fruit fruit);

  @Select
  MutinyMappedReactiveResultSet<Fruit> findAll();
}

请注意使用 MutinyMappedReactiveResultSet——它是一种专门的 Mutiny 类型,从驱动程序返回的原始 Publisher 转换而来,它还公开了一些额外的方法,例如获取查询执行信息。如果您不需要该接口中的任何内容,您还可以简单地声明您的方法返回 MultiMulti<Fruit> findAll()

同样,方法 updateAsync 返回一个 Uni——它会从驱动程序返回的原始结果集自动转换而来。

Cassandra 驱动程序使用响应式流 Publisher API 進行响应式调用。但是,Quarkus 框架使用 Mutiny。因此,CqlQuarkusSession 接口会透明地将驱动程序返回的 Publisher 实例转换为响应式类型 MultiCqlQuarkusSession 也可以将 Publisher 转换为 Uni——在这种情况下,发布者预期至多发送一行,然后完成。这适用于写查询(它们不返回任何行),或保证至多返回一行的读查询(例如,计数查询)。

接下来,我们需要调整 FruitMapper 来构造一个 ReactiveFruitDao 实例:

@Mapper
public interface FruitMapper {
  // the existing method omitted

  @DaoFactory
  ReactiveFruitDao reactiveFruitDao();
}

现在,我们可以创建一个利用我们的响应式 DAO 的 ReactiveFruitService

@ApplicationScoped
public class ReactiveFruitService {

  @Inject ReactiveFruitDao fruitDao;

  public Uni<Void> add(Fruit fruit) {
    return fruitDao.update(fruit);
  }

  public Multi<Fruit> getAll() {
    return fruitDao.findAll();
  }
}

最后,我们可以创建一个 ReactiveFruitResource

@Path("/reactive-fruits")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ReactiveFruitResource {

  @Inject ReactiveFruitService service;

  @GET
  public Multi<FruitDto> getAll() {
    return service.getAll().map(this::convertToDto);
  }

  @POST
  public Uni<Void> add(FruitDto fruitDto) {
    return service.add(convertFromDto(fruitDto));
  }

  private FruitDto convertToDto(Fruit fruit) {
    return new FruitDto(fruit.getName(), fruit.getDescription());
  }

  private Fruit convertFromDto(FruitDto fruitDto) {
    return new Fruit(fruitDto.getName(), fruitDto.getDescription());
  }
}

上述资源公开了一个新的端点 reactive-fruits。它的功能与我们之前用 FruitResource 创建的功能相同,但一切都以响应式的方式处理,没有任何阻塞操作。

上面的 getAll() 方法返回 Multi,而 add() 方法返回 Uni。这些类型与我们之前遇到的 Mutiny 类型相同;Quarkus 响应式 REST API 会自动识别它们,因此我们不必自己将其转换为 JSON。

Quarkus REST 本机支持 Mutiny 响应式类型,例如 UniMulti

此依赖项已包含在此指南的 pom.xml 中,但如果您要从头开始一个新项目,请确保包含它。

Testing the Reactive REST API

如上文所述,以开发模式运行该应用程序,然后你就可以使用 curl 命令与底层 REST API 交互。

使用反应式 REST 端点创建水果:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"name":"banana","description":"yellow and sweet"}' \
  http://localhost:8080/reactive-fruits

使用反应式 REST 端点检索水果:

curl -X GET http://localhost:8080/reactive-fruits

Creating a Reactive Frontend

现在,我们来添加一个简单的网页以与我们的 ReactiveFruitResource 进行交互。在 src/main/resources/META-INF/resources 目录中,使用 this file 中的内容添加一个 reactive-fruits.html 文件。

你现可与你的反应式 REST 服务进行交互:

Health Checks

如果你使用的是 Quarkus SmallRye Health 扩展,那么 Cassandra 客户端将自动添加一个准备就绪运行状况检查来验证与 Cassandra 集群的连接。此扩展已包括在本指南的 pom.xml 中,但如果你需要在应用程序中手动将其包含在内,请添加以下内容:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-health</artifactId>
</dependency>

当运行状况检查可用时,你可以访问应用程序的 /health/ready 端点,并获得有關连接验证状态的信息。

mvn clean quarkus:dev 的开发模式下运行,如果你将浏览器指向 [role="bare"] [role="bare"]http://localhost:8080/health/ready ,应该会看到类似于以下内容的输出:

{
    "status": "UP",
    "checks": [
        {
            "name": "DataStax Apache Cassandra Driver health check",
            "status": "UP",
            "data": {
                "cqlVersion": "3.4.4",
                "releaseVersion": "3.11.7",
                "clusterName": "Test Cluster",
                "datacenter": "datacenter1",
                "numberOfNodes": 1
            }
        }
    ]
}

如果你需要在应用程序中全局启用运行状况检查,但不希望激活 Cassandra 运行状况检查,你可以通过在 application.properties 中将 quarkus.cassandra.health.enabled 属性设置为 false 来禁用 Cassandra 运行状况检查。

Metrics

Cassandra Quarkus 客户端可以提供有关 Cassandra 会话和各个 Cassandra 节点的指标。它支持 Micrometer 和 MicroProfile。

启用指标的第一步是添加一些其他依赖项,具体取决于你计划使用的指标框架。

Enabling Metrics with Micrometer

Micrometer 是 Quarkus 应用程序中推荐的指标框架。

要在应用程序中启用 Micrometer 指标,你需要在 pom.xml 中添加以下内容。

<dependency>
  <groupId>com.datastax.oss</groupId>
  <artifactId>java-driver-metrics-micrometer</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>

本指南使用 Micrometer,因此上述依赖项已包含在本指南的 pom.xml 中。

Enabling Metrics with MicroProfile Metrics

从 pom.xml 中删除对 Micrometer 的所有依赖项,然后添加以下依赖项:

<dependency>
  <groupId>com.datastax.oss</groupId>
  <artifactId>java-driver-metrics-microprofile</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-metrics</artifactId>
</dependency>

Enabling Cassandra Metrics

即使你的应用程序中启用了指标,Cassandra 客户端也不会报告任何指标,除非你选择此功能。因此你的下一步是在 application.properties 文件中启用 Cassandra 指标。

quarkus.cassandra.metrics.enabled=true

就是这样!

最后(可选)的一步是自定义 Cassandra 客户端要跟踪的特定 Cassandra 指标。可以跟踪几个指标;如果你跳过此步骤,将自动跟踪一组有用的默认指标。

有关可用指标名称的完整列表,请参阅 driver settings reference页面;搜索`advanced.metrics`部分。同时, driver manual中详细介绍了 Cassandra 驱动器指标。

如果您确实希望自定义要跟踪的指标,则应使用以下属性:

  • `quarkus.cassandra.metrics.session.enabled`应包含要启用的会话级别指标(对会话是全局的指标)。

  • `quarkus.cassandra.metrics.node.enabled`应包含要启用的节点级别指标(Cassandra 客户端所联系的每个节点获取其自己的指标值)。

这两个属性都接受有效指标名称的逗号分隔列表。

例如,假设您希望启用以下三个 Cassandra 指标:

  • Session-level: session.connected-nodes and session.bytes-sent;

  • Node-level: node.pool.open-connections.

然后,您应该将以下设置添加到`application.properties`中:

quarkus.cassandra.metrics.enabled=true
quarkus.cassandra.metrics.session.enabled=connected-nodes,bytes-sent
quarkus.cassandra.metrics.node.enabled=pool.open-connections

本指南的`application.properties`文件已经启用了许多指标;您可以将其指标列表用作在应用程序中公开有用的 Cassandra 指标的一个良好起点。

正确启用指标后,您可以在应用程序的`/metrics`REST 端点处获得所有已启用指标的指标报告。

mvn clean quarkus:dev`中运行开发模式,如果将浏览器指向`http://localhost:8080/metrics,您应该会看到指标列表;搜索其名称包含`cassandra`的指标。

要显示 Cassandra 指标,需要初始化和连接 Cassandra 客户端;如果您使用延迟初始化(见下文),您不会看到任何 Cassandra 指标,直到您的应用程序实际连接并首次访问数据库为止。

Running in native mode

如果您安装了 GraalVM,可以使用以下方式进行build a native image

mvn clean package -Dnative

请注意,本机编译可能需要大量时间!编译完成后,您可以按如下方式运行本机可执行文件:

./target/cassandra-quarkus-quickstart-*-runner

然后您可以将浏览器指向 http://localhost:8080/fruits.html,并使用您的应用程序。

Choosing between eager and lazy initialization

如上所述,此扩展程序允许您注入多种类型的 Bean:

  • 像 `QuarkusCqlSession`或`FruitDao`这样的简单 Bean;

  • Bean 的异步版本,例如`CompletionStage&lt;QuarkusCqlSession&gt;`或`CompletionStage<FruitDao>`;

  • Bean 的反应式版本,例如`Uni&lt;QuarkusCqlSession&gt;`或`Uni&lt;FruitDao&gt;`。

最直接的方法显然是直接注入 Bean。这应该适用于大多数应用程序。但是,`QuarkusCqlSession`Bean 以及依赖于它的所有 DAO Bean 在首次使用之前可能需要一些时间初始化,并且此过程正在阻塞。

幸运的是,可以控制初始化应该何时发生:参数`quarkus.cassandra.init.eager-init`确定是否应该在第一次访问时初始化 QuarkusCqlSession`Bean(延迟)或者在应用程序启动时(热切)初始化。此参数的默认值为 `false,表示 init 过程是延迟的:`QuarkusCqlSession`Bean 将在其第一次访问时延迟初始化——例如,当有第一个 REST 请求需要与 Cassandra 数据库进行交互时。

使用延迟初始化可以加快应用程序的启动时间,并在 Cassandra 数据库不可用时避免启动失败。但是,如果你的代码完全非阻塞,例如它使用了 reactive routes,则它也可能被证明是危险的。事实上,延迟的初始化可能会在不允许阻塞的线程上意外发生,例如 Vert.x 事件循环线程。因此,在这些上下文中应该避免将 quarkus.cassandra.init.eager-init 设置为 false 并注入 QuarkusCqlSession

如果你想使用 Vert.x(或任何其他非阻塞框架)并保持延迟初始化行为,则你应该仅注入所需 Bean 的 CompletionStageUni。在注入这些 Bean 时,将在后台以非阻塞方式利用 Vert.x 事件循环来延迟触发初始化过程。这样你就不会冒着阻塞 Vert.x 线程的风险。

或者,你可以将 quarkus.cassandra.init.eager-init 设置为 true:在这种情况下,会话 Bean 和所有 DAO Bean 将在应用程序启动期间在 Quarkus 主线程上热切地初始化。这将消除阻塞 Vert.x 线程的任何风险,代价是让你的启动时间(大大)更长。

Conclusion

使用 Quarkus 和 Cassandra 扩展从客户端应用程序访问 Cassandra 数据库非常容易,它为 Apache Cassandra 的 DataStax Java 驱动程序提供了配置和本机支持。