Turbine
A modular service framework.
Launchpad (Process Manager)
The launchpad is a CLI tool located in pkg/launchpad designed to simplify development and production workflows for the entire Turbine project. It acts as a process manager that can run all defined services concurrently for development and generate a docker-compose.yml file for production deployments.
Configuration (launchpad.toml)
The launchpad is configured via a launchpad.toml file in the project root. This file defines all the services, their configurations, and the networks they use.
launchpad.toml example:
# Defines variables required by the configuration.
# These should be supplied in a .env file.
[variables]
required = ["CACHE_PASSWORD", "QUEUE_PASSWORD", "RING_IMAGE", "RING_PORT"]
# Defines docker networks.
[networks]
aspire = {}
# Service definitions
[[services]]
name = "cache"
type = "docker" # For third-party docker images
[services.prod]
image = "docker.io/library/redis:7.4"
command = ["/bin/sh", "-c", "redis-server --requirepass $$REDIS_PASSWORD"]
environment = ["REDIS_PASSWORD=${CACHE_PASSWORD}"]
expose = ["6379"]
networks = ["aspire"]
[[services]]
name = "ring"
type = "dotnet"
path = "../turbine-dotnet-services/ring"
[services.dev]
command = "dotnet watch run"
[services.prod]
image = "${RING_IMAGE}"
environment = [
"HTTP_PORTS=${RING_PORT}",
"ConnectionStrings__cache=cache:6379,password=${CACHE_PASSWORD}",
]
volumes = ["./keys:/app/keys", "./settings/ring.json:/app/appsettings.json"]
expose = ["${RING_PORT}", "5001"]
networks = ["aspire"]
depends_on = ["cache", "queue"]
Environment Variables (.env)
For the deploy command to work, you must create a .env file in the project root containing the variables defined in launchpad.toml. An example is provided in .env.example.
Commands
To use the launchpad, run its main.go file with one of the following commands:
Development (dev)
Starts all services defined in launchpad.toml in development mode. Each service runs in a separate process, and their logs are streamed to the console with colored prefixes. A single Ctrl+C will gracefully shut down all services.
go run ./pkg/launchpad/main.go dev
Production Deployment (deploy)
Generates a docker-compose.yml file in the project root based on the prod configuration of all services in launchpad.toml. It substitutes variables from your .env file. This file can be used to build and run all services as Docker containers.
go run ./pkg/launchpad/main.go deploy
Registrar
The Registrar is the service discovery system of the DysonNetwork. Here are a port to the Golang in order to support other Golang services.
To use the system, try build with these API:
package main
import (
"log"
"os"
"os/signal"
"syscall"
"yourmodule/registry"
)
func main() {
endpoints := []string{"localhost:2379"}
registrar, err := registry.NewServiceRegistrar(endpoints)
if err != nil {
log.Fatalf("Error creating registrar: %v", err)
}
serviceName := "orders"
host := "10.0.0.5"
port := 5000
ttl := int64(30)
err = registrar.Register(serviceName, "http", "instance-1", host, port, ttl)
if err != nil {
log.Fatalf("Register error: %v", err)
}
log.Println("Service registered")
// Wait for termination
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop
err = registrar.Deregister()
if err != nil {
log.Printf("Deregister error: %v", err)
} else {
log.Println("Service deregistered")
}
}
Gateway
The gateway is the entry point for all requests. It uses the registrar to discover services in real-time from etcd and forwards requests to the appropriate service instances.
Features
- Service Discovery: Automatically discovers
httpservices from etcd. - Dynamic Routing: Maintains an in-memory routing table that is automatically updated when services are added or removed.
- Request Proxying: Forwards incoming requests to the correct service instance based on the URL path (
/<service-name>/...). - Load Balancing: Implements round-robin load balancing across service instances.
- Route Overrides: Allows for custom routing rules to be defined in the configuration file.
Configuration
The gateway is configured via a settings.toml file located in the same directory.
# The address the gateway will listen on
listen = ":8080"
# ETCD configuration for service discovery
[etcd]
endpoints = ["127.0.0.1:2379"]
# Set to true if your etcd server does not use TLS
insecure = true
# Custom route overrides
# The key is the incoming path prefix.
# The value is the destination in the format "/<service_name>/<path_prefix>"
[routes]
"/websocket" = "/chatter/ws"
Config Service
The config service provides a centralized location for other services to fetch their configuration. This is useful for managing connection strings, feature flags, and other shared parameters without hardcoding them into each service.
Usage
The config service reads a shared_config.toml file from its own directory (pkg/config) and serves it as a JSON object over a simple HTTP endpoint.
To retrieve the configuration, other services can make a GET request to the gateway at /config. The gateway will route the request to an available instance of the config service.
Example with curl:
curl http://localhost:8080/config
Expected Response (JSON):
{
"database": {
"connection_string": "postgres://user:password@db-host:5432/mydatabase?sslmode=require"
},
"redis": {
"address": "redis-host:6379"
}
}