API Gateway - Siger
The API Gateway is the primary entry point for all external client interactions with the Dante GPU Platform. It routes requests to appropriate backend services, handles authentication and authorization, and can perform other cross-cutting concerns like rate limiting and request/response transformation.
1. Responsibilities
The API Gateway has the following key responsibilities:
Request Routing: Directs incoming HTTP requests to the correct microservices (e.g., Auth Service, Provider Registry, Scheduler Orchestrator, Billing Service, Storage Service). This is often based on path prefixes.
Authentication & Authorization: Verifies user identity (typically via JWT tokens) and ensures users have the necessary permissions to access requested resources or perform actions.
Service Discovery: Integrates with Consul to dynamically discover the addresses and ports of backend services.
Load Balancing: Distributes requests across multiple instances of a backend service. While a simple round-robin approach is mentioned, more sophisticated strategies could be implemented.
Job Submission: Provides endpoints for users to submit new compute jobs, which are then published to a NATS stream for the Scheduler Orchestrator to consume.
API Aggregation: Can combine results from multiple services into a single response for the client.
Rate Limiting: (Planned) To prevent abuse and ensure fair usage.
Request/Response Transformation: (Planned) Modifying requests or responses as needed.
2. Tech Stack
The API Gateway is built using:
Programming Language:
GoHTTP Routing:
Chi routerService Discovery:
HashiCorp ConsulMessaging Queue (for job submission): NATS (JetStream)
Logging: Zap for structured logging
Authentication: JWT (JSON Web Tokens)
Configuration: YAML files
3. Core Components and Logic
3.1. Configuration (internal/config/config.go)
The API Gateway's behavior is determined by its configuration file (configs/config.yaml).
Key configuration sections include:
server: Port and host for the HTTP server.consul: Address for the Consul agent and service registration details.nats: NATS server address and subject for job submissions.jwt: Secret key for JWT signing and verification, and token expiry duration.services: Configuration for backend services, including their names in Consul and path prefixes for routing.billing_service: Specific configuration for the billing service client.
3.2. HTTP Server and Routing (cmd/main.go)
The main function initializes the server, logger, Consul client, NATS client, and sets up routing using chi.
Standard middleware for request ID, real IP, logging, panic recovery, and timeout are applied globally.
3.3. Authentication (internal/auth/jwt.go, internal/middleware/auth.go)
JWTs are used for stateless authentication.
JWT Generation (
internal/auth/jwt.go): TheGenerateTokenfunction creates a new JWT signed with a secret key, containing user claims (like UserID, username, roles).JWT Validation (
internal/auth/jwt.go): TheValidateTokenfunction parses and verifies a JWT string.
Auth Middleware (
internal/middleware/auth.go): This middleware extracts the JWT from theAuthorizationheader, validates it, and if valid, injects user information (UserID, roles) into the request context for downstream handlers.
3.4. Service Discovery and Load Balancing (internal/consul/client.go, internal/loadbalancer/balancer.go)
The
ConsulClientdiscovers service instances from Consul.DiscoverServicemethod fetches healthy instances of a given service.The
RoundRobinBalancerselects a service instance using a round-robin strategy.
3.5. Request Proxying (internal/handlers/proxy.go)
The ProxyHandler is responsible for forwarding requests to the discovered backend services. It modifies the request's URL and headers as needed before sending it to the target service.
3.6. Job Submission (internal/handlers/job.go, internal/nats/client.go)
The JobHandler exposes an endpoint (e.g., /jobs/submit) for users to submit compute jobs.
It receives job details in the request body.
The
NatsClientis used to publish the job data to a configured NATS subject.It uses JetStream for ensuring message persistence and delivery.
3.7. Billing Proxy (internal/handlers/billing.go, internal/billing/client.go)
The BillingServiceProxy handler forwards requests to the Billing Payment Service.
The BillingClient in internal/billing/client.go is used by other services (like Scheduler) to interact with the billing service, not directly by the proxy itself, but it shows the model interactions. The proxy handler uses the generic proxy mechanism.
4. API Endpoints
The API Gateway exposes several endpoints:
Auth Endpoints (e.g.,
/auth/):POST /auth/register: User registration.POST /auth/login: User login, returns JWT.GET /auth/users/me: Get current user's details (requires auth).POST /auth/validate: Validates a token (internal or admin use).
Job Submission Endpoint:
POST /jobs/submit: Submits a new compute job (requires auth).
Billing Service Endpoints (e.g.,
/billing/): Proxied to the Billing Payment Service (requires auth).Examples:
/billing/wallets/{userID},/billing/sessions/start,/billing/usage-update.
Provider Registry Endpoints (e.g.,
/providers/): Proxied to the Provider Registry Service.Examples:
GET /providers,GET /providers/{providerID}.
Storage Service Endpoints (e.g.,
/storage/): Proxied to the Storage Service.Examples:
POST /storage/upload/{bucket_name},GET /storage/download/{bucket_name}/{object_key}.
Health Check:
GET /health: Basic health check for the API Gateway itself.
5. Workflow
Startup:
Loads configuration.
Initializes logger, Consul client, NATS client (with JetStream), and HTTP router (Chi).
Registers its own health check with Consul if enabled.
Sets up HTTP handlers for auth, job submission, and generic proxying.
Starts the HTTP server.
Incoming Request:
A client sends an HTTP request to the API Gateway.
Middleware (logging, timeout, etc.) is applied.
Authentication/Authorization (if applicable):
The
AuthMiddlewarechecks for a JWT in theAuthorizationheader.If the token is valid, user information is added to the request context.
If the route or service requires specific roles, these are checked against the user's roles.
Routing & Proxying:
If the request is for a specific handler like
/auth/loginor/jobs/submit, the dedicated handler processes it.For other requests, the generic
ProxyHandlerdetermines the target backend service based on the request path and service configurations.It discovers healthy instances of the target service from Consul.
Selects an instance using the load balancer.
The request is modified (URL, headers) and forwarded to the chosen backend instance.
The response from the backend service is streamed back to the client.
Job Submission Workflow:
User calls
POST /jobs/submitwith job details.After authentication, the
JobHandlermarshals the job request and publishes it to the configured NATS subject usingnatsClient.PublishJob.The API Gateway responds to the user with an acceptance (e.g.,
202 Accepted).
Shutdown:
Receives SIGINT or SIGTERM.
Deregisters from Consul (if applicable).
Gracefully shuts down the NATS client and HTTP server.
6. Future Considerations
Rate Limiting: Implement service-level and global rate limiting.
Caching: Implement caching for frequently accessed, static data.
Request/Response Transformation: Add capabilities for more complex transformations if needed.
WebSockets: Support for WebSocket proxying if real-time bidirectional communication is required for some services.
Advanced Load Balancing: Implement more sophisticated load balancing strategies (e.g., least connections, weighted round-robin).
Circuit Breaking: Implement circuit breaker patterns for improved resilience when backend services are down or slow.
Distributed Tracing: Integrate with a distributed tracing system (e.g., Jaeger, Zipkin) for better observability across microservices.
API Versioning: Strategy for managing multiple versions of APIs.
Last updated