Статьи

Что нового в блоггерах JVM — Docker Compose и Views Counter

Как некоторые из вас могут знать, в течение последнего года я работаю над любимым проектом под названием JVM Bloggers с целью популяризации ведения блогов и обмена знаниями в польском сообществе разработчиков Java. Мы отправляем еженедельную сводку с новыми сообщениями в блогах и новыми видео, опубликованными за последние 7 дней.

За последние несколько недель в проект были добавлены два основных изменения:

  • развертывание выполняется с помощью Docker Compose
  • Все клики проходят через приложение, поэтому мы можем собрать некоторую статистику

Docker Compose

Ранее приложение развертывалось с использованием двух отдельных докеров, это был более простой подход, но когда мы переходили на архитектуру микросервисов, я знал, что Docker Compose будет хорошим выбором, позволяющим нам легко добавлять все больше и больше элементов в нашу систему.

Во-первых, docker-compose.yml должен быть создан с двумя сервисами: jvm_bloggers_db и jvm-bloggers-core:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '2'
services:
  jvm_bloggers_db:
    image: sameersbn/postgresql:9.4-22
    environment:
      DB_USER: $JVM_BLOGGERS_DB_USER
      DB_PASS: $JVM_BLOGGERS_DB_PASSWORD
      DB_NAME: $JVM_BLOGGERS_DB_NAME
    ports:
      - "$JVM_BLOGGERS_DB_PUBLISHED_PORT:5432"
    volumes:
      - "$JVM_BLOGGERS_DB_PATH:/var/lib/postgresql"
  jvm-bloggers-core:
    image: tdziurko/jvm-bloggers:$JVM_BLOGGERS_CORE_IMAGE_VERSION
    environment:
      spring.profiles.active: $JVM_BLOGGERS_CORE_SPRING_PROFILES
      jasypt.encryptor.password: $JVM_BLOGGERS_CORE_ENCRYPTOR_PASSWORD
    ports:
      - "$JVM_BLOGGERS_CORE_PORT:8080"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /usr/share/zoneinfo/Europe/Warsaw:/etc/timezone:ro
      - /tmp
    links:
      - jvm_bloggers_db
    depends_on:
      - jvm_bloggers_db

В jvm_bloggers_db у нас есть некоторые параметры, которые позволяют настраивать образ PostgreSQL, кроме самых очевидных, таких как имя базы данных, имя пользователя и пароль, также есть:

  • $ JVM_BLOGGERS_DB_PUBLISHED_PORT — порт, на котором наша база данных будет доступна с внешнего (например, компьютера разработчика)
  • $ JVM_BLOGGERS_DB_PATH — путь к каталогу, где файлы базы данных расположены на нашем сервере

jvm-bloggers-core более сложный:

  • Переменные среды определяют профиль Spring и мастер-пароль, используемые для шифрования таких свойств, как ключи API, пароль для панели администратора и т. д.
  • $ JVM_BLOGGERS_CORE_PORT — порт, на котором доступно приложение, на производстве оно, очевидно, 80, но локально оно может отличаться
  • ссылка jvm_bloggers_db позволяет нам использовать это в качестве URL- адреса базы данных в spring.datasource.url со значением jdbc: postgresql: // jvm_bloggers_db: 5432 / jvm_bloggers_prod, не беспокоясь о том, где именно контейнер базы данных работает в нашей внутренней сети.

Рядом с файлом docker-compose нам нужен bash-скрипт для запуска / остановки нашей системы:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/sh
 
setupProperties() {
  # Database settings
  export JVM_BLOGGERS_DB_USER=jvm_bloggers
  export JVM_BLOGGERS_DB_PASSWORD=jvm_bloggers
  export JVM_BLOGGERS_DB_NAME=jvm_bloggers
  export JVM_BLOGGERS_DB_PATH="~/postgresql-data/"
  export JVM_BLOGGERS_DB_PUBLISHED_PORT=5432
 
  # Core Application settings:
  export JVM_BLOGGERS_CORE_IMAGE_VERSION=0.9.0-20160724-165001-19f0d70
  export JVM_BLOGGERS_CORE_SPRING_PROFILES=dev
  export JVM_BLOGGERS_CORE_ENCRYPTOR_PASSWORD=secret
  export JVM_BLOGGERS_CORE_PORT=9000
}
 
start() {
    docker-compose up -d
    echo "Started JVM Bloggers"
}
 
stop() {
    docker-compose down
}
 
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
esac

Основная часть этого файла состоит из нескольких экспортов, которые позволяют настраивать docker-compose, поэтому его можно использовать без изменений локально и в производстве. Затем у нас есть простые команды для запуска, выключения и проверки состояния запущенных сервисов. И все, теперь мы можем использовать следующую команду для запуска всех сервисов:

1
./jvm-bloggers.sh start

Счетчик просмотров

Следующая функция, выпущенная в версии 0.10.0, — счетчик просмотров. Я хотел узнать, сколько людей используют блоггеры JVM и, что наиболее важно, какие записи наиболее популярны. В ближайшие недели мы планируем добавить раздел с самыми популярными сообщениями прошлого месяца, чтобы авторы самого ценного контента могли получить дополнительное признание.

Чтобы добавить эту функцию, потребовались следующие вещи:

  1. Контроллер перенаправления
  2. Миграция с UUID в качестве уникального идентификатора записи блога на что-то более короткое
  3. Логика для хранения кликов в базе данных

Работа Redirect Controller очень проста — получить UID из параметра url (например, http://jvm-bloggers.com/r/wx1LivZ ) и перенаправить пользователя на соответствующую запись в блоге. Но до 0.10.0 UID был полным

1
_UUID.randomUUID().toString()_

поэтому вместо красивой и короткой ссылки у нас было что-то вроде http://jvm-bloggers.com/r/b877a837-4f5b-4a0b-90b2-981c83c1366e, не очень дружелюбный и лаконичный. Необходима простая миграция данных, а в новом подходе UID — это компактная строка длиной 7 символов:

1
RandomStringUtils.randomAlphanumeric(7);

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

В RedirectController мы публикуем событие SingleClick:

1
actorRef.tell(new SingleClick(blogPost.get()), noSender());

и актеры просто обрабатывают это событие, сохраняя сущность Click:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
@Slf4j
public class ClicksStoringActor extends AbstractActor {
 
    public ClicksStoringActor(ClickRepository clickRepository, NowProvider nowProvider) {
        log.debug("Creating " + ClicksStoringActor.class.getSimpleName());
        receive(ReceiveBuilder.match(SingleClick.class,
            clickEvent -> {
                log.debug("Storing click for " + clickEvent.getBlogPost().getUrl());
                clickRepository.save(new Click(clickEvent.getBlogPost(), nowProvider.now()));
            }).build()
        );
    }
 
    public static Props props(ClickRepository clickRepository, NowProvider nowProvider) {
        return Props.create(ClicksStoringActor.class, () -> {
                return new ClicksStoringActor(clickRepository, nowProvider);
            }
        );
    }
}

кредиты

Эти новые функции были бы невозможны без участников, в частности, Mateusz Urbański и Marcin Kłopotek .

Резюме

Блоггеры JVM все еще развиваются и с небольшими изменениями, и с новыми важными функциями, поэтому, если вы хотите помочь, свяжитесь со мной или присоединитесь к нашему каналу Gitter . У нас есть Java8, Spring Boot, Docker, Akka и множество идей для реализации (даже с использованием разных языков).

Для получения более подробной информации вы должны посетить наш репозиторий GitHub .

Ссылка: Что нового в блоггерах JVM — Docker Compose и Views Counter от нашего партнера по JCG Томаша Дзюрко в блоге Code Hard Go Pro .