☕ 🏗️ Microservices Architecture with TuskLang Java

Java Documentation

🏗️ Microservices Architecture with TuskLang Java

"We don't bow to any king" - Microservices Java Edition

TuskLang Java enables building microservices architectures with service discovery, API Gateway, and distributed patterns that scale independently and communicate seamlessly.

🎯 Microservices Architecture Overview

Microservices Configuration

// microservices-app.tsk
[microservices]
name: "Enterprise Microservices Platform"
version: "3.0.0"
architecture: "microservices"
service_mesh: "istio"

[service_registry] type: "eureka" host: @env("EUREKA_HOST", "localhost") port: @env("EUREKA_PORT", "8761") secure: false instance_id: @env("INSTANCE_ID", "microservice-instance") app_name: @env("APP_NAME", "microservice-app")

[api_gateway] name: "api-gateway" port: 8080 host: "0.0.0.0" cors: { allowed_origins: ["https://app.example.com", "https://admin.example.com"] allowed_methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"] allowed_headers: ["Content-Type", "Authorization", "X-Requested-With"] allow_credentials: true max_age: 3600 }

rate_limiting: { enabled: true requests_per_minute: 1000 burst_size: 100 user_based: true }

circuit_breaker: { enabled: true failure_threshold: 5 recovery_timeout: "30s" half_open_state: true }

[services] user_service: { name: "user-service" port: 8081 health_check: "/actuator/health" dependencies: ["database", "cache"] api_version: "v1" load_balancer: "round-robin" retry_policy: { max_attempts: 3 backoff: "exponential" initial_delay: "1s" } circuit_breaker: { failure_threshold: 3 recovery_timeout: "60s" half_open_state: true } metrics: { enabled: true endpoint: "/actuator/metrics" custom_metrics: ["request_duration", "error_rate", "active_connections"] } }

order_service: { name: "order-service" port: 8082 health_check: "/actuator/health" dependencies: ["database", "payment_service", "inventory_service"] api_version: "v1" load_balancer: "least_connections" retry_policy: { max_attempts: 5 backoff: "exponential" initial_delay: "2s" } circuit_breaker: { failure_threshold: 5 recovery_timeout: "120s" half_open_state: true } saga_coordinator: { enabled: true timeout: "5m" compensation_enabled: true } }

payment_service: { name: "payment-service" port: 8083 health_check: "/actuator/health" dependencies: ["database", "external_payment_gateway"] api_version: "v1" load_balancer: "round-robin" retry_policy: { max_attempts: 3 backoff: "exponential" initial_delay: "1s" } circuit_breaker: { failure_threshold: 2 recovery_timeout: "300s" half_open_state: true } idempotency: { enabled: true key_header: "X-Idempotency-Key" ttl: "24h" } }

inventory_service: { name: "inventory-service" port: 8084 health_check: "/actuator/health" dependencies: ["database", "cache"] api_version: "v1" load_balancer: "round-robin" retry_policy: { max_attempts: 3 backoff: "exponential" initial_delay: "1s" } circuit_breaker: { failure_threshold: 10 recovery_timeout: "60s" half_open_state: false } cache_strategy: { ttl: "5m" invalidation: "write_through" } }

notification_service: { name: "notification-service" port: 8085 health_check: "/actuator/health" dependencies: ["email_service", "sms_service", "push_service"] api_version: "v1" load_balancer: "round-robin" retry_policy: { max_attempts: 3 backoff: "exponential" initial_delay: "1s" } circuit_breaker: { failure_threshold: 3 recovery_timeout: "60s" half_open_state: true } async_processing: { enabled: true queue_size: 1000 worker_threads: 10 } }

[databases] user_db: { type: "postgresql" host: @env("USER_DB_HOST", "localhost") port: @env("USER_DB_PORT", "5432") name: @env("USER_DB_NAME", "user_service") user: @env("USER_DB_USER", "user_service_user") password: @env.secure("USER_DB_PASSWORD") pool_size: 20 connection_timeout: "30s" }

order_db: { type: "postgresql" host: @env("ORDER_DB_HOST", "localhost") port: @env("ORDER_DB_PORT", "5432") name: @env("ORDER_DB_NAME", "order_service") user: @env("ORDER_DB_USER", "order_service_user") password: @env.secure("ORDER_DB_PASSWORD") pool_size: 30 connection_timeout: "30s" }

payment_db: { type: "postgresql" host: @env("PAYMENT_DB_HOST", "localhost") port: @env("PAYMENT_DB_PORT", "5432") name: @env("PAYMENT_DB_NAME", "payment_service") user: @env("PAYMENT_DB_USER", "payment_service_user") password: @env.secure("PAYMENT_DB_PASSWORD") pool_size: 15 connection_timeout: "30s" }

inventory_db: { type: "postgresql" host: @env("INVENTORY_DB_HOST", "localhost") port: @env("INVENTORY_DB_PORT", "5432") name: @env("INVENTORY_DB_NAME", "inventory_service") user: @env("INVENTORY_DB_USER", "inventory_service_user") password: @env.secure("INVENTORY_DB_PASSWORD") pool_size: 25 connection_timeout: "30s" }

[cache] redis: { type: "redis" mode: "cluster" nodes: [ { host: @env("REDIS_NODE_1", "redis-node-1") port: @env("REDIS_PORT", "6379") }, { host: @env("REDIS_NODE_2", "redis-node-2") port: @env("REDIS_PORT", "6379") }, { host: @env("REDIS_NODE_3", "redis-node-3") port: @env("REDIS_PORT", "6379") } ] password: @env.secure("REDIS_PASSWORD") ttl: "1h" max_memory: "4gb" }

[message_broker] kafka: { bootstrap_servers: [ @env("KAFKA_BROKER_1", "kafka-1:9092"), @env("KAFKA_BROKER_2", "kafka-2:9092"), @env("KAFKA_BROKER_3", "kafka-3:9092") ] security: { sasl_mechanism: "PLAIN" username: @env.secure("KAFKA_USERNAME") password: @env.secure("KAFKA_PASSWORD") } topics: { user_events: { partitions: 10 replication_factor: 3 retention: "7d" } order_events: { partitions: 20 replication_factor: 3 retention: "30d" } payment_events: { partitions: 15 replication_factor: 3 retention: "90d" } inventory_events: { partitions: 12 replication_factor: 3 retention: "7d" } } }

[monitoring] distributed_tracing: { enabled: true sampling_rate: 0.1 exporter: "jaeger" endpoint: @env("JAEGER_ENDPOINT", "http://jaeger:14268/api/traces") correlation_id_header: "X-Correlation-ID" }

metrics: { prometheus: { enabled: true endpoint: "/actuator/prometheus" scrape_interval: "15s" } custom_metrics: [ "request_duration", "error_rate", "active_connections", "circuit_breaker_state", "cache_hit_rate" ] }

health_checks: { liveness: { path: "/actuator/health/liveness" timeout: "5s" initial_delay: "30s" period: "10s" } readiness: { path: "/actuator/health/readiness" timeout: "5s" initial_delay: "5s" period: "5s" } startup: { path: "/actuator/health/startup" timeout: "5s" initial_delay: "0s" period: "10s" } }

[security] jwt: { secret: @env.secure("JWT_SECRET") algorithm: "HS256" expiration: "24h" refresh_expiration: "7d" issuer: @env("JWT_ISSUER", "microservices-platform") audience: @env("JWT_AUDIENCE", "microservices-users") }

oauth: { providers: { google: { client_id: @env.secure("GOOGLE_CLIENT_ID") client_secret: @env.secure("GOOGLE_CLIENT_SECRET") redirect_uri: @env("GOOGLE_REDIRECT_URI") scopes: ["openid", "email", "profile"] } github: { client_id: @env.secure("GITHUB_CLIENT_ID") client_secret: @env.secure("GITHUB_CLIENT_SECRET") redirect_uri: @env("GITHUB_REDIRECT_URI") scopes: ["read:user", "user:email"] } } }

[deployment] kubernetes: { enabled: true namespace: @env("K8S_NAMESPACE", "microservices") replicas: { user_service: 3 order_service: 5 payment_service: 2 inventory_service: 3 notification_service: 2 } resources: { requests: { cpu: "500m" memory: "512Mi" } limits: { cpu: "1000m" memory: "1Gi" } } autoscaling: { enabled: true min_replicas: 2 max_replicas: 10 target_cpu_utilization: 70 } }

🚪 API Gateway Implementation

Spring Cloud Gateway Configuration

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.tusklang.java.annotations.TuskConfig;
import java.time.Duration;

@Configuration @TuskConfig public class ApiGatewayConfiguration { private final MicroservicesConfig microservicesConfig; public ApiGatewayConfiguration(MicroservicesConfig microservicesConfig) { this.microservicesConfig = microservicesConfig; } @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() // User Service Routes .route("user_service", r -> r .path("/api/v1/users/**") .filters(f -> f .rewritePath("/api/v1/users/(?<segment>.*)", "/${segment}") .addRequestHeader("X-Service-Name", "user-service") .circuitBreaker(config -> config .setName("user-service-circuit-breaker") .setFallbackUri("forward:/fallback/user-service")) .retry(config -> config .setRetries(3) .setMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE) .setBackoff(Duration.ofSeconds(1), Duration.ofSeconds(5), 2, true)) .requestRateLimiter(config -> config .setRateLimiter(redisRateLimiter()) .setKeyResolver(userKeyResolver()))) .uri("lb://user-service")) // Order Service Routes .route("order_service", r -> r .path("/api/v1/orders/**") .filters(f -> f .rewritePath("/api/v1/orders/(?<segment>.*)", "/${segment}") .addRequestHeader("X-Service-Name", "order-service") .circuitBreaker(config -> config .setName("order-service-circuit-breaker") .setFallbackUri("forward:/fallback/order-service")) .retry(config -> config .setRetries(5) .setMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE) .setBackoff(Duration.ofSeconds(2), Duration.ofSeconds(10), 2, true)) .requestRateLimiter(config -> config .setRateLimiter(redisRateLimiter()) .setKeyResolver(userKeyResolver()))) .uri("lb://order-service")) // Payment Service Routes .route("payment_service", r -> r .path("/api/v1/payments/**") .filters(f -> f .rewritePath("/api/v1/payments/(?<segment>.*)", "/${segment}") .addRequestHeader("X-Service-Name", "payment-service") .circuitBreaker(config -> config .setName("payment-service-circuit-breaker") .setFallbackUri("forward:/fallback/payment-service")) .retry(config -> config .setRetries(3) .setMethods(HttpMethod.GET, HttpMethod.POST) .setBackoff(Duration.ofSeconds(1), Duration.ofSeconds(5), 2, true)) .requestRateLimiter(config -> config .setRateLimiter(redisRateLimiter()) .setKeyResolver(userKeyResolver()))) .uri("lb://payment-service")) // Inventory Service Routes .route("inventory_service", r -> r .path("/api/v1/inventory/**") .filters(f -> f .rewritePath("/api/v1/inventory/(?<segment>.*)", "/${segment}") .addRequestHeader("X-Service-Name", "inventory-service") .circuitBreaker(config -> config .setName("inventory-service-circuit-breaker") .setFallbackUri("forward:/fallback/inventory-service")) .retry(config -> config .setRetries(3) .setMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT) .setBackoff(Duration.ofSeconds(1), Duration.ofSeconds(5), 2, true)) .requestRateLimiter(config -> config .setRateLimiter(redisRateLimiter()) .setKeyResolver(userKeyResolver()))) .uri("lb://inventory-service")) // Notification Service Routes .route("notification_service", r -> r .path("/api/v1/notifications/**") .filters(f -> f .rewritePath("/api/v1/notifications/(?<segment>.*)", "/${segment}") .addRequestHeader("X-Service-Name", "notification-service") .circuitBreaker(config -> config .setName("notification-service-circuit-breaker") .setFallbackUri("forward:/fallback/notification-service")) .retry(config -> config .setRetries(3) .setMethods(HttpMethod.GET, HttpMethod.POST) .setBackoff(Duration.ofSeconds(1), Duration.ofSeconds(5), 2, true)) .requestRateLimiter(config -> config .setRateLimiter(redisRateLimiter()) .setKeyResolver(userKeyResolver()))) .uri("lb://notification-service")) .build(); } @Bean public RedisRateLimiter redisRateLimiter() { ApiGatewayConfig config = microservicesConfig.getApiGateway(); return new RedisRateLimiter( config.getRateLimiting().getRequestsPerMinute(), config.getRateLimiting().getBurstSize() ); } @Bean public KeyResolver userKeyResolver() { return exchange -> { String userKey = exchange.getRequest().getHeaders().getFirst("X-User-Key"); if (userKey != null) { return Mono.just(userKey); } return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()); }; } }

@TuskConfig public class MicroservicesConfig { private String name; private String version; private String architecture; private String serviceMesh; private ServiceRegistryConfig serviceRegistry; private ApiGatewayConfig apiGateway; private Map<String, ServiceConfig> services; private Map<String, DatabaseConfig> databases; private CacheConfig cache; private MessageBrokerConfig messageBroker; private MonitoringConfig monitoring; private SecurityConfig security; private DeploymentConfig deployment; // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getArchitecture() { return architecture; } public void setArchitecture(String architecture) { this.architecture = architecture; } public String getServiceMesh() { return serviceMesh; } public void setServiceMesh(String serviceMesh) { this.serviceMesh = serviceMesh; } public ServiceRegistryConfig getServiceRegistry() { return serviceRegistry; } public void setServiceRegistry(ServiceRegistryConfig serviceRegistry) { this.serviceRegistry = serviceRegistry; } public ApiGatewayConfig getApiGateway() { return apiGateway; } public void setApiGateway(ApiGatewayConfig apiGateway) { this.apiGateway = apiGateway; } public Map<String, ServiceConfig> getServices() { return services; } public void setServices(Map<String, ServiceConfig> services) { this.services = services; } public Map<String, DatabaseConfig> getDatabases() { return databases; } public void setDatabases(Map<String, DatabaseConfig> databases) { this.databases = databases; } public CacheConfig getCache() { return cache; } public void setCache(CacheConfig cache) { this.cache = cache; } public MessageBrokerConfig getMessageBroker() { return messageBroker; } public void setMessageBroker(MessageBrokerConfig messageBroker) { this.messageBroker = messageBroker; } public MonitoringConfig getMonitoring() { return monitoring; } public void setMonitoring(MonitoringConfig monitoring) { this.monitoring = monitoring; } public SecurityConfig getSecurity() { return security; } public void setSecurity(SecurityConfig security) { this.security = security; } public DeploymentConfig getDeployment() { return deployment; } public void setDeployment(DeploymentConfig deployment) { this.deployment = deployment; } }

@TuskConfig public class ApiGatewayConfig { private String name; private int port; private String host; private CorsConfig cors; private RateLimitingConfig rateLimiting; private CircuitBreakerConfig circuitBreaker; // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public CorsConfig getCors() { return cors; } public void setCors(CorsConfig cors) { this.cors = cors; } public RateLimitingConfig getRateLimiting() { return rateLimiting; } public void setRateLimiting(RateLimitingConfig rateLimiting) { this.rateLimiting = rateLimiting; } public CircuitBreakerConfig getCircuitBreaker() { return circuitBreaker; } public void setCircuitBreaker(CircuitBreakerConfig circuitBreaker) { this.circuitBreaker = circuitBreaker; } }

🔄 Service Discovery Implementation

Eureka Client Configuration

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.tusklang.java.annotations.TuskConfig;

@Configuration @EnableEurekaClient @TuskConfig public class ServiceDiscoveryConfiguration { private final MicroservicesConfig microservicesConfig; public ServiceDiscoveryConfiguration(MicroservicesConfig microservicesConfig) { this.microservicesConfig = microservicesConfig; } @Bean public EurekaInstanceConfigBean eurekaInstanceConfigBean() { ServiceRegistryConfig registry = microservicesConfig.getServiceRegistry(); EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(); config.setInstanceId(registry.getInstanceId()); config.setAppName(registry.getAppName()); config.setSecurePortEnabled(registry.isSecure()); config.setNonSecurePortEnabled(!registry.isSecure()); // Health check configuration config.setHealthCheckUrlPath("/actuator/health"); config.setStatusPageUrlPath("/actuator/info"); // Lease configuration config.setLeaseRenewalIntervalInSeconds(30); config.setLeaseExpirationDurationInSeconds(90); // Metadata config.getMetadataMap().put("version", microservicesConfig.getVersion()); config.getMetadataMap().put("zone", "default"); return config; } @Bean public EurekaClientConfigBean eurekaClientConfigBean() { ServiceRegistryConfig registry = microservicesConfig.getServiceRegistry(); EurekaClientConfigBean config = new EurekaClientConfigBean(); config.setServiceUrl(Map.of( "defaultZone", String.format("http://%s:%d/eureka/", registry.getHost(), registry.getPort()) )); config.setRegisterWithEureka(true); config.setFetchRegistry(true); config.setRegistryFetchIntervalSeconds(30); return config; } }

@TuskConfig public class ServiceRegistryConfig { private String type; private String host; private int port; private boolean secure; private String instanceId; private String appName; // Getters and setters public String getType() { return type; } public void setType(String type) { this.type = type; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public boolean isSecure() { return secure; } public void setSecure(boolean secure) { this.secure = secure; } public String getInstanceId() { return instanceId; } public void setInstanceId(String instanceId) { this.instanceId = instanceId; } public String getAppName() { return appName; } public void setAppName(String appName) { this.appName = appName; } }

Service Communication

import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;

@Configuration @EnableFeignClients public class ServiceCommunicationConfiguration { @Bean @LoadBalanced public RestTemplate loadBalancedRestTemplate() { return new RestTemplate(); } @Bean public ServiceCommunicationService serviceCommunicationService( RestTemplate restTemplate, MicroservicesConfig microservicesConfig) { return new ServiceCommunicationService(restTemplate, microservicesConfig); } }

@Service public class ServiceCommunicationService { private final RestTemplate restTemplate; private final MicroservicesConfig microservicesConfig; private final CircuitBreakerFactory circuitBreakerFactory; public ServiceCommunicationService(RestTemplate restTemplate, MicroservicesConfig microservicesConfig, CircuitBreakerFactory circuitBreakerFactory) { this.restTemplate = restTemplate; this.microservicesConfig = microservicesConfig; this.circuitBreakerFactory = circuitBreakerFactory; } public <T> T callService(String serviceName, String endpoint, Class<T> responseType) { ServiceConfig serviceConfig = microservicesConfig.getServices().get(serviceName); if (serviceConfig == null) { throw new ServiceNotFoundException("Service not found: " + serviceName); } CircuitBreaker circuitBreaker = circuitBreakerFactory.create(serviceName + "-circuit-breaker"); return circuitBreaker.run( () -> { String url = String.format("http://%s%s", serviceName, endpoint); return restTemplate.getForObject(url, responseType); }, throwable -> { log.error("Circuit breaker opened for service: {}", serviceName, throwable); return handleFallback(serviceName, endpoint, responseType); } ); } public <T> T callServiceWithRetry(String serviceName, String endpoint, Class<T> responseType, int maxAttempts) { ServiceConfig serviceConfig = microservicesConfig.getServices().get(serviceName); if (serviceConfig == null) { throw new ServiceNotFoundException("Service not found: " + serviceName); } RetryPolicyConfig retryPolicy = serviceConfig.getRetryPolicy(); return Retry.decorateSupplier( RetryConfig.custom() .maxAttempts(maxAttempts) .waitDuration(Duration.parse(retryPolicy.getInitialDelay())) .retryExceptions(Exception.class) .build(), () -> { String url = String.format("http://%s%s", serviceName, endpoint); return restTemplate.getForObject(url, responseType); } ).get(); } private <T> T handleFallback(String serviceName, String endpoint, Class<T> responseType) { // Implement fallback logic log.warn("Using fallback for service: {} endpoint: {}", serviceName, endpoint); return null; // Return default value or cached response } }

@TuskConfig public class ServiceConfig { private String name; private int port; private String healthCheck; private List<String> dependencies; private String apiVersion; private String loadBalancer; private RetryPolicyConfig retryPolicy; private CircuitBreakerConfig circuitBreaker; private MetricsConfig metrics; // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getHealthCheck() { return healthCheck; } public void setHealthCheck(String healthCheck) { this.healthCheck = healthCheck; } public List<String> getDependencies() { return dependencies; } public void setDependencies(List<String> dependencies) { this.dependencies = dependencies; } public String getApiVersion() { return apiVersion; } public void setApiVersion(String apiVersion) { this.apiVersion = apiVersion; } public String getLoadBalancer() { return loadBalancer; } public void setLoadBalancer(String loadBalancer) { this.loadBalancer = loadBalancer; } public RetryPolicyConfig getRetryPolicy() { return retryPolicy; } public void setRetryPolicy(RetryPolicyConfig retryPolicy) { this.retryPolicy = retryPolicy; } public CircuitBreakerConfig getCircuitBreaker() { return circuitBreaker; } public void setCircuitBreaker(CircuitBreakerConfig circuitBreaker) { this.circuitBreaker = circuitBreaker; } public MetricsConfig getMetrics() { return metrics; } public void setMetrics(MetricsConfig metrics) { this.metrics = metrics; } }

🔧 Best Practices

1. Service Design

- Keep services small and focused - Use database per service pattern - Implement proper API versioning - Use event-driven communication

2. Service Communication

- Use circuit breakers for resilience - Implement retry policies with backoff - Use health checks for service discovery - Implement proper timeout handling

3. Data Management

- Use saga pattern for distributed transactions - Implement eventual consistency - Use event sourcing for audit trails - Implement proper data partitioning

4. Security

- Use JWT for service-to-service authentication - Implement proper authorization - Use network policies for isolation - Encrypt sensitive data

5. Monitoring and Observability

- Use distributed tracing - Implement comprehensive health checks - Monitor service dependencies - Set up proper alerting

🎯 Summary

TuskLang Java microservices architecture provides:

- Service Discovery: Eureka integration for dynamic service registration - API Gateway: Spring Cloud Gateway with routing and filtering - Service Communication: Load balancing and circuit breakers - Distributed Patterns: Saga, CQRS, and event sourcing - Monitoring: Distributed tracing and comprehensive observability

The combination of TuskLang's executable configuration with Java's microservices capabilities creates a powerful platform for building scalable, resilient, and maintainable distributed systems.

"We don't bow to any king" - Build microservices that scale independently!