Primary tabs

Vert.x нативный образ потрясающий!

Ссылка на оригинал - https://www.jetdrone.xyz/2018/08/10/Vertx-native-image-10mb.html, автор публикации - Paulo Lopes

Я уже некоторое время работаю с GraalVM, главным образом, над аспектом Polyglot , но некоторая работа была проделана в поддержке нативных изображений. Сегодня я хотел бы поделиться тем, что сейчас это возможно, спойлер: запустить Docker изображение с размером от 38MB и 10MB из памяти!

Немного истории

С серией 3.x Eclipse Vert.x была проделана большая работа по уменьшению количества загрузчиков классов , магии отражения(именно поэтому, например, нет аннотаций). Это обычно рассматривается как противоречащий смысл в мире Java, но это окупается, так как мы уже можем делать некоторые удивительные вещи, не задумываясь о хакерах или обходных путях, чтобы обойти ограничения субстрата.

Доказательство концепции

В качестве подтверждения концепции я решил создать небольшое приложение на основе презентации, которую я сделал около 2 лет назад на JavaZone. Приложение делает следующее:

  • Запустите клиент WebSocket для сбора в реальном времени неподтвержденных транзакций биткойнов.
  • Подключение к Postgres с победителем Techempower Benchmarks # 16 пг-реактивным-клиента.
  • По неподтвержденной транзакции сохраните ее в postgres.
  • На сохранить публикацию в UTX карту восстановленного значения vert.x eventbus
  • Запустите HTTP-сервер, обслуживающий одностраничное приложение
  • При запуске сервера подключите шину событий от сервера к веб-браузеру, используя sockjs
  • В браузере визуализируйте значения UTX в реальном времени по мере их поступления с веб-сокета сервера .

Как вы можете видеть, здесь уже много чего происходит: серверы, клиенты , веб-сокеты , события . Я мог бы продолжать добавлять больше материала, но это PoC правильно!

Покажи мне код

Теперь, когда у нас есть идея, мы должны реализовать ее, как я уже сказал, это был римейк старой презентации, поэтому код для меня был почти готов. Вот как это оказалось:

final Vertx vertx = Vertx.vertx();
final EventBus eb = vertx.eventBus();
final PgPool postgres = PgClient.pool(...);

BlockChainClient.create(vertx)
  .connect(self -> {
    self.subscribeUnconfirmed(json -> {
      postgres.preparedQuery(
        "INSERT INTO UTX (data) VALUES ($1)",
        Tuple.of(Json.create(json)), ar -> {
          int utxValue = 0;
          if (json.containsKey("out")) {
            // reduce step
            for (Object o : json.getJsonArray("out")) {
              utxValue += ((JsonObject) o).getInteger("value", 0);
            }
          }
          eb.publish("data.updates", utxValue);
      });
    });
  });

final Router app = Router.router(vertx);

app.route("/eventbus/*").handler(SockJSHandler.create(vertx));
app.route().handler(StaticHandler.create("static"));

vertx.createHttpServer()
  .requestHandler(app)
  .listen(Integer.getInteger("port", 8080));

Обработка ошибок и конфигурация опущены для краткости.

Это очень простое приложение, и на самом деле именно так вы и будете кодировать его с помощью Vert.x, я не делал никаких попыток заставить его работать на Graal SVM.

Построение

Сборка кода тривиальна, но у сборки изображения возникли некоторые проблемы. К счастью, проблемы просты и могут быть решены с помощью простого файла замены Java.

Таким образом, создание нативного изображения было так просто:

native-image \
  -Djava.net.preferIPv4Stack=true \
  -Dvertx.disableDnsResolver=true \
  -H:IncludeResources="(META-INF/services|webroot)/.*" \
  -H:+ReportUnsupportedElementsAtRuntime \
  -H:ReflectionConfigurationFiles=./src/main/svm/reflection.json \
  -jar "target/bitcoin-viewer.jar"

Итак, что важно увидеть здесь, сначала я укажу, что я предпочитаю стек IPV4 от виртуальной машины (но это не является обязательным требованием). Во-вторых, я отключаю распознаватель DNS Vert.x по той причине, что он не работает корректно с SVM, и vert.x откатится к преобразователю DNS по умолчанию на виртуальной машине (блокирующему), который работает нормально. Затем я указываю, какие ресурсы я бы хотел сохранить в своем fatjar, и указываю файл замещения.

После завершения вы можете увидеть:

-rwxrwxr-x.  1 plopes plopes 24603024 10 aug 11:45 bitcoin-viewer

Ваша заявка сейчас просто 24,6MB !

Dockerize

Graal SVM опирается на Glibc, так что это означает, что вы можете запустить его на многих изображениях, таких как Ubuntu , Fedora , Centos ... но эти изображения довольно большие, так почему бы не Alpine ?

Альпийские образы созданы против musl-libc, и это проблема. К счастью, проект alpine задокументировал, как заставить glibcработать на alpine, и на докер-хабе уже есть несколько изображений frolvlad/alpine-glibc.

Итак, давайте перейдем в докер?

# GraalVM docker image used for AoT compilation
FROM panga/graalvm-ce:latest AS build-aot
# Add maven wrapper
ADD mvnw app/
ADD mvnw.cmd app/
ADD .mvn app/.mvn/
# Add settings.xml to allow snapshots
ADD settings.xml root/.m2/
# Add pom
ADD pom.xml app/
# Add sources
ADD src app/src/
# Set working dir
WORKDIR /app
# Build (java side)
RUN ./mvnw -Pnative-image package
# Build image
RUN native-image \
    --no-server \
    -Djava.net.preferIPv4Stack=true \
    -Dvertx.disableDnsResolver=true \
    -H:IncludeResources="(META-INF/services|webroot)/.*" \
    -H:+ReportUnsupportedElementsAtRuntime \
    -H:ReflectionConfigurationFiles=./src/main/svm/reflection.json \
    -jar "target/bitcoin-viewer.jar"
# Create new image from alpine
FROM frolvlad/alpine-glibc:alpine-3.8
RUN apk add --no-cache ca-certificates
# Copy generated native executable from build-aot
COPY --from=build-aot /app/bitcoin-viewer /bitcoin-viewer
# Set the entrypoint
ENTRYPOINT [ "/bitcoin-viewer" ]

Результаты

Поэтому, когда мы запускаем наше приложение и postgres и запускаем, docker stats мы видим:

CONTAINER ID  NAME            CPU %  MEM USAGE / LIMIT    MEM %
c7f5e7af56fe  vertx-bitcoin   0.61%  5.133MiB / 15.54GiB  0.03%
a3536684f175  postgres        1.26%  11.27MiB / 15.54GiB  0.07%

Я бы сказал, что это удивительное сложное приложение, работающее в 5 МБ оперативной памяти !!! с мгновенным запуском!

А насчет размеров изображения, бега docker imagesмы видим:

REPOSITORY      TAG      IMAGE ID       CREATED             SIZE
vertx-bitcoin   latest   3b8b487b8ad8   43 minutes ago      37.9MB

Таким образом, общий размер составляет 38 МБ!

Java теперь жизнеспособная технология Serveless, и мы можем согласиться с тем, что Java не медленная и не раздутая, верно ?!

Не нашли ответ на свой вопрос? Возможно, вы найдете решение проблемы на нашем канале в Youtube! Здесь мы собрали небольшие, но эффективные инструкции. Смотрите и подписывайтесь на наш youtube-канал!

Смотреть на Youtube