Как некоторые из вас могут знать, в течение последнего года я работаю над любимым проектом под названием 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 и, что наиболее важно, какие записи наиболее популярны. В ближайшие недели мы планируем добавить раздел с самыми популярными сообщениями прошлого месяца, чтобы авторы самого ценного контента могли получить дополнительное признание.
Чтобы добавить эту функцию, потребовались следующие вещи:
- Контроллер перенаправления
- Миграция с UUID в качестве уникального идентификатора записи блога на что-то более короткое
- Логика для хранения кликов в базе данных
Работа 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 . |