Microservices কী?
Monolith vs Microservices — একটি বড় app-কে অনেক ছোট, independent service-এ ভাগ করা। প্রতিটি service আলাদা DB, deploy, team।
Service Decomposition
E-commerce মোনোলিথ → Catalog Service (Products, Categories) Order Service (Orders, Cart) Payment Service (Stripe integration) Shipping Service (Courier API) Notification Service(Email, SMS) Identity Service (Auth, JWT)
Communication Patterns
- Synchronous — HTTP/REST, gRPC (immediate response)
- Asynchronous — Message broker (RabbitMQ, Kafka, Azure Service Bus)
HttpClient Factory (Sync)
// Program.cs
builder.Services.AddHttpClient<ICatalogClient, CatalogClient>(c => {
c.BaseAddress = new Uri("http://catalog-service");
}).AddPolicyHandler(GetRetryPolicy());
// Polly retry
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() =>
HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));
// Client
public class CatalogClient : ICatalogClient {
private readonly HttpClient _http;
public CatalogClient(HttpClient http) => _http = http;
public async Task<ProductDto?> GetAsync(int id) =>
await _http.GetFromJsonAsync<ProductDto>($"/api/products/{id}");
}
RabbitMQ + MassTransit (Async) ⭐
dotnet add package MassTransit.RabbitMQ
// Program.cs
builder.Services.AddMassTransit(x => {
x.AddConsumer<OrderCreatedConsumer>();
x.UsingRabbitMq((ctx, cfg) => {
cfg.Host("rabbitmq://localhost", h => {
h.Username("guest"); h.Password("guest");
});
cfg.ReceiveEndpoint("order-created", e => e.ConfigureConsumer<OrderCreatedConsumer>(ctx));
});
});
// Event
public record OrderCreated(int OrderId, decimal Total, string Email);
// Publish (Order Service)
public class OrderService {
private readonly IPublishEndpoint _publish;
public async Task PlaceOrder(...) {
// Save order
await _publish.Publish(new OrderCreated(order.Id, order.Total, user.Email));
}
}
// Consume (Notification Service)
public class OrderCreatedConsumer : IConsumer<OrderCreated> {
public async Task Consume(ConsumeContext<OrderCreated> ctx) {
await SendEmail(ctx.Message.Email, $"Order {ctx.Message.OrderId} placed");
}
}
API Gateway (YARP / Ocelot)
# YARP appsettings.json
{
"ReverseProxy": {
"Routes": {
"catalog": { "ClusterId": "catalog", "Match": { "Path": "/api/products/{**catch-all}" } },
"orders": { "ClusterId": "orders", "Match": { "Path": "/api/orders/{**catch-all}" } }
},
"Clusters": {
"catalog": { "Destinations": { "d1": { "Address": "http://catalog-service" } } },
"orders": { "Destinations": { "d1": { "Address": "http://order-service" } } }
}
}
}
// Program.cs
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
app.MapReverseProxy();
Service Discovery
- Consul — service registry + health
- Kubernetes — built-in DNS-based discovery
- Eureka — Netflix OSS
Distributed Tracing
// OpenTelemetry
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Exporter.Jaeger
builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddJaegerExporter());
Patterns
- Saga — distributed transaction coordination
- Outbox — DB + message atomic publish
- Circuit Breaker — Polly
- Bulkhead — resource isolation
- CQRS + Event Sourcing
Drawbacks
Network latency, distributed transaction complexity, monitoring overhead, data consistency challenges। Small team-এ monolith first।