В прошлой статье я начал изучать микросервисный подход, но до полноценного решения тогда не дошёл. Тогда я пробовал сам поднимать процессы на php, управлять ими, связывать между собой через очереди потому что монолит не мог справиться с асинхронными задачами. Но чего у меня реально нехватало, так это нормальной изоляции и деплоймента, межсервисного взаимодействия и стабильной работы.
Docker
Я сразу скажу что не знаю как настраивать production с докер-контейнерами, но сервисы в рабочем окружении поднимаются тривиально
- Ставите Docker для Мака или для Windows
- Ставите dry для терминала (по желанию)
- Создаёте Dockerfile
- Создаёте docker-compose.yml
- Запускаете docker-compose up
Концепции
Images (образы) это изолированная среда, как правило с конкретным языком (node, php) или библиотекой. За это отвечает Dockerfile, который ссылается на существующий, скачиваемый образ на докер хабе.
Что-бы увидеть установленные образы, есть комманда docker images .
Контейнеры это запущенные образы которые изолированы от host-машины. Обычно контейнер поднимается для какого-то сервиса, поэтому у него есть своё название, явно объявлен маппинг сетевых портов на host-машину и способ монтирования файловой системы — за это отвечает docker-compose.yml
Что-бы увидеть установленные образы, есть комманда docker images .
Контейнеры это запущенные образы которые изолированы от host-машины. Обычно контейнер поднимается для какого-то сервиса, поэтому у него есть своё название, явно объявлен маппинг сетевых портов на host-машину и способ монтирования файловой системы — за это отвечает docker-compose.yml
По умолчанию порт не перебрасываются на такой же , а файлы хоста не линкуются и не будут обновляться внутри контейнера после старта.
Что-бы увидеть запущенные контейнеры, есть комманда docker ps (а лучше dry)
Что-бы запустить текущую папку есть docker-compose down && docker-compose up — это основная комманда которой вы будете пользоваться в разработке если будете делать изменения
Для автоматизации перезагрузки контейнера при изменении файлов на hostе, для node надо копать в сторону pm2-docker
Consul
Консул это сервер, который служит для связывания сервисов воедино (service discovery), поддержания их состояния здоровья (healthcheck) и для их конфигурации без перезапуска (key-value storage)
Каждый поднимающийся сервис сам должен зарегистрировать себя в консуле, указать на каком IP/порте он работает. Сам должен открыть HTTP endpoint который будет выдавать состояние здоровья
Сложности
При создании микросервисов самая сложная часть это граница и управление. Сервис должен отвечать за конкретную бизнес-функцию и доменную область. Это вертикальный срез приложения. Но при этом сервис должен выполнять весь стек работы — ui, backend, db storage, queue processor. Впихивать столько ответсвенности в один сервис технологически сложно, поэтому приходится дробить вертикальный стек ещё на несколько горизонтальных слоёв. Образно был article-manager — стал article-frontend, article-server, article-worker, над которыми нависают ещё всякие сервисы мониторинга. Это тяжело связывать вместе и деплоить разом.
Node
Поскольку нода висит постоянно в памяти, в отличие от php, который запускается при запросе, то возникает проблема перезагрузки кода при его изменении. Вот как выглядит Dockerfile с PM2:
FROM node:6-alpine
USER root
ENV PORT=3000
EXPOSE 3000
RUN npm install pm2 -g
WORKDIR /app
CMD ["pm2-docker", "start", "pm2.json", "--watch"]
Теперь в pm2.json описывается при каком случае надо перезапускать докер сервис
{
"apps": [
{
"name": "article-manager",
"script": "index.js",
"env": {
"PORT": 3000,
"CONSUL_IP": "192.168.10.10",
"CONSUL_PORT": 8500,
"SERVICE_NAME": "article-manager"
},
"watch": true,
"ignore_watch": [
"node_modules",
"npm-debug.log",
".idea",
".git",
"test/coverage"
],
"watch_options": {
"followSymlinks": false
}
}
]
}
Redis
Очень быстрая in-memory база для кеширования данных
version: '2'
services:
redis-master:
image: 'redis:2.8'
network_mode: bridge
volumes:
- ./data:/data
ports:
- 6379:6379
command: redis-server --appendonly yes
Alias
Для удобства, советую добавить в ваш ~/.bashrc или ~/.zshrc алиас на быстрое поднятие контейнера:
alias doc='docker-compose down && docker-compose up'