Tutorial: Projeto de microsserviços com clusters flexíveis

Neste tutorial, você usará o Banco de Dados do Azure para PostgreSQL como o back-end de armazenamento para vários microsserviços. O tutorial demonstra uma configuração de exemplo e uma operação básica desse cluster. Saiba como:

  • Pré-requisitos
  • Criar funções para seus microsserviços
  • Usar o utilitário psql para criar funções e esquemas distribuídos
  • Criar tabelas para os serviços de exemplo
  • Configurar serviços
  • Executar serviços
  • Explore o banco de dados

Pré-requisitos

Crie um cluster elástico de uma das seguintes maneiras:

Criar funções para seus microsserviços

Você pode colocar dinamicamente esquemas distribuídos em um cluster elástico. O sistema pode rebalanceá-los como uma unidade inteira entre os nós disponíveis, para que você obtenha uma eficiência aprimorada em seus recursos de cluster sem alocação manual.

Ao aplicar a fragmentação de esquema a um padrão de design de microsserviço, você cria um esquema de banco de dados para cada microsserviço correspondente. Além disso, use uma FUNÇÃO distinta para cada microsserviço ao se conectar ao banco de dados. Quando cada usuário se conecta, seu nome de função vai no início do search_path. Se o nome da função corresponder ao nome do esquema, você não precisará de nenhuma alteração adicional do aplicativo para definir o search_path correto.

Neste exemplo, use três microsserviços:

  • usuário
  • time
  • executar ping

Crie as funções de banco de dados para cada serviço:

CREATE USER user_service;
CREATE USER time_service;
CREATE USER ping_service;

Usar o utilitário psql para criar esquemas distribuídos

Depois de se conectar ao cluster elástico usando psql, você pode concluir algumas tarefas básicas.

Você pode distribuir um esquema de duas maneiras:

  • Manualmente chamando a função citus_schema_distribute(schema_name):
CREATE SCHEMA AUTHORIZATION user_service;
CREATE SCHEMA AUTHORIZATION time_service;
CREATE SCHEMA AUTHORIZATION ping_service;

SELECT citus_schema_distribute('user_service');
SELECT citus_schema_distribute('time_service');
SELECT citus_schema_distribute('ping_service');

Esse método também permite converter os esquemas regulares existentes em esquemas distribuídos.

Observação

Você só pode distribuir esquemas que não contêm tabelas distribuídas e de referência.

  • Habilitando a citus.enable_schema_based_sharding variável de configuração. Você pode alterar a variável para a sessão atual ou permanentemente nos parâmetros do nó coordenador. Quando você define o parâmetro como ON, todos os esquemas criados são distribuídos por padrão.
SET citus.enable_schema_based_sharding TO ON;

CREATE SCHEMA AUTHORIZATION user_service;
CREATE SCHEMA AUTHORIZATION time_service;
CREATE SCHEMA AUTHORIZATION ping_service;

Execute o seguinte comando para listar os esquemas distribuídos no momento:

SELECT * FROM citus_schemas;
 schema_name | colocation_id | schema_size | schema_owner
-------------+---------------+-------------+--------------
 user_service |             5 | 0 bytes     | user_service
 time_service |             6 | 0 bytes     | time_service
 ping_service |             7 | 0 bytes     | ping_service
(3 rows)

Criar tabelas para os serviços de exemplo

Agora você pode se conectar ao cluster elástico para cada microsserviço. No exemplo a seguir, o banco de dados de cluster elástico se chama Citus. Na sessão psql, você pode usar o comando \c para alternar para outro usuário.

\c citus user_service
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);
\c citus time_service
CREATE TABLE query_details (
    id SERIAL PRIMARY KEY,
    ip_address INET NOT NULL,
    query_time TIMESTAMP NOT NULL
);
\c citus ping_service
CREATE TABLE ping_results (
    id SERIAL PRIMARY KEY,
    host VARCHAR(255) NOT NULL,
    result TEXT NOT NULL
);

Configurar serviços

Neste tutorial, usamos um conjunto simples de serviços. Você pode obtê-los clonando este repositório público:

git clone https://github.com/citusdata/citus-example-microservices.git
$ tree
.
├── LICENSE
├── README.md
├── ping
│   ├── app.py
│   ├── ping.sql
│   └── requirements.txt
├── time
│   ├── app.py
│   ├── requirements.txt
│   └── time.sql
└── user
    ├── app.py
    ├── requirements.txt
    └── user.sql

No entanto, antes de executar os serviços, edite user/app.pyping/app.pye os time/app.py arquivos que fornecem a configuração de conexão para o cluster elástico:

# Database configuration
db_config = {
    'host': 'EXAMPLE.postgres.database.azure.com',
    'database': 'postgres',
    'password': 'SECRET',
    'user': 'ping_service',
    'port': 5432
}

Depois de fazer as alterações, salve todos os arquivos modificados e passe para a próxima etapa de execução dos serviços.

Executar serviços

Altere em cada diretório de aplicativo e execute-os em seu próprio ambiente Python.

cd user
pipenv install
pipenv shell
python app.py

Repita os comandos para o serviço de tempo e de ping, após o qual você pode usar a API.

Crie alguns usuários:

curl -X POST -H "Content-Type: application/json" -d '[
  {"name": "John Doe", "email": "john@example.com"},
  {"name": "Jane Smith", "email": "jane@example.com"},
  {"name": "Mike Johnson", "email": "mike@example.com"},
  {"name": "Emily Davis", "email": "emily@example.com"},
  {"name": "David Wilson", "email": "david@example.com"},
  {"name": "Sarah Thompson", "email": "sarah@example.com"},
  {"name": "Alex Miller", "email": "alex@example.com"},
  {"name": "Olivia Anderson", "email": "olivia@example.com"},
  {"name": "Daniel Martin", "email": "daniel@example.com"},
  {"name": "Sophia White", "email": "sophia@example.com"}
]' http://localhost:5000/users

Listar os usuários criados:

curl http://localhost:5000/users

Obtenha a hora atual:

Get current time:

Execute o ping em example.com:

curl -X POST -H "Content-Type: application/json" -d '{"host": "example.com"}' http://localhost:5002/ping

Explore o banco de dados

Agora que você chamou algumas funções de API, os dados são armazenados e você pode verificar se citus_schemas reflete o que é esperado:

SELECT * FROM citus_schemas;
 schema_name | colocation_id | schema_size | schema_owner
-------------+---------------+-------------+--------------
 user_service |             1 | 112 kB      | user_service
 time_service |             2 | 32 kB       | time_service
 ping_service |             3 | 32 kB       | ping_service
(3 rows)

Quando você criou os esquemas, não indicou em quais computadores criar os esquemas. Isso foi feito automaticamente. Você pode ver onde cada esquema reside com a seguinte consulta:

  SELECT nodename,nodeport, table_name, pg_size_pretty(sum(shard_size))
  FROM citus_shards
  GROUP BY nodename,nodeport, table_name;
nodename  | nodeport |         table_name         | pg_size_pretty
-----------+----------+---------------------------+----------------
 localhost |     7001 | time_service.query_details | 32 kB
 localhost |     7002 | user_service.users         | 112 kB
 localhost |     7002 | ping_service.ping_results  | 32 kB

Para obter a brevidade da saída de exemplo nesta página, em vez de usar nodename como um endereço de IP, nós o substituímos pelo localhost. Suponha que localhost:7001 é o nó um e localhost:7002 é o nó dois.

Você pode ver que o serviço de hora pousou no nó localhost:7001 enquanto o usuário e o serviço de ping compartilham espaço no segundo nó localhost:7002. Os aplicativos de exemplo são simplistas e os tamanhos de dados aqui são insignificantes, mas vamos supor que você seja afetado pela utilização de espaço de armazenamento desigual entre os nós. Seria mais lógico ter os dois menores serviços de tempo e ping residindo em um nó, enquanto o maior serviço de usuário reside em seu próprio nó.

Você pode reequilibrar facilmente o cluster pelo tamanho do disco:

SELECT citus_rebalance_start();
NOTICE:  Scheduled 1 moves as job 1
DETAIL:  Rebalance scheduled as background job
HINT:  To monitor progress, run: SELECT * FROM citus_rebalance_status();
 citus_rebalance_start
-----------------------
                     1
(1 row)

Quando terminar, você pode verificar a aparência do novo layout:

  SELECT nodename,nodeport, table_name, pg_size_pretty(sum(shard_size))
  FROM citus_shards
  GROUP BY nodename,nodeport, table_name;
 nodename  | nodeport |         table_name        | pg_size_pretty
-----------+----------+---------------------------+----------------
 localhost |     7001 | time_service.query_details | 32 kB
 localhost |     7001 | ping_service.ping_results  | 32 kB
 localhost |     7002 | user_service.users         | 112 kB
(3 rows)

De acordo com as expectativas, os esquemas são movidos e temos um cluster mais equilibrado. Essa operação é transparente para os aplicativos. Você nem precisa reiniciá-los, eles continuam atendendo consultas.

Próxima etapa