System DesignMastery
--Distributed Systems — ডিস্ট্রিবিউটেড সিস্টেম

Service Discovery & Registry

Duration৪৫-৬০ মিনিট
LevelIntermediate
FocusService Mesh
001Why It Matters

Service Discovery কেন শিখতে হবে?

আপনার microservices system এ Order Service কে Payment Service কে call করতে হবে। কিন্তু Payment Service এর IP কী? Kubernetes এ pods dynamically scale হয় — IP বদলায়। Hardcode করা impossible।

এই সমস্যার সমাধান হলো Service Discovery — services নিজেদের register করে, অন্যরা সেই registry থেকে খুঁজে নেয়।

DEFINITION

Service Discovery হলো একটা mechanism যেখানে services automatically তাদের network location (IP, port) একটা registry তে register করে। অন্য services ওই registry থেকে তাদের খুঁজে নেয়। Dynamic scaling এ IP hardcode করার দরকার নেই।

Without vs With Service Discovery

❌ Without Discovery

Order Service: http://192.168.1.45:8001/charge — hardcoded। Payment pod restart হলে IP বদলায় → app broken।

✅ With Discovery

Order Service: http://payment-service/charge — DNS name। Kubernetes DNS automatically resolve করে। Pod যেকোনো IP তে থাকুক।

002Discovery Patterns

দুটো Pattern — Client-side vs Server-side

1. Client-Side Discovery

Client নিজেই Service Registry থেকে service এর location বের করে এবং directly call করে। Netflix Eureka এই pattern follow করে।

CLIENT-SIDE DISCOVERY FLOW

1.Order Service → Service Registry: "Where is Payment Service?"
2.Registry → Order Service: "It's at 10.0.1.5:8001"
3.Order Service → Payment Service (direct call to 10.0.1.5:8001)
Note:Payment Service instances register on start → Registry (Consul/Eureka)
LB:Client has load balancing logic (Netflix Ribbon)

2. Server-Side Discovery

Client একটা fixed endpoint এ request পাঠায়। Load Balancer / API Gateway নিজে Registry থেকে service location বের করে forward করে। Client কিছু জানে না। Kubernetes Service এই pattern।

SERVER-SIDE DISCOVERY (Kubernetes Style)

Client →payment-svc (stable DNS)
K8s Service:Stable DNS + VIP। kube-proxy load balances pods
etcd:Pod registry (internal)
Pods:Pod 10.0.1.5, 10.0.1.6, 10.0.1.7 — K8s Service routes to all
PatternLoad BalancingComplexityExample
Client-sideClient handlesHigherNetflix Eureka + Ribbon
Server-sideLB/Infra handlesLowerKubernetes Service, AWS ALB
003Service Mesh

Service Mesh — Infrastructure Layer

Service Discovery solve করার পরও বাকি থাকে: load balancing, circuit breaking, retry, mTLS, observability। প্রতিটা service এ আলাদাভাবে এগুলো implement করা tedious।

Service Mesh এই সমস্যা solve করে — প্রতিটা service এর পাশে একটা sidecar proxy বসায় (যেমন Envoy)। সব network traffic এই proxy দিয়ে যায়। Service কোড change করতে হয় না।

SERVICE MESH — SIDECAR PATTERN

POD A

Order

Service

Envoy

Sidecar

mTLS, LB

Circuit Breaker

POD B

Envoy

Sidecar

Payment

Service

mTLS Encrypted Channel

Mutual TLS · Auto cert rotation

Istio Control Plane

Service Mesh কী কী করে?

🔐 mTLS

Service-to-service communication automatically encrypted। Certificate management automatic। Zero-trust network।

⚖️ Load Balancing

Advanced algorithms: round-robin, least connections, consistent hashing। Health-aware routing।

⚡ Circuit Breaking

Code change ছাড়াই circuit breaker। YAML config এ define করুন। Language-agnostic।

📊 Observability

Automatic distributed tracing, metrics, logs। প্রতিটা service এ code লেখা লাগে না। Jaeger integration।

ToolTypeProxyBest For
IstioService MeshEnvoyKubernetes — full featured, complex
LinkerdService Meshlinkerd-proxyLightweight K8s mesh
Consul ConnectMesh + DiscoveryEnvoy/built-inMulti-platform, non-K8s too
AWS App MeshManaged MeshEnvoyAWS ECS/EKS
ConsulDiscovery onlyMulti-DC service registry
K8s DNSDiscovery onlySimple K8s service discovery
004Code Examples

Practical Code

Python: Consul Service Registration

service_registry.py
# pip install python-consul
import consul
import socket
from fastapi import FastAPI
import uvicorn
import atexit

app = FastAPI()
c = consul.Consul(host='localhost', port=8500)

SERVICE_NAME = "payment-service"
SERVICE_PORT = 8001
SERVICE_ID = f"payment-service-{socket.gethostname()}"

def register_service():
    """Consul এ service register করুন"""
    c.agent.service.register(
        name=SERVICE_NAME,
        service_id=SERVICE_ID,
        address=socket.gethostbyname(socket.gethostname()),
        port=SERVICE_PORT,
        check={
            "http": f"http://localhost:{SERVICE_PORT}/health",
            "interval": "10s",   # Every 10s health check
            "timeout": "5s"
        },
        tags=["payment", "api", "v1"]
    )
    print(f"✅ Registered: {SERVICE_ID}")

def deregister_service():
    """Shutdown এ deregister করুন"""
    c.agent.service.deregister(SERVICE_ID)
    print(f"❌ Deregistered: {SERVICE_ID}")

def discover_service(service_name: str) -> str:
    """Service এর URL বের করুন"""
    _, services = c.health.service(service_name, passing=True)
    if not services:
        raise Exception(f"No healthy instances of {service_name}")
    # Simple round-robin (real এ load balancer করবেন)
    service = services[0]['Service']
    return f"http://{service['Address']}:{service['Port']}"

@app.on_event("startup")
async def startup():
    register_service()
    atexit.register(deregister_service)

@app.get("/health")
async def health():
    return {"status": "healthy"}

@app.post("/orders")
async def create_order():
    # Discover payment service dynamically
    payment_url = discover_service("payment-service")
    return {"payment_url": payment_url, "status": "processing"}

Kubernetes: Service Discovery YAML

payment-service.yaml
# Kubernetes Service — stable DNS endpoint
apiVersion: v1
kind: Service
metadata:
  name: payment-service   # DNS name হবে: payment-service.default.svc.cluster.local
  namespace: default
spec:
  selector:
    app: payment          # এই label এর pods কে route করবেন
  ports:
    - port: 80            # Service port
      targetPort: 8001     # Pod এর actual port
  type: ClusterIP        # Internal only
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-deployment
spec:
  replicas: 3            # 3 pods — K8s Service load balances
  selector:
    matchLabels:
      app: payment
  template:
    metadata:
      labels:
        app: payment
    spec:
      containers:
      - name: payment
        image: payment-service:latest
        ports:
        - containerPort: 8001
        # Order service এখন শুধু "payment-service" use করে
        # কোনো IP hardcode না!
005Real World

Real World Use Cases

☸️ Kubernetes DNS

সবচেয়ে common। K8s Service create করলেনই DNS entry হয়। payment-service.default.svc.cluster.local — automatic। কোনো external tool লাগে না।

🎬 Netflix Eureka

Client-side discovery। প্রতিটা service Eureka তে register করে। Ribbon load balancer client-side। Java Spring Cloud ecosystem।

🌐 Istio (Google)

K8s তে সবচেয়ে popular service mesh। Envoy sidecar। Traffic management, security, observability। Google, Lyft, IBM এর product।

🔗 Consul (HashiCorp)

K8s ছাড়াও কাজ করে। Multi-DC। VM এবং container উভয়ে। Health checking built-in। Terraform ecosystem এর সাথে ভালো।

006Interview Preparation

Common Interview Questions

🎯 Q1: Service Discovery ছাড়া microservices কেন কাজ করে না?

Dynamic environment এ (K8s, auto-scaling) services এর IP constantly বদলায়। Hardcoded IP = broken system। Service Discovery: register on start, deregister on stop, discover by name। এটাই dynamic infrastructure এর foundation।

🎯 Q2: Service Mesh কি সবসময় দরকার?

না। Small microservices (৫-১০ services), simple communication — Service Mesh overkill। K8s DNS যথেষ্ট। ৫০+ services, complex traffic policies, zero-trust security, observability দরকার হলে Service Mesh consider করুন।

🎯 Q3: Sidecar Pattern কীভাবে কাজ করে?

প্রতিটা service pod এ দুটো container: (1) actual service, (2) Envoy proxy sidecar। সব inbound/outbound traffic proxy দিয়ে যায়। Service কোড change ছাড়াই mTLS, retry, circuit breaking পানয়া যায়। Control Plane (Istiod) সব sidecars কে configure করে।

Interview এ এটা বলুন

"Service Discovery এর জন্য আমি Kubernetes এ প্রথমে built-in DNS use করবো — এটা simplest। Complex traffic management, mTLS, observability দরকার হলে Istio বা Linkerd add করবো। ৫-১০ services এ Service Mesh overkill।" — এটাই সঠিক industry approach।
007Health Checks

Health Check — কেন গুরুত্বপূর্ণ?

Service crash হলে registry থেকে remove হওয়া দরকার। Regular health checks (HTTP /health endpoint, TCP check) দিয়ে Consul/K8s automatically unhealthy pods কে deregister করে। Traffic only healthy instances এ যায়।

Health Check ছাড়া Service Discovery অসম্পূর্ণ

Service crash হলে যদি registry তে এখনও registered থাকে, অন্য services সেই dead instance এ traffic পাঠাবে — errors হবে। Health Check ছাড়া Service Discovery কাজ করে না properly।

Proper Health Check Endpoint Design

health_check.py
from fastapi import FastAPI, Response
import httpx
import asyncpg

app = FastAPI()

@app.get("/health")
async def health_check(response: Response):
    """
    Proper health check — সব dependencies check করুন
    """
    checks = {
        "status": "healthy",
        "database": "unknown",
        "external_api": "unknown"
    }

    # Database connection check
    try:
        conn = await asyncpg.connect("postgresql://localhost/mydb")
        await conn.execute("SELECT 1")
        await conn.close()
        checks["database"] = "healthy"
    except Exception as e:
        checks["database"] = f"unhealthy: {str(e)}"
        checks["status"] = "unhealthy"

    # External service check
    try:
        async with httpx.AsyncClient(timeout=2.0) as client:
            resp = await client.get("https://external-api/ping")
            if resp.status_code == 200:
                checks["external_api"] = "healthy"
            else:
                checks["external_api"] = "degraded"
    except Exception:
        checks["external_api"] = "unhealthy"
        # External service unhealthy কিন্তু আমরা still serve করতে পারবো
        # তাই status "degraded" — critical না হলে

    if checks["status"] == "unhealthy":
        response.status_code = 503  # Service Unavailable

    return checks

# Consul এ register করার সময় এই endpoint দিন:
# "http": "http://localhost:8001/health"
# Consul 503 response দেখলে automatically deregister করবেন
008Tool Comparison

কোন Tool কখন ব্যবহার করবো?

Service Discovery এর জন্য অনেক tool আছে। কোনটা কখন ব্যবহার করবেন সেটা জানা important।

ScenarioRecommended Toolকারণ
Kubernetes only environmentK8s DNS (built-in)No extra setup, automatic, free
K8s + complex traffic managementIstiomTLS, circuit breaking, observability
K8s + lightweight meshLinkerdSimpler than Istio, less overhead
Mixed (VMs + containers)ConsulWorks everywhere, multi-DC support
AWS managed environmentAWS App MeshManaged, ECS/EKS integration
Java Spring Cloud appsNetflix Eureka + RibbonSpring ecosystem integration

Decision Framework

শুরুতে সবসময় simplest option নাও। K8s এ আছো? → K8s DNS যথেষ্ট। mTLS/observability দরকার? → Istio বা Linkerd যোগ করুন। K8s ছাড়া VM আছে? → Consul। Over-engineer করুন না।
009Lesson Summary

SUMMARY — আজকে যা শিখলাম

Conceptএক লাইনে
Service DiscoveryServices নিজেদের register করে, অন্যরা name দিয়ে খোঁজে
Client-SideClient নিজে LB করে — Netflix Eureka+Ribbon
Server-SideLB/Infra করে — K8s Service, AWS ALB
K8s DNSSimplest — Service create করলেনই DNS auto
Service MeshSidecar proxy — mTLS, LB, CB, tracing auto
EnvoyIndustry standard proxy — Istio, Consul, AWS এ
Health CheckUnhealthy service automatically deregister হয়
010Knowledge Check
011Assignments
012Practical Lab