Compartir a través de


Tutorial: Diseño de microservicios con clústeres elásticos

En este tutorial, usará Azure Database for PostgreSQL como back-end de almacenamiento para varios microservicios. En el tutorial se muestra una configuración de ejemplo y una operación básica de este clúster. Obtenga información sobre cómo:

  • Prerrequisitos
  • Creación de roles para los microservicios
  • Uso de la utilidad psql para crear roles y esquemas distribuidos
  • Creación de tablas para los servicios de ejemplo
  • Configurar servicios
  • Ejecución de servicios
  • Exploración de la base de datos

Prerrequisitos

Cree un clúster elástico de una de las maneras siguientes:

Creación de roles para los microservicios

Puede colocar dinámicamente esquemas distribuidos dentro de un clúster elástico. El sistema puede reequilibrarlos como una unidad completa en los nodos disponibles, por lo que obtendrá una mayor eficacia en los recursos del clúster sin asignación manual.

Al aplicar particiones de esquema a un patrón de diseño de microservicios, se crea un esquema de base de datos para cada microservicio correspondiente. Además, use un rol distinto para cada microservicio al conectarse a la base de datos. Cuando cada usuario se conecta, su nombre de rol va al principio del search_path. Si el nombre del rol coincide con el nombre del esquema, no necesita cambios adicionales en la aplicación para establecer el search_path correcto.

En este ejemplo, use tres microservicios:

  • user
  • time
  • ping

Cree los roles de base de datos para cada servicio:

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

Uso de la utilidad psql para crear esquemas distribuidos

Después de conectarse al clúster elástico mediante psql, puede completar algunas tareas básicas.

Puede distribuir un esquema de dos maneras:

  • Para ello, llame manualmente a la citus_schema_distribute(schema_name) función :
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');

Este método también permite convertir esquemas normales existentes en esquemas distribuidos.

Nota:

Solo puede distribuir esquemas que no contengan tablas distribuidas y de referencia.

  • Habilitando la variable de citus.enable_schema_based_sharding configuración. Puede cambiar la variable para la sesión actual o de forma permanente dentro de los parámetros del nodo coordinador. Al establecer el parámetro en ON, todos los esquemas creados se distribuyen de forma predeterminada.
SET citus.enable_schema_based_sharding TO ON;

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

Ejecute el siguiente comando para enumerar los esquemas distribuidos actualmente:

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)

Creación de tablas para los servicios de ejemplo

Ahora puede conectarse al clúster elástico para cada microservicio. En el ejemplo siguiente, la base de datos del clúster elástico se denomina Citus. Desde la sesión de psql, puede usar el comando \c para cambiar a otro usuario.

\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 servicios

En este tutorial, usamos un conjunto sencillo de servicios. Puede obtenerlos mediante la clonación de este repositorio 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

Sin embargo, antes de ejecutar los servicios, edite user/app.py, ping/app.pyy time/app.py los archivos que proporcionan la configuración de conexión para el clúster elástico:

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

Después de realizar los cambios, guarde todos los archivos modificados y continúe con el siguiente paso de ejecución de los servicios.

Ejecución de servicios

Cambie a cada directorio de la aplicación y ejecútelos en su propio entorno de Python.

cd user
pipenv install
pipenv shell
python app.py

Repita los comandos para el servicio de hora y ping, después de lo cual puede usar la API.

Cree algunos usuarios:

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

Enumere los usuarios creados:

curl http://localhost:5000/users

Obtenga la hora actual:

Get current time:

Ejecute el ping en example.com:

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

Exploración de la base de datos

Ahora que ha llamado a algunas funciones de API, los datos se almacenan y puede comprobar si citus_schemas refleja lo que se espera:

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)

Al crear los esquemas, no se indica en qué máquinas se crean los esquemas. Esto se realiza de forma automática. Puede ver dónde reside cada esquema con la siguiente 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 mayor brevedad de la salida de ejemplo en esta página, en lugar de usar nodename como una dirección IP, lo reemplazamos por localhost. Supongamos que localhost:7001 es el nodo uno y localhost:7002 es el nodo dos.

Puede ver que el servicio de hora ha llegado al nodo localhost:7001 mientras el usuario y el servicio ping comparten espacio en el segundo nodo localhost:7002. Las aplicaciones de ejemplo son simplistas y los tamaños de datos aquí son insignificantes, pero supongamos que se ve afectado por el uso desigual del espacio de almacenamiento entre los nodos. Tendría más sentido que los dos servicios más pequeños de tiempo y de ping residieran en un nodo, mientras que el servicio más grande de usuario residiera en su propio nodo.

Puede reequilibrar fácilmente el clúster por tamaño de 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)

Cuando haya terminado, puede comprobar cómo se ve nuestro nuevo diseño:

  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)

Según las expectativas, los esquemas se mueven y tenemos un clúster más equilibrado. Esta operación es transparente para las aplicaciones. Ni siquiera es necesario reiniciarlas, siguen atendiendo consultas.

Paso siguiente