১. সেটআপ (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)