---
title: Микросервисы 2
date: 2017-07-06T10:00
tags: [backend]
---

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

### Docker

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

- Ставите [Docker для Мака или для Windows](https://www.docker.com/products/docker-toolbox)  
    
- Ставите [dry](https://github.com/moncho/dry) для терминала (по желанию)
- Создаёте Dockerfile
- Создаёте docker-compose.yml
- Запускаете docker-compose up

#### Концепции

**Images (образы)** это изолированная среда, как правило с конкретным языком (node, php) или библиотекой. За это отвечает [Dockerfile](https://docs.docker.com/engine/reference/builder/), который ссылается на существующий, скачиваемый образ на докер хабе.

Что-бы увидеть установленные образы, есть комманда  ****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](http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/)

### 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'
```

## Related

- [Alter sequence](/ru/blog/tech/backend/DB/postgres/alter-sequence/)
- [Amazon S3 direct upload](/ru/blog/tech/backend/amazon-s3-direct-upload/)
- [CUDA](/ru/blog/tech/backend/gpu/cuda/)
