Redis®*的功率,用于您的超音速Quarkus/Java应用程序
#开源 #redis #quarkus #aiven

在构建在Kubernetes上运行的应用程序时,您希望启动时间和足迹很小。传统的Java应用程序更喜欢消耗其限制内存和CPU,并且您可能已经在生产应用程序中看到OOMKilled错误。 Brace您自己将带您与Quarkus(快速轻巧的Java框架)和Redis-®*(快速内存数据结构商店)进行“超音速”旅程。

构建一个小型通信应用程序

想象一下,您正在构建一个较大项目的一部分,构建一次性通信功能。您的团队正在使用他们熟悉的Java,而Quarkus则是框架,因为他们希望该应用程序与Kubernetes兼容(在大小和启动时间方面)。

除了关系数据库外,该团队还使用REDIS快速查询生成的一次性通信。此示例使用Aiven for Redis,如果您想尝试一下,则可以使用sign up for a free trial

对您的团队的一个重要考虑因素是Quarkus和Redis都是开源项目。

在你开始之前

要遵循此博客的动手部分,以下是软件要求:

是时候构建应用程序了

创建一个Maven项目

以下命令创建了一个新的Maven项目,并将所需的扩展程序添加到您的项目中。 Quarkus redis-client扩展程序允许用户连接到Redis服务器并运行Redis命令。 resteasy-jackson扩展程序允许构建Restful Web服务并处理JSON数据格式。 resteasy-mutiny扩展有助于为异步系统构建反应性API。

mvn io.quarkus.platform:quarkus-maven-plugin:2.7.5.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=one-time-password \
    -Dextensions="redis-client,resteasy-jackson,resteasy-mutiny" \
    -DnoCode
cd one-time-password

使用以下命令将redis-client依赖关系添加到您的pom.xml文件:

./mvnw quarkus:add-extension -Dextensions="redis-client"

获取REDIS服务器详细信息

创建一个Aiven for Redis实例。对于此练习,任何服务计划都会做。 REDIS服务运行后,请从概述>> 连接信息选项卡中复制服务URI

转到您喜欢的代码编辑器并打开one-time-password项目。粘贴服务URI src > main > resources > application.properties文件:

quarkus.redis.hosts=[YOUR REDIS CONNECTION INFORMATION GOES HERE]

如果您在本地计算机上运行Redis,请使用以下设置:

quarkus.redis.hosts=redis://localhost:6379 

创建OTP POJO(普通的旧Java对象)

Otp类创建一个pojo(普通的旧爪哇对象)来容纳session_keyotp_valuegenerateRandomOtp方法在给定范围内生成一个随机值。

创建src/main/java/org/acme/redis/Otp.java文件并添加以下内容:

package org.acme.redis;
import java.util.Random;

public class Otp {
    final int lowRange = 100000;
    final int highRange = 999999;
    public String session_key;
    public int otp_value;

    public Otp(String session_key) {
        this.session_key = session_key;
        this.otp_value = generateRandomOtp(lowRange, highRange);
    }

    public Otp() {}

    private static int generateRandomOtp(int low, int high) {

        // Generate random int value from $low to ($high - 1)
        return low + new Random().nextInt(high - low);
    }
}

创建OTP服务

您将创建将扮演Redis客户端角色的OtpService。该课程将帮助您执行GETEXISTSSETEXSETNXTTL Redis命令。有关这些文档,请参见official Redis commands page

创建src/main/java/org/acme/redis/OtpService.java文件并添加以下内容:

package org.acme.redis;
import io.quarkus.redis.client.RedisClient;
import java.util.Arrays;
import javax.inject.Inject;
import javax.inject.Singleton;

@Singleton
class OtpService {
    final int timeInSeconds = 20;

    @Inject
    RedisClient redisClient;

    public String getOtp(String session_key) {
        return redisClient.get(session_key).toString();
    }

    public void newOtp(String session_key) {
        Otp otp = new Otp(session_key);

        // SETNX will only create a key if it doesn't already exist
        // - so we won't overwrite an existing OTP value
        // Unfortunately SETNX can't set the TTL/expiration time
        if (redisClient.setnx(otp.session_key.toString(),
                String.valueOf(otp.otp_value)).toBoolean()) {

            // Only update TTL/expiration if the OTP value was set
            redisClient.setex(otp.session_key.toString(),
                String.valueOf(timeInSeconds),
                String.valueOf(otp.otp_value));
        }
    }

    public String getOtpTTL(String session_key) {
        return redisClient.ttl(session_key).toString();
    }

    public boolean keyExists(String session_key) {
        return redisClient.exists(Arrays.asList(session_key)).toBoolean();
    }
}

创建OTP资源

创建src/main/java/org/acme/redis/OtpResource.java文件,在其中您为一次性password服务定义HTTP端点。

观察@Inject注释以轻松创建服务实例,然后@Path("/otp")表示HTTP端点的创建。 GETPOST调用都使用相同的端点。使用像Quarkus这样的框架的伟大之处是,如果没有注释,您将不得不编写多行代码才能达到相同的结果。

package org.acme.redis;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jboss.resteasy.annotations.jaxrs.QueryParam;
import io.vertx.core.json.JsonObject;

@Path("/otp")
public class OtpResource {
    @Inject
    OtpService service;

    @GET
    public JsonObject getOtp(@QueryParam String session_key) {

        // If the key doesn't exist, return an error response rather than the usual
        // object response
        if (!service.keyExists(session_key)) {
            return errorResponse();
        }
        JsonObject result = new JsonObject();
        result.put("OTP: ", service.getOtp(session_key));
        result.put("TTL: ", service.getOtpTTL(session_key));
        return result;
    }

    JsonObject errorResponse() {
        JsonObject result = new JsonObject();
        result.put("Message: ", "The OTP key doesn't exist.");
        return result;
    }

    @POST
    public void newOtp(@QueryParam String session_key) {
        service.newOtp(session_key);
    }
}

运行您的新Quarkus应用程序

从您的一次性password项目的根部执行以下命令:

 ./mvnw quarkus:dev

导航到http://localhost:8080/otp?session_key=[SOME_KEY],用任何文本代替[SOME_KEY]。对于您的初始运行,您将收到这样的错误响应:

"Message: ": "The OTP key doesn't exist."

这是因为此密钥在Redis中还不存在。从您的终端中,制作以下 post 请求创建您的密钥:

curl --location --request POST 'http://localhost:8080/otp?session_key=[SOME_KEY]'

现在重新加载您的浏览器,您应该收到一个随机的6位数字作为一次性通信,该数字在20秒内到期。如果您等待超过20秒,它将到期,您将再次收到错误响应。

如果您不断刷新页面,您将获得相同的OTP,直到(到期)TTL用完为止。

您可能还会意识到您不必为此应用程序进行任何服务器设置/处理,因为Quarkus为您处理了这一点。很酷,嗯?

进一步学习

在此博客中,我通过使用Quarkus Framework构建一个简单的一次性Password应用程序,为您提供了Redis的入门经验,并通过构建了用例。实际的一次性通信软件的设计和实现比此处提到的简单应用程序要复杂得多。例如,它可能不想给其他用户提供相同的OTP。

了解有关Quarkus的更多信息:

了解REDIS的更多信息:

*redis是Redis Ltd.的注册商标,Redis Box徽标是Redis Ltd的标记。其中任何权利都保留给RedisLtd。Aiven的任何用途仅用于参考目的,并且不表示。 Redis和Aiven之间的任何赞助,认可或隶属关系。本网站中使用的所有产品和服务名称仅用于识别目的,并不意味着认可。