Мощь Redis®* для вашего сверхзвукового приложения Quarkus/Java

При создании приложений, работающих на Kubernetes, вы хотите, чтобы время запуска и занимаемая площадь были небольшими. Традиционные Java-приложения любят потреблять больше, чем их ограниченная память и процессор, и вы могли видеть ошибки OOMKilled в ваших производственных приложениях. Приготовьтесь, поскольку этот блог отправит вас в «сверхзвуковое» путешествие с Quarkus (быстрым и легким Java-фреймворком) и Redis®* (быстрым хранилищем структур данных в памяти).

Создание небольшого приложения для одноразового пароля

Представьте, что вы создаете функцию одноразового пароля в рамках более крупного проекта. Ваша команда использует Java, с которой она хорошо знакома, и Quarkus в качестве фреймворка, поскольку хочет, чтобы приложение было совместимо с Kubernetes (с точки зрения размера и времени запуска).

Помимо реляционной базы данных, команда также использует Redis для быстрого запроса сгенерированных одноразовых паролей. В этом примере используется Aiven для Redis, и вы можете подписаться на бесплатную пробную версию, если хотите опробовать ее.

Важным моментом для вашей команды является то, что и Quarkus, и Redis — это проекты с открытым исходным кодом.

Прежде чем начать

Чтобы следовать практической части этого блога, вот требования к программному обеспечению:

  • JDK 11+
  • Apache Maven 3.8.1+
  • Локальный или управляемый экземпляр Redis

Время для создания приложения

Создание проекта Maven

Следующая команда создает новый проект Maven и добавляет необходимые расширения в ваш проект. Расширение Quarkus redis-client позволяет пользователю подключаться к серверу Redis и выполнять команды Redis. Расширение resteasy-jackson позволяет создавать RESTful веб-сервисы и обрабатывать данные в формате 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 службы с вкладки Overview > Connection information.

Перейдите в ваш любимый редактор кода и откройте проект 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 
Войти в полноэкранный режим Выйти из полноэкранного режима

Создание POJO Otp (Plain Old Java Object)

Класс Otp создает POJO (Plain Old Java Object) для хранения session_key и otp_value. Метод generateRandomOtp генерирует случайное значение в заданном диапазоне.

Создайте файл 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

Вы собираетесь создать OtpService, который будет играть роль клиента Redis. Этот класс поможет вам выполнять команды Redis GET, EXISTS, SETEX, SETNX и TTL. Документацию по ним можно найти на официальной странице команд Redis.

Создайте файл 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, в котором вы определите конечные точки HTTP для вашей службы одноразовых паролей.

Обратите внимание на аннотацию @Inject для простого создания экземпляра службы и @Path("/otp") для указания создания конечных точек HTTP. Одна и та же конечная точка используется для вызовов GET и POST. Преимущество использования такого фреймворка, как 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

В корне проекта с одноразовым паролем выполните следующую команду:

 ./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, пока не истечет время жизни (time-to-live) TTL.

Вы также можете понять, что вам не пришлось выполнять настройку/обработку сервера для этого приложения, поскольку Quarkus позаботился об этом за вас. Довольно круто, да?

Дальнейшее обучение

В этом блоге я рассказал вам о начале работы с Redis и продемонстрировал пример использования, создав простое приложение для одноразовых паролей с помощью фреймворка Quarkus. Проектирование и реализация реального программного обеспечения для одноразовых паролей намного сложнее, чем простое приложение, упомянутое здесь; например, оно, вероятно, не захочет предоставлять один и тот же OTP разным пользователям.

Чтобы узнать больше о Quarkus:

  • Документация проекта Quarkus

Чтобы узнать больше о Redis:

  • Документация по Redis
  • Aiven для Redis — документация для разработчиков

*Redis является зарегистрированной торговой маркой компании Redis Ltd., а логотип Redis box является маркой компании Redis Ltd. Все права на них принадлежат Redis Ltd. Любое использование Aiven исключительно в справочных целях и не указывает на какое-либо спонсорство, одобрение или связь между Redis и Aiven. Все названия продуктов и услуг, используемые на этом сайте, предназначены только для идентификации и не подразумевают одобрения.

Оцените статью
devanswers.ru
Добавить комментарий