Prática sobre Sidecar Pattern
No artigo sobre o que seria Sidecar Pattern, há uma breve explicação a teria agora vamos para à pratica.
Repositório
Fica localizado no GITHUB
Breve contexto
O padrão de design arquitetônico Sidecar Pattern é usado principalmente em microserviços. Ele envolve o uso de um componente secundário, chamado de “sidecar”, que é instalado ao lado de um serviço principal para fornecer funções adicionais, como monitoramento, segurança, proxy e registro.
Exemplo
Imagine um serviço de autenticação que precisa de registro minucioso de cada pedido. Você pode fazer um sidecar que colete e transmite os registros para um sistema central, em vez de incorporar essa lógica diretamente no serviço. Esse sidecar funciona em conjunto com o serviço principal sem que a configuração seja alterada.
Como funciona:
- O serviço principal continua focado em suas responsabilidades (ex: autenticação).
- O sidecar lida com tarefas complementares (ex: logs, segurança).
Vantagens:
- Separação de responsabilidades.
- Reutilização do sidecar em outros serviços.
- Flexibilidade e escalabilidade.
Esse padrão é muito usado em plataformas como Kubernetes, onde o sidecar é implementado como um container adicional no mesmo pod do serviço principal.
Estrutura de arquivos:
├── __init__.py
├── bff
│ ├── Dockerfile
│ ├── __init__.py
│ └── main.py
├── docker-compose.yml
├── readme.md
└── service
├── Dockerfile
├── __init__.py
└── main.py
1-) Código do serviço principal (bff/main.py):
import requests from fastapi import FastAPI
# Criação de instância do FastAPI
app = FastAPI()
# Função que faz uma chamada a um serviço externo
def call_external_service(url):
response = requests.get(url)
return str(response.json())
# Rota do FastAPI para lidar com a chamada ao serviço externo
@app.get("/home")
def handle_call_service():
service_url = "http://services:8001/v1/services"
try:
data = call_external_service(service_url)
return {"data": data}
except:
print("An exception occurred")
@app.get("/")
def read_root():
return {"message": "Welcome BFF!"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
2-) Dockerfile para o serviço principal (bff/Dockerfile):
FROM python:3.9-slim
WORKDIR /app
RUN pip install --only-binary :all: fastapi[all] requests
COPY . /app
CMD ["python", "main.py"]
3-) Código do sidecar (service/main.py):
from fastapi import FastAPI
# Criação de instância do FastAPI
app = FastAPI()
@app.get("/v1/services")
def read_root():
return {"message": "Welcome Services!"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)
4-) Dockerfile para o sidecar (service/Dockerfile):
FROM python:3.9-slim
WORKDIR /app
RUN pip install --only-binary :all: fastapi[all]
COPY . /app
CMD ["python", "main.py"]
5-) Arquivo docker-compose.yml:
version: '3'
services:
main-bff:
build: ./bff
ports:
- "8000:8000"
depends_on:
- services
services:
build: ./service
ports:
- "8001:8001"
6-) Arquivo docker-compose.yml:
Como executar: No diretório raiz, execute docker-compose up --build.
Acesse o serviço principal em http://localhost:8000/home.
Faça uma requisição POST para http://localhost:8001/v1/services com um JSON e veja o sidecar registrando os logs.
Conclusão
O Sidecar Pattern é uma solução arquitetural poderosa para gerenciar funcionalidades auxiliares em sistemas distribuídos. Ele oferece benefícios como separação de responsabilidades, reutilização de código, escalabilidade e padronização. No entanto, é importante considerar os desafios, como a complexidade adicional e o consumo de recursos, antes de adotar esse padrão.
Se implementado corretamente, o Sidecar Pattern pode ser um divisor de águas, permitindo que equipes de desenvolvimento mantenham o foco na lógica de negócio, enquanto as funcionalidades transversais são gerenciadas de forma eficiente e consistente.