A simple distributed system implementation with a master-worker architecture using gRPC for communication between nodes.
This project implements a basic distributed system with two types of nodes:
- Master Node: Coordinates tasks and distributes them to worker nodes
- Worker Node: Executes tasks received from the master node
The system uses gRPC for communication between nodes and provides a REST API to submit tasks to the master.
-
Master Node:
- Listens for gRPC connections from worker nodes
- Provides an HTTP API for task submission
- Distributes tasks to connected worker nodes using round-robin load balancing
-
Worker Node:
- Connects to the master via gRPC
- Receives and executes tasks (commands)
- Reports status back to the master
- Supports unique worker IDs and configurable master address
- Go 1.18 or later
- protoc (Protocol Buffers compiler)
# Clone the repository git clone https://github.com/DjonatanS/go-distributed-data-system.git cd go-distributed-data-system # Install dependencies go mod tidyO arquivo principal agora está em cmd/server/main.go e o exemplo de cluster/demo está em example/cluster_demo/main.go.
# Usando argumentos por flag go run cmd/server/main.go -type=master # Para compatibilidade antiga (se aplicável) go run cmd/server/main.go masterIsso irá iniciar:
- Um servidor gRPC na porta 50051 para conexões de workers
- Uma API REST na porta 9092 para submissão de tarefas
# Usando argumentos por flag com ID customizado go run cmd/server/main.go -type=worker -id=worker1 -master=localhost:50051 # Para compatibilidade antiga (se aplicável) go run cmd/server/main.go worker# Inicia um master e 3 workers (padrão) go run cmd/server/main.go -type=cluster # Inicia um master com 5 workers go run cmd/server/main.go -type=cluster -workers=5Execute o exemplo de cluster/demo, que inicia o cluster e envia tarefas automaticamente:
go run example/cluster_demo/main.goVocê pode submeter tarefas para o master usando a API REST:
curl -X POST http://localhost:9092/tasks \ -H "Content-Type: application/json" \ -d '{"cmd":"echo hello world"}'| Endpoint | Method | Description |
|---|---|---|
/tasks | POST | Submit a task to be executed by worker nodes. Request body: {"cmd":"command_to_execute"} |
/workers | GET | Get count of currently connected workers |
The system defines the following gRPC services:
service NodeService { rpc ReportStatus(Request) returns (Response){}; rpc AssignTask(Request) returns (stream Response){}; }-
Initialization:
- The master node starts and listens for gRPC connections
- Worker nodes connect to the master via gRPC and register themselves
-
Task Assignment:
- Tasks are submitted via HTTP to the master's REST API
- The master distributes tasks to workers using round-robin load balancing
- Each task is sent to exactly one worker
-
Command Execution:
- Workers receive commands and execute them using the system's shell
- The execution output is captured and printed on the worker's console
- Workers automatically reconnect if the connection to the master is lost
. ├── cmd/ │ └── server/ │ └── main.go # Entry point principal (CLI) ├── core/ │ ├── node.go # Master node and service implementations │ ├── node.pb.go # Generated protobuf message definitions │ ├── node_grpc.pb.go # Generated gRPC service definitions │ ├── node.proto # Protocol buffer definitions │ ├── worker_node.go # Worker node implementation │ ├── node_test.go # Unit tests for the master node │ └── worker_node_test.go # Unit tests for the worker node ├── example/ │ └── cluster_demo/ │ └── main.go # Exemplo de uso programático do cluster ├── launcher/ │ ├── launcher.go # Package to start both master and workers together │ └── launcher_test.go # Tests for the launcher package ├── go.mod ├── go.sum └── README.md The master node:
- Creates a gRPC server for worker connections
- Maintains a thread-safe registry of connected workers
- Provides a REST API for task submission (using Gin)
- Distributes commands to workers using round-robin load balancing
- Monitors worker connections and removes disconnected workers
The worker node:
- Establishes a gRPC connection to the master
- Has configurable parameters (ID, master address, reconnect delay)
- Creates a streaming connection for receiving tasks
- Executes commands using Go's
execpackage and captures output - Handles reconnection to the master if the connection is lost
- Reports status to the master with its worker ID
The launcher package provides:
- A simple way to start both master and multiple workers from a single import
- Configurable number of workers and other settings
- Clean shutdown handling with proper context cancellation
- Client submits a task to master's REST API
- Master selects a worker using round-robin and sends the task via gRPC stream
- Worker executes the command and displays the output
- If a worker disconnects, the master removes it from the pool
You can also use the launcher package to programmatically start a cluster:
import "github.com/DjonatanS/go-distribuited-data-system/launcher" // Start a cluster with default configuration (1 master + 3 workers) cluster := launcher.StartCluster() // Or customize the configuration config := launcher.DefaultClusterConfig() config.WorkerCount = 5 cluster := launcher.NewCluster(config) cluster.Start() // Later, when finished cluster.Stop()type WorkerConfig struct { ID string // Worker identifier MasterAddr string // Address of the master node (host:port) ReconnectDelay time.Duration // Delay between reconnection attempts }type ClusterConfig struct { MasterPort int // Port for the master's gRPC server (default: 50051) ApiPort int // Port for the master's REST API (default: 9092) WorkerCount int // Number of workers to start (default: 3) MasterHost string // Host for the master node (default: "localhost") BaseWorkerID string // Base prefix for worker IDs (default: "worker") ReconnectDelay time.Duration // Delay between worker reconnection attempts (default: 5s) }The system includes both unit and integration tests:
# Run all tests go test ./... # Run unit tests only go test ./core -run "^Test[^Integration]"If you modify the .proto files, regenerate the Go code:
protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ core/node.proto- More advanced task scheduling and prioritization
- Worker capabilities registration and task routing based on capabilities
- Authentication and security measures
- Better error handling and retry mechanisms
- Persistence of tasks and results
- Web-based administrative UI
[License information]