NB: Inspired by a LinkedIn post.
১. সেটআপ (Setup) - প্রথম ধাপ
একটি সার্ভার দিয়ে শুরু
যখন আপনি প্রথম একটি ওয়েবসাইট বা অ্যাপ্লিকেশন তৈরি করেন, সবকিছু একটি সার্ভারে চলে:
একটি সার্ভারে যা থাকে:
- ওয়েব সার্ভার (Nginx/Apache) - HTTP রিকোয়েস্ট গ্রহণ করে
- অ্যাপ্লিকেশন সার্ভার (Node.js, Python, Java) - বিজনেস লজিক চালায়
- ডেটাবেস (MySQL, PostgreSQL) - ডেটা সংরক্ষণ করে
- ফাইল স্টোরেজ - ছবি, ভিডিও ইত্যাদি
উদাহরণ:
ব্যবহারকারী → ইন্টারনেট → একটি সার্ভার ↓ [ওয়েব + অ্যাপ + ডিবি] এই সেটআপের সমস্যা:
-
পারফরম্যান্স বাধা:
- যদি ১০০ জন একসাথে আসে, সার্ভার ধীর হয়ে যায়
- CPU ১০০% হয়ে গেলে নতুন রিকোয়েস্ট এক্সেপ্ট হয় না
- RAM ভরে গেলে সার্ভার ক্র্যাশ করে
-
Single Point of Failure:
- সার্ভার বন্ধ হলে পুরো সাইট ডাউন
- বিদ্যুৎ চলে গেলে, হার্ডওয়্যার ফেইল হলে সব শেষ
- আপডেট দিতে গেলে ডাউনটাইম দরকার
-
স্কেলিং সমস্যা:
- একটি মেশিনের সীমা আছে
- বেশি ট্র্যাফিক হলে কী করবেন?
কখন এটি যথেষ্ট:
- ছোট ব্যবসা, ব্লগ, পোর্টফোলিও সাইট
- দিনে ১০০০-৫০০০ ভিজিটর পর্যন্ত
- বাজেট কম থাকলে
- শুরুর দিকের স্টার্টআপ
একজন সিনিয়র ইঞ্জিনিয়ার যা করেন:
- মনিটরিং টুল লাগান (CPU, RAM, Disk, Network)
- Logs দেখে বোঝেন কোথায় সমস্যা
- প্রয়োজন হলেই স্কেল করেন, আগে নয়
২. ডেটাবেস (Databases) - সবচেয়ে গুরুত্বপূর্ণ অংশ
ডেটাবেস কেন বটলনেক হয়?
আপনার অ্যাপ্লিকেশন খুব দ্রুত চললেও, ডেটাবেস যদি ধীর হয়, পুরো সিস্টেম ধীর হয়ে যাবে।
উদাহরণ:
অ্যাপ সার্ভার: ১ মিলিসেকেন্ডে রেসপন্স তৈরি করে ডেটাবেস কুয়েরি: ৫০০ মিলিসেকেন্ড লাগে ------- মোট সময়: ৫০১ মিলিসেকেন্ড (ডেটাবেসই সমস্যা!) Read-Heavy vs Write-Heavy অ্যাপ্লিকেশন
Read-Heavy (পড়ার চাপ বেশি):
- ফেসবুক নিউজফিড - লাখো মানুষ পড়ছে, কিছু জন লিখছে
- ই-কমার্স - প্রোডাক্ট দেখা >> কেনা
- ব্লগ, নিউজ সাইট
সমাধান:
Master DB (লেখার জন্য) ↓ (Replication) Replica DB 1 (পড়ার জন্য) Replica DB 2 (পড়ার জন্য) Replica DB 3 (পড়ার জন্য) Write-Heavy (লেখার চাপ বেশি):
- সোশ্যাল মিডিয়া পোস্ট/কমেন্ট
- IoT সেন্সর ডেটা
- লগ সিস্টেম
সমাধান:
- Write Buffer ব্যবহার করুন
- Batch Insert করুন (একসাথে অনেক ডেটা)
- ডেটাবেস Sharding করুন
ডেটাবেস অপটিমাইজেশন টেকনিক
১. Indexing (ইনডেক্সিং)
ইনডেক্স ছাড়া:
SELECT * FROM users WHERE email = 'john@example.com'; -- ডেটাবেস প্রতিটি রো একে একে চেক করবে (Slow!) -- ১ মিলিয়ন ইউজার থাকলে ১ মিলিয়ন রো চেক করতে হবে ইনডেক্স সহ:
CREATE INDEX idx_email ON users(email); -- এখন ডেটাবেস সরাসরি খুঁজে পাবে (Fast!) -- Binary Search এর মতো - লগারিদমিক টাইম ইনডেক্সের অসুবিধা:
- লেখার সময় বাড়ে (প্রতিটি INSERT/UPDATE এ ইনডেক্স আপডেট করতে হয়)
- বেশি স্টোরেজ লাগে
- অতিরিক্ত ইনডেক্স ক্ষতিকর
কখন ইনডেক্স দেবেন:
- WHERE clause এ যে কলাম ব্যবহার হয়
- JOIN এ যে কলাম ব্যবহার হয়
- ORDER BY এর কলামে
- Foreign Key তে
২. Connection Pooling
সমস্যা:
প্রতিটি ডেটাবেস কানেকশন তৈরি করতে সময় লাগে:
নতুন কানেকশন তৈরি: ১০০ মিলিসেকেন্ড কুয়েরি চালানো: ১০ মিলিসেকেন্ড কানেকশন বন্ধ করা: ৫০ মিলিসেকেন্ড ------- মোট: ১৬০ মিলিসেকেন্ড (অপচয়!) সমাধান: Connection Pool
অ্যাপ্লিকেশন শুরুতেই ১০টি কানেকশন তৈরি করে রাখে ↓ রিকোয়েস্ট আসলে পুল থেকে কানেকশন নেয় ↓ কাজ শেষে পুলে ফেরত দেয় ↓ পরবর্তী রিকোয়েস্ট সেই কানেকশন রিইউজ করে সুবিধা:
- দ্রুত পারফরম্যান্স
- ডেটাবেসের উপর চাপ কমে
- লিমিটেড কানেকশন = সার্ভার ওভারলোড হয় না
৩. Caching (ক্যাশিং)
৮০/২০ রুল:
আপনার ৮০% রিকোয়েস্ট একই ২০% ডেটার জন্য আসে।
উদাহরণ: ই-কমার্স সাইট
হোমপেজের প্রোডাক্ট লিস্ট: - প্রতি সেকেন্ডে ১০০০ জন দেখছে - কিন্তু ডেটা ১০ মিনিটে একবার পরিবর্তন হয় - প্রতিবার ডেটাবেস থেকে আনার দরকার নেই! ক্যাশিং স্তরসমূহ:
১. Browser Cache:
ব্রাউজারে ছবি, CSS, JS ফাইল সংরক্ষণ ব্যবহারকারী পরবর্তীতে দ্রুত লোড পায় ২. CDN Cache:
Cloudflare, AWS CloudFront বিশ্বের বিভিন্ন জায়গায় কন্টেন্ট রাখে ইউজার তার কাছের সার্ভার থেকে ডেটা পায় ৩. Application Cache (Redis/Memcached):
# ক্যাশ ছাড়া def get_user(user_id): return db.query("SELECT * FROM users WHERE id = ?", user_id) # প্রতিবার ডেটাবেসে যেতে হয় # ক্যাশ সহ def get_user(user_id): cache_key = f"user:{user_id}" # প্রথমে ক্যাশে চেক করো user = redis.get(cache_key) if user: return user # ক্যাশে পাওয়া গেছে! (১ মিলিসেকেন্ড) # ক্যাশে না থাকলে ডেটাবেস থেকে আনো user = db.query("SELECT * FROM users WHERE id = ?", user_id) # ক্যাশে সংরক্ষণ করো (১০ মিনিটের জন্য) redis.set(cache_key, user, expire=600) return user ক্যাশ Invalidation (সবচেয়ে কঠিন অংশ):
দুটি কঠিন সমস্যা কম্পিউটার সায়েন্সে:
- ক্যাশ Invalidation
- নামকরণ
সমস্যা: ডেটা আপডেট হলে ক্যাশ কীভাবে আপডেট করবেন?
কৌশল:
১. Time-based (TTL - Time To Live):
ক্যাশ ৫ মিনিট পর নিজে নিজে মুছে যায় সহজ কিন্তু stale data দেখাতে পারে ২. Event-based:
def update_user(user_id, new_data): # ডেটাবেস আপডেট db.update("UPDATE users SET ... WHERE id = ?", user_id) # ক্যাশ মুছে দাও redis.delete(f"user:{user_id}") ৩. Write-through:
ডেটাবেস + ক্যাশ দুটোতেই একসাথে লেখা সবসময় আপডেটেড ডেটা ৪. Database Sharding (ডেটা ভাগ করা)
কখন দরকার:
যখন একটি ডেটাবেস সার্ভার যথেষ্ট না।
Sharding মানে: ডেটা একাধিক ডেটাবেস সার্ভারে ভাগ করে রাখা।
উদাহরণ: ইউজার ডেটা
১০ মিলিয়ন ইউজার ↓ Shard 1: user_id 1 - 2,500,000 Shard 2: user_id 2,500,001 - 5,000,000 Shard 3: user_id 5,000,001 - 7,500,000 Shard 4: user_id 7,500,001 - 10,000,000 Sharding Strategy:
১. Hash-based Sharding:
def get_shard(user_id): shard_number = user_id % 4 # ৪টি শার্ড return database_servers[shard_number] # user_id = 12345 # 12345 % 4 = 1 # Shard 1 তে যাবে ২. Range-based Sharding:
user_id 1-1M → Shard 1 user_id 1M-2M → Shard 2 ... ৩. Geographic Sharding:
বাংলাদেশের ইউজার → Asia Shard USA এর ইউজার → US Shard ইউরোপের ইউজার → Europe Shard Sharding এর চ্যালেঞ্জ:
১. Cross-shard Query:
-- এটি কঠিন! SELECT * FROM users WHERE country = 'Bangladesh' ORDER BY created_at LIMIT 10; -- প্রতিটি শার্ডে যেতে হবে, ডেটা একত্রিত করতে হবে ২. Rebalancing:
নতুন শার্ড যোগ করলে পুরানো ডেটা সরানো জটিল ৩. Joins:
দুটি টেবিল ভিন্ন শার্ডে থাকলে JOIN করা কঠিন ৩. SPOF (Single Point of Failure)
SPOF কী?
আপনার সিস্টেমের যে কম্পোনেন্ট ফেইল হলে পুরো সিস্টেম বন্ধ হয়ে যায়।
উদাহরণ: বাস্তব জীবন
একটি বাড়িতে একটি মেইন সুইচ ↓ সুইচ বন্ধ = পুরো বাড়ি অন্ধকার ↓ এটি SPOF সিস্টেমে SPOF চেনার উপায়
প্রশ্ন করুন:
- এই সার্ভার ডাউন হলে কী হবে?
- এই ডেটাবেস ক্র্যাশ করলে?
- লোড ব্যালেন্সার মারা গেলে?
- ইন্টারনেট প্রোভাইডার ডাউন হলে?
উদাহরণ আর্কিটেকচার:
ইউজার → লোড ব্যালেন্সার → সার্ভার 1 → সার্ভার 2 → সার্ভার 3 ↓ একটি ডেটাবেস (SPOF!) এখানে:
- সার্ভার ১, ২, ৩ এর যেকোনো একটি ডাউন হলেও সিস্টেম চলবে
- কিন্তু ডেটাবেস ডাউন = পুরো সিস্টেম বন্ধ
- লোড ব্যালেন্সার ডাউন = সব সার্ভার আছে কিন্তু ইউজার পৌঁছাতে পারছে না
SPOF দূর করার উপায়
১. Database Replication (Master-Slave)
Simple Setup:
Master DB (লেখার জন্য) ↓ (Continuous Replication) Slave DB (পড়ার জন্য + Backup) কীভাবে কাজ করে:
1. Master এ ডেটা লেখা হয় 2. Master সাথে সাথে Slave কে আপডেট পাঠায় 3. Read operations Slave থেকে হয় 4. Master ফেইল হলে Slave কে Master বানানো হয় Master-Master Setup:
Master 1 ⟷ Master 2 (উভয়েই লেখা/পড়া করতে পারে) সুবিধা:
- High Availability
- Read Scaling
- Automatic Failover
সমস্যা:
- Replication Lag (কিছু সময় পিছিয়ে থাকতে পারে)
- Conflict Resolution (দুটি Master একই ডেটা পরিবর্তন করলে)
২. Load Balancer Redundancy
সমস্যা:
একটি লোড ব্যালেন্সার = SPOF সমাধান: Multiple Load Balancers
Active-Passive Setup:
DNS ↓ Primary Load Balancer (Active) Secondary Load Balancer (Passive, Standby) Primary ফেইল হলে: ↓ Secondary Automatically Active হয়ে যায় (VRRP/Keepalived) Active-Active Setup:
DNS Round Robin ↙ ↘ Load Balancer 1 Load Balancer 2 (দুটোই একসাথে কাজ করে) ৩. Multi-AZ (Availability Zone) Deployment
AWS Example:
Region: ap-south-1 (Mumbai) ↓ AZ-1a: Web Server 1, DB Replica 1 AZ-1b: Web Server 2, DB Replica 2 AZ-1c: Web Server 3, DB Master একটি AZ ডাউন হলে বাকি দুটি চলতে থাকবে ৪. Geographic Redundancy
Global Load Balancer (GeoDNS) ↙ ↘ Region 1 (Asia) Region 2 (US) Full Setup Full Setup Asia ডাউন হলে US থেকে সার্ভ করবে Real-World Example: AWS Setup
Route 53 (DNS) - Multi-region ↓ CloudFront (CDN) - Global Edge Locations ↓ ALB (Load Balancer) - Multi-AZ ↙ ↘ EC2 AZ-1a EC2 AZ-1b (Auto-scaling) ↓ ↓ RDS Primary (AZ-1a) ⟷ RDS Standby (AZ-1b) এই সেটআপে:
- DNS: Route 53 (AWS এর অনেক DNS সার্ভার বিশ্বজুড়ে)
- CDN: CloudFront (কন্টেন্ট সবার কাছে)
- Load Balancer: Multi-AZ
- Servers: Auto-scaling (চাপ বাড়লে নতুন সার্ভার তৈরি)
- Database: Automatic failover
কোনো SPOF নেই!
৪. Scaling - স্কেলিং কৌশল
Vertical Scaling
মানে: বড় মেশিন কিনুন
উদাহরণ:
আগে: - 2 CPU Core - 4 GB RAM - 100 GB SSD পরে: - 16 CPU Core - 64 GB RAM - 1 TB SSD সুবিধা:
১. সহজ:
কোড চেঞ্জ করার দরকার নেই শুধু বড় সার্ভার কিনুন ২. কোনো জটিলতা নেই:
Distributed System এর ঝামেলা নেই একটি মেশিন = সহজ ডিবাগিং ৩. Performance Consistency:
সব ডেটা এক জায়গায় Network Latency নেই অসুবিধা:
১. হার্ডওয়্যার সীমা:
বাজারে সবচেয়ে বড় সার্ভার: - 128 CPU Core - 2 TB RAM - এর বেশি কিনতে পারবেন না! ২. দাম:
2 CPU → 4 CPU = 2x দাম 4 CPU → 8 CPU = 4x দাম (Exponential!) AWS t3.medium: $0.0416/hour AWS t3.2xlarge: $0.3328/hour (8x expensive!) ৩. SPOF:
একটি মেশিন = সব ডিম এক ঝুড়িতে মেশিন ক্র্যাশ = সব শেষ ৪. Downtime:
Upgrade করতে সার্ভার বন্ধ করতে হয় Old Server → New Server মাইগ্রেশন কখন ব্যবহার করবেন:
- দ্রুত সমাধান দরকার
- ডেটাবেস সার্ভার (কারণ ডেটাবেস স্কেল করা কঠিন)
- Legacy Application যা Horizontal Scale করা যায় না
- ছোট টিম (Complexity সামলানো কঠিন)
Horizontal Scaling
মানে: অনেক ছোট মেশিন যোগ করুন
উদাহরণ:
আগে: 1 Server (16 CPU, 64 GB RAM) পরে: 8 Servers (2 CPU, 8 GB RAM each) আর্কিটেকচার:
Load Balancer ↙ ↓ ↓ ↘ Server1 Server2 Server3 Server4 সুবিধা:
১. প্রায় অসীম স্কেলিং:
চাপ বাড়ছে? আরো সার্ভার যোগ করুন 1 → 10 → 100 → 1000 সার্ভার ২. High Availability:
Server 1 ডাউন? Server 2, 3, 4 চলছে ইউজার বুঝতেই পারবে না ৩. Cost Effective:
Commodity Hardware ব্যবহার করতে পারেন প্রয়োজন মতো যোগ/বাদ করুন ৪. No Downtime:
Rolling Update সম্ভব: Server 1 Update → Live Server 2 Update → Live Server 3 Update → Live ৫. Load Distribution:
Peak Time: 10 সার্ভার চালু Night Time: 2 সার্ভার চালু (Auto-scaling) অসুবিধা:
১. জটিল:
Distributed System State Management Data Consistency ২. Stateless হতে হবে:
# Bad (Stateful) user_sessions = {} # In-memory storage def login(user_id): user_sessions[user_id] = "logged_in" # সমস্যা: Server 1 এ লগইন, Server 2 জানে না! # Good (Stateless) def login(user_id): redis.set(f"session:{user_id}", "logged_in") # সব সার্ভার Redis থেকে পড়বে ৩. Session Management:
ইউজার Server 1 তে লগইন করল পরের রিকোয়েস্ট Server 2 তে গেল Server 2 জানে না ইউজার লগইন করা! সমাধান: - Sticky Sessions (একই ইউজার একই সার্ভারে) - External Session Store (Redis) - JWT Tokens (Stateless) ৪. Data Consistency:
Server 1: ইউজার ব্যালেন্স $100 Server 2: ইউজার ব্যালেন্স $100 দুটি সার্ভারে একসাথে $50 উত্তোলন ↓ Server 1: $50 Server 2: $50 সঠিক: $0 হওয়া উচিত ছিল! সমাধান: Database Transaction
Stateless Application Design
গুরুত্বপূর্ণ নিয়ম: Horizontal Scaling এর জন্য অ্যাপ্লিকেশন Stateless হতে হবে।
Stateless মানে:
সার্ভার কোনো ইউজার ডেটা মনে রাখে না প্রতিটি রিকোয়েস্ট স্বাধীন যেকোনো সার্ভার যেকোনো রিকোয়েস্ট হ্যান্ডেল করতে পারে উদাহরণ:
Stateful (Bad):
# মেমরিতে সংরক্ষণ shopping_cart = {} @app.post("/add-to-cart") def add_item(user_id, item): if user_id not in shopping_cart: shopping_cart[user_id] = [] shopping_cart[user_id].append(item) # সমস্যা: শুধু এই সার্ভারে আছে! Stateless (Good):
# External Store ব্যবহার @app.post("/add-to-cart") def add_item(user_id, item): cart_key = f"cart:{user_id}" redis.lpush(cart_key, json.dumps(item)) # সুবিধা: যেকোনো সার্ভার থেকে এক্সেস করা যায় ৫. Load Balancers - ট্র্যাফিক নিয়ন্ত্রক
Load Balancer কী?
সহজ ভাষায়:
একটি ট্রাফিক পুলিশ যে সিদ্ধান্ত নেয় কোন সার্ভারে রিকোয়েস্ট পাঠাবে উদাহরণ: রেস্তোরাঁ
100 জন কাস্টমার 1 জন হোস্ট (Load Balancer) 5 টি টেবিল (Servers) হোস্ট সিদ্ধান্ত নেয়: - কোন টেবিলে খালি জায়গা আছে - কোন ওয়েটার কম ব্যস্ত - কাস্টমারকে সেই টেবিলে পাঠায় Load Balancing Algorithms (বিস্তারিত)
১. Round Robin (রাউন্ড রবিন)
কীভাবে কাজ করে:
Request 1 → Server 1 Request 2 → Server 2 Request 3 → Server 3 Request 4 → Server 1 (আবার শুরু) Request 5 → Server 2 ... উদাহরণ কোড:
servers = ['Server1', 'Server2', 'Server3'] current = 0 def get_server(): global current server = servers[current] current = (current + 1) % len(servers) return server # Test print(get_server()) # Server1 print(get_server()) # Server2 print(get_server()) # Server3 print(get_server()) # Server1 সুবিধা:
- খুব সহজ
- সব সার্ভার সমান কাজ পায়
- ফেয়ার ডিস্ট্রিবিউশন
অসুবিধা:
- সার্ভারের লোড বিবেচনা করে না
- কিছু রিকোয়েস্ট ভারী, কিছু হালকা
- Long-running requests এর সমস্যা
উদাহরণ সমস্যা:
Server 1: Request A (10 সেকেন্ড) Server 2: Request B (1 সেকেন্ড) Server 3: Request C (1 সেকেন্ড) পরের রিকোয়েস্ট Server 1 তে যাবে (Round Robin) কিন্তু Server 1 ব্যস্ত! Server 2 বা 3 ভালো হতো কখন ব্যবহার করবেন:
- সব সার্ভার একই ক্ষমতার
- সব রিকোয়েস্ট একই সময় নেয়
- সহজ সেটআপ দরকার
২. Least Connections (সবচেয়ে কম সংযোগ)
কীভাবে কাজ করে:
যে সার্ভারে সবচেয়ে কম Active Connection আছে, সেখানে নতুন রিকোয়েস্ট পাঠাও উদাহরণ:
Server 1: 5 active connections Server 2: 12 active connections Server 3: 3 active connections নতুন রিকোয়েস্ট → Server 3 (সবচেয়ে কম) কোড উদাহরণ:
servers = { 'Server1': {'connections': 5}, 'Server2': {'connections': 12}, 'Server3': {'connections': 3} } def get_least_connected_server(): return min(servers.items(), key=lambda x: x[1]['connections'])[0] # Test print(get_least_connected_server()) # Server3 সুবিধা:
- লোড আরো ভালোভাবে ডিস্ট্রিবিউট হয়
- Long-running connections সামলায়
- Dynamic Load এর জন্য ভালো
অসুবিধা:
- একটু জটিল
- Overhead বেশি (Connection Count Track করতে হয়)
কখন ব্যবহার করবেন:
- WebSocket connections
- Long polling
- Database connections
- Chat applications
৩. IP Hash (আইপি হ্যাশ)
কীভাবে কাজ করে:
ইউজারের IP Address থেকে হ্যাশ তৈরি করো হ্যাশ ব্যবহার করে সার্ভার বাছাই করো একই IP সবসময় একই সার্ভারে যায় উদাহরণ:
def ip_hash(ip_address, num_servers): hash_value = hash(ip_address) server_index = hash_value % num_servers return f"Server{server_index + 1}" # Test print(ip_hash("192.168.1.100", 3)) # Server2 print(ip_hash("192.168.1.100", 3)) # Server2 (সবসময় একই!) print(ip_hash("192.168.1.101", 3)) # Server1 সুবিধা:
- Session Persistence (Sticky Session)
- Cache Hit Rate বাড়ে
- ইউজার তার ডেটা একই সার্ভারে পায়
অসুবিধা:
- Uneven Distribution হতে পারে
- সার্ভার যোগ/বাদ করলে সব হ্যাশ পরিবর্তন
- NAT এর পিছনের ইউজারদের সমস্যা
ব্যবহার:
E-commerce Shopping Cart: - ইউজার যোগ করল Server 1 তে - পরের রিকোয়েস্ট Server 1 তেই যাবে - Cart ডেটা হারাবে না ৪. Weighted Round Robin (ওজন অনুযায়ী রাউন্ড রবিন)
কীভাবে কাজ করে:
প্রতিটি সার্ভারের ক্ষমতা অনুযায়ী ওজন দেওয়া বেশি ক্ষমতার সার্ভার বেশি রিকোয়েস্ট পায় উদাহরণ:
Server 1: 16 CPU, Weight = 4 Server 2: 8 CPU, Weight = 2 Server 3: 4 CPU, Weight = 1 Distribution: 4 requests → Server 1 2 requests → Server 2 1 request → Server 3 কোড:
servers = [ {'name': 'Server1', 'weight': 4}, {'name': 'Server2', 'weight': 2}, {'name': 'Server3', 'weight': 1} ] def weighted_round_robin(): # Weight অনুযায়ী তালিকা তৈরি weighted_list = [] for server in servers: weighted_list.extend([server['name']] * server['weight']) # Round robin করো while True: for server in weighted_list: yield server # Test gen = weighted_round_robin() for _ in range(14): print(next(gen)) # Output: # Server1, Server1, Server1, Server1, # Server2, Server2, # Server3, # Server1, Server1, Server1, Server1, # Server2, Server2, # Server3 কখন ব্যবহার করবেন:
- সার্ভারগুলো ভিন্ন ক্ষমতার
- Gradual Migration (নতুন সার্ভারে ধীরে ধীরে ট্র্যাফিক)
- Canary Deployment (1% ট্র্যাফিক নতুন ভার্সনে)
Layer 4 vs Layer 7 Load Balancing
OSI Model:
Layer 7: Application (HTTP, HTTPS, FTP) Layer 6: Presentation Layer 5: Session Layer 4: Transport (TCP, UDP) Layer 3: Network (IP) Layer 2: Data Link Layer 1: Physical Layer 4 Load Balancing (Transport Layer)
কী দেখে:
- Source IP Address
- Destination IP Address
- Source Port
- Destination Port
- Protocol (TCP/UDP)
দেখে না:
- HTTP Headers
- URL
- Cookies
- Content
উদাহরণ:
ইউজার রিকোয়েস্ট পাঠাল: 192.168.1.100:54321 → LoadBalancer:80 Load Balancer সিদ্ধান্ত নিল: 192.168.1.100:54321 → Server2:8080 সব TCP প্যাকেট Server2 তে যাবে Content বুঝে কিছু করে না সুবিধা:
- খুব দ্রুত (কম প্রসেসিং)
- কম Resource লাগে
- Any Protocol সাপোর্ট করে
- SSL Passthrough (Encryption সার্ভারে থাকে)
অসুবিধা:
- Smart Routing করতে পারে না
- Content-based Decision নেই
- Sticky Session কঠিন
ব্যবহার:
- Very High Traffic
- Low Latency দরকার
- Non-HTTP Protocol (Database, Gaming)
Layer 7 Load Balancing (Application Layer)
কী দেখে:
- HTTP Method (GET, POST)
- URL Path
- HTTP Headers
- Cookies
- Query Parameters
- Request Body
উদাহরণ:
Request 1: GET /api/users → API Servers Request 2: GET /images/cat.jpg → Image Servers Request 3: GET /videos/movie.mp4 → Video Servers Smart Routing:
# Nginx Configuration location /api/ { proxy_pass http://api_servers; } location /static/ { proxy_pass http://cdn_servers; } location / { proxy_pass http://web_servers; } User-based Routing:
if (cookie.user_type == "premium") { send_to(premium_servers); } else { send_to(free_servers); } সুবিধা:
- Smart Content-based Routing
- SSL Termination (Load Balancer এ Decrypt)
- Caching
- Compression
- WAF (Web Application Firewall)
- A/B Testing
অসুবিধা:
- ধীর (বেশি Processing)
- বেশি Resource লাগে
- শুধু HTTP/HTTPS
ব্যবহার:
- Microservices Routing
- Content Delivery
- API Gateway
- Modern Web Apps
Health Checks (স্বাস্থ্য পরীক্ষা)
কেন দরকার:
Server 2 ক্র্যাশ করেছে কিন্তু Load Balancer জানে না রিকোয়েস্ট পাঠাচ্ছে → ব্যর্থ হচ্ছে ইউজার Error পাচ্ছে সমাধান: Health Check
কীভাবে কাজ করে:
প্রতি 5 সেকেন্ডে: Load Balancer → GET /health → Server 1 Server 1 → 200 OK (সুস্থ!) Load Balancer → GET /health → Server 2 Server 2 → Timeout (মৃত!) Load Balancer সিদ্ধান্ত: Server 1 তে রিকোয়েস্ট পাঠাও ✓ Server 2 তে পাঠাও না ✗ Health Check Endpoint:
@app.get("/health") def health_check(): try: # ডেটাবেস চেক db.execute("SELECT 1") # Redis চেক redis.ping() # Disk Space চেক if disk_space() < 10%: return {"status": "unhealthy"}, 503 return {"status": "healthy"}, 200 except: return {"status": "unhealthy"}, 503 Configuration:
health_check: interval: 5s # প্রতি 5 সেকেন্ডে চেক timeout: 2s # 2 সেকেন্ডে রেসপন্স না আসলে Failed unhealthy_threshold: 3 # 3 বার Failed হলে Unhealthy healthy_threshold: 2 # 2 বার Success হলে Healthy Session Persistence (Sticky Sessions)
সমস্যা:
ইউজার লগইন করল: Request 1 → Server 1 (Session তৈরি হল) পরের রিকোয়েস্ট: Request 2 → Server 2 (Session নেই! ইউজার লগআউট!) সমাধান ১: Cookie-based Sticky Session
Load Balancer একটি Cookie সেট করে: Set-Cookie: SERVER=server1 পরের রিকোয়েস্টে: Cookie: SERVER=server1 ↓ সবসময় Server 1 তে যাবে সমাধান ২: External Session Store
# সব সার্ভার একই জায়গায় Session রাখে import redis session_store = redis.Redis() @app.post("/login") def login(username, password): if verify(username, password): session_id = generate_id() session_store.set( f"session:{session_id}", json.dumps({"user": username}), expire=3600 ) return {"session_id": session_id} @app.get("/profile") def profile(session_id): session = session_store.get(f"session:{session_id}") if session: return {"user": json.loads(session)} return {"error": "Not logged in"} সমাধান ৩: JWT (Stateless)
import jwt @app.post("/login") def login(username, password): if verify(username, password): token = jwt.encode( {"user": username, "exp": time() + 3600}, secret_key ) return {"token": token} @app.get("/profile") def profile(token): try: payload = jwt.decode(token, secret_key) return {"user": payload["user"]} except: return {"error": "Invalid token"} ৬. Security (নিরাপত্তা) - তিন স্তরের প্রতিরক্ষা
Per Endpoint Security (প্রতিটি API এর নিরাপত্তা)
Rate Limiting:
from flask_limiter import Limiter limiter = Limiter(app, key_func=get_remote_address) @app.post("/login") @limiter.limit("5 per minute") # মিনিটে ৫ বার def login(): # Brute Force Attack রোধ করে pass @app.post("/api/create-post") @limiter.limit("10 per hour") # ঘণ্টায় ১০ বার def create_post(): # Spam রোধ করে pass Authentication:
@app.get("/profile") @require_auth # লগইন ছাড়া প্রবেশ নিষেধ def profile(): return current_user.data Input Validation:
@app.post("/register") def register(email, password): # Email Validation if not re.match(r"[^@]+@[^@]+\.[^@]+", email): return {"error": "Invalid email"} # Password Strength if len(password) < 8: return {"error": "Password too weak"} # SQL Injection Prevention db.execute( "INSERT INTO users (email, password) VALUES (?, ?)", (email, hash(password)) # Parameterized Query ) Per User/IP Security (ব্যবহারকারী/আইপি ভিত্তিক নিরাপত্তা)
User-based Rate Limiting:
# Redis দিয়ে Track করা def check_rate_limit(user_id, limit=100, window=3600): key = f"rate_limit:{user_id}" current = redis.incr(key) if current == 1: redis.expire(key, window) if current > limit: return False # Limit exceeded return True @app.get("/api/data") def get_data(user_id): if not check_rate_limit(user_id): return {"error": "Rate limit exceeded"}, 429 return {"data": "..."} IP-based Blocking:
BLOCKED_IPS = set() @app.before_request def check_ip(): ip = request.remote_addr # Blacklist চেক if ip in BLOCKED_IPS: abort(403) # Suspicious Activity Detection if detect_suspicious(ip): BLOCKED_IPS.add(ip) notify_admin(f"Blocked IP: {ip}") abort(403) def detect_suspicious(ip): # ১ মিনিটে ১০০০ রিকোয়েস্ট? count = redis.get(f"request_count:{ip}") return int(count or 0) > 1000 CAPTCHA for Suspicious Behavior:
@app.post("/login") def login(username, password): failed_attempts = redis.get(f"failed_login:{username}") if int(failed_attempts or 0) > 3: # CAPTCHA দেখাও if not verify_captcha(request.form.get('captcha')): return {"error": "Invalid CAPTCHA"} # Login process... Overall DDoS Mitigation (সামগ্রিক DDoS প্রতিরক্ষা)
DDoS Attack কী:
হাজার হাজার কম্পিউটার থেকে একসাথে রিকোয়েস্ট ↓ সার্ভার Overwhelmed ↓ সাইট ডাউন Protection Layers:
১. CDN (Cloudflare, AWS CloudFront):
Attacker ↓ CDN Edge (Absorbs attack) ↓ Your Server (Protected!) সুবিধা:
- CDN এর হাজার সার্ভার attack absorb করে
- আপনার সার্ভারে পৌঁছায় না
- Legitimate traffic filter করে পাঠায়
২. WAF (Web Application Firewall):
# WAF Rules rules = [ # SQL Injection Block { "pattern": r"(union|select|insert|drop|delete)", "action": "block" }, # XSS Block { "pattern": r"<script>", "action": "block" }, # Rate Limit { "condition": "requests > 100/min", "action": "challenge" # CAPTCHA দেখাও } ] ৩. Auto-scaling:
Attack শুরু হলো: ↓ Traffic spike detect করা হলো ↓ Auto-scaling: ৫ সার্ভার → ২০ সার্ভার ↓ Load distribute হলো ↓ Site চলতে থাকলো ৪. Traffic Analysis:
def analyze_traffic(): patterns = { 'normal': 100 req/sec, 'current': 10000 req/sec # Suspicious! } if patterns['current'] > patterns['normal'] * 10: # DDoS হতে পারে enable_strict_mode() notify_team() activate_cloudflare_shield() বাস্তব উদাহরণ: একটি ই-কমার্স সাইট স্কেলিং
পর্যায় ১: শুরু (১০০ ইউজার/দিন)
একটি সার্ভার - Nginx + Node.js + PostgreSQL - $20/month পর্যায় ২: বৃদ্ধি (১০,০০০ ইউজার/দিন)
সমস্যা: ডেটাবেস স্লো সমাধান: - ডেটাবেস আলাদা সার্ভারে - Redis Cache যোগ - CDN ছবির জন্য খরচ: $200/month পর্যায় ৩: দ্রুত বৃদ্ধি (১ লাখ ইউজার/দিন)
সমস্যা: একটি ওয়েব সার্ভার যথেষ্ট নয় সমাধান: - Load Balancer - ৩টি ওয়েব সার্ভার - Database Read Replica - Auto-scaling খরচ: $1,500/month পর্যায় ৪: স্কেল (১০ লাখ ইউজার/দিন)
সমস্যা: ডেটাবেস bottleneck সমাধান: - Database Sharding - ১০টি ওয়েব সার্ভার (Auto-scale) - Multiple Read Replicas - Microservices আর্কিটেকচার - Multi-region Deployment খরচ: $10,000/month মূল শিক্ষা
১. ছোট থেকে শুরু করুন - Over-engineering করবেন না
২. সমস্যা দেখা দিলে সমাধান করুন - আগে থেকে নয়
৩. মনিটরিং জরুরি - না দেখলে জানবেন কীভাবে?
৪. Cache করুন - সবচেয়ে সহজ optimization
৫. Stateless রাখুন - Horizontal scaling সহজ হবে
৬. SPOF দূর করুন - Redundancy যোগ করুন
৭. Test করুন - Load testing, Failover testing
Top comments (0)