Микросервисы #2

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

Docker

Я сразу скажу что не знаю как настраивать production с докер-контейнерами, но сервисы в рабочем окружении поднимаются тривиально

Концепции

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'