مواصلاتی پرت کئی تعمیراتی فیصلوں میں سے ایک ہے جو آپ کی ایپ میں موجود ہر چیز کو متاثر کرتی ہے۔ یہ تاخیر کا تعین کرتا ہے، ٹیمیں کس طرح آزادانہ طور پر تعینات کر سکتی ہیں، ناکامیاں کیسے پھیلتی ہیں، اور ہر بار معاہدہ تبدیل ہونے پر انہیں کتنا درد محسوس ہوتا ہے۔
تین اہم نمونے ہیں: HTTP پر REST، پروٹوکول بفرز کے ساتھ gRPC، اور بروکرز کے ذریعے ایونٹ پر مبنی پیغام رسانی۔ زیادہ تر پیداواری نظام تینوں کا مرکب استعمال کرتے ہیں۔ ہنر یہ جاننا ہے کہ کون سے نمونے کن تعاملات کے لیے موزوں ہیں۔
اس مضمون میں، آپ ہر مواصلاتی انداز کے بنیادی میکانزم کے بارے میں سیکھیں گے، ان کے درمیان پانچ جہتوں (دیرتا، جوڑے، اسکیما ارتقاء، ڈیبگنگ، اور آپریشنل پیچیدگی) میں عملی تجارت کے بارے میں، اور ہر سروس کے تعامل کے لیے مناسب پیٹرن کو منتخب کرنے کے لیے فیصلہ سازی کا فریم ورک۔
شرطیں
اس مضمون سے زیادہ سے زیادہ فائدہ اٹھانے کے لیے، آپ کو یہ جاننے کی ضرورت ہے:
-
بنیادی HTTP تصورات (درخواست/جواب، اسٹیٹس کوڈز، ہیڈر)
-
کسی بھی بیک اینڈ زبان میں API کے ساتھ کام کریں (مثال کے طور پر TypeScript اور Node.js کا استعمال کریں)
-
مائیکرو سروس فن تعمیر کی عمومی تفہیم
-
JSON کا علم، ایک ڈیٹا ایکسچینج فارمیٹ۔
انڈیکس
تین نمونوں کو دریافت کریں۔
گہرائی میں غوطہ لگانے سے پہلے یہ نظارہ ہے:
| باقی | جی آر پی سی | واقعہ کی بنیاد پر | |
|---|---|---|---|
| مواصلات | ہم وقت ساز | ہم وقت ساز (+ سلسلہ بندی) | متضاد |
| کوڈ | HTTP/1.1 یا HTTP/2 | HTTP/2 | بروکر پر منحصر (TCP) |
| سیریلائزیشن | JSON (عام طور پر) | پروٹوکول بفر (بائنری) | JSON، Avro، Protoboof |
| کنکشن | وقت کی درخواست کریں | وقت + اسکیما کی درخواست کریں۔ | عارضی ڈیکپلنگ |
| کے لیے بہترین موزوں ہے۔ | عوامی API، CRUD | اندرونی اعلی تھرو پٹ | ورک فلو، ایونٹ سورسنگ |
ہر ایک کی اپنی طاقتیں ہیں، اور کوئی بھی عالمی طور پر بہتر نہیں ہے۔ اس مضمون کا بقیہ حصہ اس کی وجہ دریافت کرتا ہے۔
REST: پہلے سے طے شدہ انتخاب
REST اوور HTTP سب سے زیادہ سمجھا جانے والا مواصلاتی نمونہ ہے۔ سروسز یو آر ایل کے اختتامی نقطوں پر وسائل کو ظاہر کرتی ہیں، اور کلائنٹ معیاری HTTP طریقوں کے ذریعے تعامل کرتے ہیں۔
// Order service calls the inventory service
async function checkInventory(productId: string): Promise {
const response = await fetch(
`https://inventory-service/api/v1/products/${productId}/stock`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getServiceToken()}`,
},
}
);
if (!response.ok) {
throw new HttpError(response.status, await response.text());
}
return response.json();
}
جہاں REST بہترین ہے۔
تمام زبانیں، فریم ورک، اور پلیٹ فارم HTTP استعمال کرتے ہیں۔ فرنٹنڈز، موبائل ایپس، پارٹنر انٹیگریشنز، اور اندرونی سروسز سب ایک ہی پروٹوکول استعمال کر سکتے ہیں۔
اوزار بھی بالغ ہیں۔ لوڈ بیلنسرز، API گیٹ ویز، کیشنگ پراکسی، اور ڈیبگنگ ٹولز سبھی مقامی طور پر HTTP کو سمجھتے ہیں۔
یہ نسبتاً آسان بھی ہے۔ ایک نیا ڈویلپر ایک REST کال پڑھ سکتا ہے اور سمجھ سکتا ہے کہ یہ کیا کرتا ہے۔ یو آر ایل ایک وسائل کی وضاحت کرتا ہے۔ ایک HTTP طریقہ آپریشن کی وضاحت کرتا ہے۔ اسٹیٹس کوڈ نتیجہ بیان کرتا ہے۔ کوئی اسکیما تالیف کے اقدامات نہیں ہیں، کوئی کوڈ جنریشن نہیں ہے، اور کسی خاص کلائنٹ لائبریریوں کی ضرورت نہیں ہے۔
اس کے علاوہ HTTP میں بلٹ ان کیشنگ سیمنٹکس ہے۔ کوئی راستہ نہیں GET /products/123 کے ساتھ جواب دیں۔ Cache-Control: max-age=60 کال کرنے والے اور سرور کے درمیان کسی بھی پراکسی کے ذریعے ہیڈر کیش کیا جا سکتا ہے۔ gRPC اور ایونٹ پر مبنی پیٹرن میں مساوی بلٹ ان میکانزم نہیں ہیں۔
// REST response with cache headers
app.get("/api/v1/products/:id", async (req, res) => {
const product = await getProduct(req.params.id);
res.set("Cache-Control", "public, max-age=60");
res.set("ETag", computeETag(product));
res.json(product);
});
جہاں REST کی کمی ہے۔
REST کے وسائل پر مبنی ماڈل کو اکثر جواب جمع کرنے کے لیے متعدد دوروں کی ضرورت ہوتی ہے۔ کسی آرڈر کو اس کے آئٹمز، کسٹمر کی تفصیلات اور ڈیلیوری کی حیثیت کے ساتھ حاصل کرنے کا مطلب تین الگ الگ HTTP کالز ہو سکتی ہیں۔ ہر کال نیٹ ورک لیٹنسی، TCP ہینڈ شیک اوور ہیڈ، اور سیریلائزیشن کے اخراجات کا اضافہ کرتی ہے۔
// Three sequential calls to build one view
async function getOrderDetails(orderId: string): Promise {
const order = await fetch(`/api/orders/${orderId}`).then((r) => r.json());
const customer = await fetch(`/api/customers/${order.customerId}`).then((r) => r.json());
const shipment = await fetch(`/api/shipments/${order.shipmentId}`).then((r) => r.json());
return { order, customer, shipment };
}
آپ کمپوزٹ اینڈ پوائنٹس یا گراف کیو ایل کا استعمال کرکے اس کو کم کرسکتے ہیں، لیکن اس سے پیچیدگی بڑھ جاتی ہے۔ gRPC پیغام کی ساخت کے ذریعے اسے زیادہ قدرتی طور پر ہینڈل کرتا ہے۔
سیریلائزیشن اوور ہیڈ بھی ایک مسئلہ ہے۔ JSON انسانی پڑھنے کے قابل ہے، لیکن تجزیہ کرنا مہنگا ہے۔ ہائی تھرو پٹ اندرونی مواصلات کے لیے جہاں کوئی بھی پے لوڈ کو نہیں پڑھتا ہے، آپ CPU اور بینڈوتھ پر ٹیکس ادا کر رہے ہوں گے پڑھنے کی قابلیت کے لیے جس کی آپ کو ضرورت نہیں ہے۔
آخر میں، کوئی سلسلہ بندی نہیں ہے. معیاری REST درخواست کا جواب ہے۔ اگر سرور کو کلائنٹس تک اپ ڈیٹس کو آگے بڑھانے کی ضرورت ہے (ریئل ٹائم آرڈر ٹریکنگ، ریئل ٹائم میٹرکس)، REST کو کام کی ضرورت ہوتی ہے جیسے کہ پولنگ، سرور کے بھیجے گئے ایونٹس، یا WebSockets۔ ان میں سے کوئی بھی خود REST ماڈل کا حصہ نہیں ہے۔
gRPC: کارکردگی کے انتخاب
gRPC ایک ریموٹ پروسیجر کال فریم ورک ہے جو HTTP/2 اور پروٹوکول بفرز پر بنایا گیا ہے۔ URLs اور JSON کے بجائے، آپ سروسز اور پیغامات کی وضاحت کرتے ہیں۔ .proto آپ ایک فائل بناتے ہیں اور فریم ورک مضبوطی سے ٹائپ شدہ کلائنٹ اور سرور کوڈ تیار کرتا ہے۔
معاہدے کی تعریف
// inventory.proto
syntax = "proto3";
package inventory;
service InventoryService {
// Unary: single request, single response
rpc CheckStock(StockRequest) returns (StockResponse);
// Server streaming: single request, stream of responses
rpc WatchStockLevels(WatchRequest) returns (stream StockUpdate);
// Client streaming: stream of requests, single response
rpc BulkUpdateStock(stream StockAdjustment) returns (BulkUpdateResult);
}
message StockRequest {
string product_id = 1;
string warehouse_id = 2;
}
message StockResponse {
string product_id = 1;
int32 available = 2;
int32 reserved = 3;
google.protobuf.Timestamp last_updated = 4;
}
message StockUpdate {
string product_id = 1;
int32 available = 2;
string warehouse_id = 3;
}
چلانے کے بعد protoc (پروٹوکول بفر کمپائلر) آپ کی ٹارگٹ لینگویج میں تیار کردہ کلائنٹ اور سرور اسٹبس حاصل کرنے کے لیے۔ TypeScript کلائنٹ ہے:
import { InventoryServiceClient } from "./generated/inventory";
import { credentials } from "@grpc/grpc-js";
const client = new InventoryServiceClient(
"inventory-service:50051",
credentials.createInsecure()
);
async function checkStock(productId: string): Promise {
return new Promise((resolve, reject) => {
client.checkStock(
{ productId, warehouseId: "warehouse-eu-1" },
(error, response) => {
if (error) reject(error);
else resolve(response);
}
);
});
}
جہاں جی آر پی سی بہترین ہے۔
پروٹوکول بفرز کو کمپیکٹ بائنری فارمیٹ میں سیریلائز کیا جاتا ہے۔ JSON میں 1KB کا پیغام Protobuf میں 300 بائٹس کا ہو سکتا ہے۔ HTTP/2 ملٹی پلیکسنگ (ایک واحد TCP کنکشن پر متعدد درخواستیں) کے ساتھ مل کر، gRPC اندرونی سروس کالز کے لیے REST کے مقابلے میں بہت کم لیٹنسی اور زیادہ تھرو پٹ فراہم کرتا ہے۔ اور ہم سب جانتے ہیں کہ کارکردگی اہمیت رکھتی ہے۔
| میٹرک نظام | REST (JSON/HTTP 1.1) | gRPC (Protobuf/HTTP 2) |
|---|---|---|
| سیریلائزیشن سائز | بڑا (متن پر مبنی JSON) | کافی چھوٹا (بائنری پروٹوبف) |
| سیریلائزیشن کا وقت | آہستہ (JSON پارسنگ/سٹرنگنگ) | تیز تر (بائنری انکوڈنگ/ڈی کوڈنگ) |
| فی کنکشن کی درخواستیں۔ | 1 (کوئی پائپ لائن نہیں) | ملٹی پلیکسنگ |
| اوپر کنکشن | نئے کنکشن فی درخواست (HTTP/1.1) | ملٹی پلیکسنگ کے ذریعے مسلسل رابطہ |
پے لوڈ سائز، نیٹ ورک ٹوپولوجی، اور سرور کے نفاذ کے لحاظ سے بہتری کی صحیح مقدار مختلف ہوگی۔ بینچ مارکس میں، فرق نہ ہونے کے برابر (تیز نیٹ ورکس پر چھوٹے پے لوڈز) سے لے کر بہت زیادہ (بڑے پے لوڈ، زیادہ ہم آہنگی) تک ہوتے ہیں۔
پایان لائن: gRPC کی بائنری سیریلائزیشن اور HTTP/2 ملٹی پلیکسنگ اندرونی ٹریفک کے لیے ساختی فوائد فراہم کرتے ہیں، لیکن آپ کو تاخیر کے دعوے کرنے سے پہلے اپنے ماحول میں تاخیر کی پیمائش کرنی چاہیے۔
مزید برآں، gRPC مقامی طور پر چار مواصلاتی نمونوں کی حمایت کرتا ہے: یونری (درخواست-جواب)، سرور اسٹریمنگ، کلائنٹ اسٹریمنگ، اور دو طرفہ سلسلہ بندی۔ یہ ریئل ٹائم استعمال کے معاملات جیسے کہ ریئل ٹائم انوینٹری اپ ڈیٹس، لاگ ٹیلنگ، یا پروگریس رپورٹنگ کے لیے ایک فطری فٹ بناتا ہے۔
// Server streaming: watch inventory changes in real time
function watchStockLevels(warehouseId: string): void {
const stream = client.watchStockLevels({ warehouseId });
stream.on("data", (update: StockUpdate) => {
console.log(`Product \({update.productId}: \){update.available} available`);
});
stream.on("error", (error) => {
console.error("Stream error:", error.message);
// Reconnect logic here
});
stream.on("end", () => {
console.log("Stream ended");
});
}
آخر میں، ہم اپنی تمام سروسز میں ٹائپنگ کی طاقتور خصوصیات پیش کرتے ہیں۔ کہ .proto ایک فائل آپ کی معلومات کا واحد ذریعہ ہے۔ کلائنٹ اور سرور دونوں یہاں بنائے گئے ہیں۔ اگر انوینٹری سروس بدل جاتی ہے۔ StockResponse جب اشارہ کیا جائے تو، آرڈرنگ سروس کی تعمیر اس وقت تک ناکام ہو جائے گی جب تک کہ آپ کلائنٹ کو دوبارہ تخلیق نہیں کر لیتے۔ یہ 3am پر نہیں بلکہ مرتب وقت پر بریکنگ تبدیلیوں کو پکڑتا ہے۔
جہاں جی آر پی سی کم ہوتا ہے۔
پہلا بڑا مسئلہ براؤزر سپورٹ ہے۔ براؤزر مقامی جی آر پی سی کالز نہیں کر سکتے ہیں۔ fetch API HTTP/2 فریمنگ کو بے نقاب نہیں کرتا ہے جس کی gRPC کو ضرورت ہوتی ہے، جیسے اسٹیٹس کوڈز کے ٹریلر اور انٹرایکٹو اسٹریمز پر عمدہ کنٹرول۔
آپ کو gRPC-Web کی ضرورت ہے، جو GRPC کے براؤزر سے مطابقت رکھنے والے سب سیٹ اور مکمل پروٹوکول کے درمیان ترجمہ کرنے کے لیے Envoy جیسی پراکسی کا استعمال کرتا ہے۔ متبادل طور پر، آپ اپنی gRPC سروس کے سامنے REST یا GraphQL گیٹ وے رکھ سکتے ہیں۔
کسی بھی طرح سے، جی آر پی سی ان اینڈ پوائنٹس کے لیے قابل عمل انتخاب نہیں ہے جنہیں براؤزر براہ راست کال کرتا ہے۔ اسی لیے اس مضمون میں فیصلہ کا فریم ورک عوامی APIs کے لیے REST پر ڈیفالٹ ہے۔
ڈیبگ کرنا بھی مشکل ہے۔ تم نہیں کر سکتے curl gRPC اختتامی نقطہ۔ بائنری پے لوڈز انسانی پڑھنے کے قابل نہیں ہیں۔ اوزار جیسے grpcurl پوسٹ مین کی جی آر پی سی سپورٹ مدد کرتی ہے، لیکن ڈیبگنگ کا تجربہ براؤزر کے نیٹ ورک ٹیب میں JSON جواب کی جانچ کرنے سے بھی بدتر ہے۔
# Debugging a REST endpoint
curl -s https://inventory-service/api/v1/products/abc-123/stock | jq
# Debugging a gRPC endpoint (requires grpcurl)
grpcurl -plaintext -d '{"product_id": "abc-123"}' \
inventory-service:50051 inventory.InventoryService/CheckStock
آخر کار، آپریشنل اوور ہیڈ ایک مسئلہ ہے۔ آپ کو اس کا انتظام کرنے کی ضرورت ہے۔ .proto ایک فائل بنائیں، بلڈ پائپ لائن میں کوڈ جنریشن چلائیں، پروٹو ڈیفینیشن کا ورژن بنائیں، اور اس بات کو یقینی بنائیں کہ اسکیما تبدیل ہونے پر تمام صارفین کو دوبارہ تخلیق کیا جائے۔
دو خدمات والی ٹیم کے لیے، یہ قابل انتظام ہے۔ 20 سروسز کے لیے پروٹو رجسٹری اور گورننس کے عمل کی ضرورت ہوتی ہے۔
واقعہ پر مبنی پیغام رسانی: علیحدگی کا انتخاب
واقعہ پر مبنی مواصلات ماڈل کو اپنے سر پر بدل دیتا ہے۔ سروس A کالنگ سروس B کے بجائے، سروس A ایک بروکر (کافکا، ربیٹ ایم کیو، ایمیزون SNS/SQS، وغیرہ) کو ایونٹس شائع کرتی ہے اور سروس B انہیں متضاد طور پر استعمال کرتی ہے۔
// Order service publishes an event after confirming an order
import { Kafka } from "kafkajs";
const kafka = new Kafka({ brokers: ["kafka:9092"] });
const producer = kafka.producer();
async function publishOrderConfirmed(order: Order): Promise {
await producer.send({
topic: "order.confirmed",
messages: [
{
key: order.id,
value: JSON.stringify({
eventType: "order.confirmed",
eventId: crypto.randomUUID(),
timestamp: new Date().toISOString(),
data: {
orderId: order.id,
customerId: order.customerId,
items: order.items.map((item) => ({
productId: item.productId,
quantity: item.quantity,
})),
total: order.total,
},
}),
},
],
});
}
// Inventory service consumes the event independently
const consumer = kafka.consumer({ groupId: "inventory-service" });
async function startInventoryConsumer(): Promise {
await consumer.subscribe({ topic: "order.confirmed" });
await consumer.run({
eachMessage: async ({ message }) => {
const event = JSON.parse(message.value.toString());
for (const item of event.data.items) {
await decrementStock(item.productId, item.quantity);
}
logger.info("Inventory updated for order", {
orderId: event.data.orderId,
});
},
});
}
ایک بہترین ایونٹ بیس کے ساتھ ایک جگہ
سب سے پہلے، یہ دنیاوی علیحدگی کا استعمال کرتا ہے. پروڈیوسر صارفین کا انتظار نہیں کرتے۔ "آرڈر کنفرمیشن” پوسٹ کرنے کے بعد آرڈر سروس پر کارروائی کی جائے گی۔ اگر انوینٹری سروس میں خلل پڑتا ہے، تو اس کے بحال ہونے تک بروکر پر تقریبات منعقد کی جائیں گی۔ پروڈیوسر میں کوئی ٹائم آؤٹ نہیں ہے، کوئی دوبارہ کوشش کرنے کی کوئی منطق نہیں ہے، اور نہ ہی کوئی جھڑپ کی غلطیاں ہیں۔
ایک واقعہ متعدد آزاد ردعمل کو متحرک کر سکتا ہے۔ آرڈر کی تصدیق ہونے کے بعد، انوینٹری سروس انوینٹری کو کم کر دیتی ہے، نوٹیفکیشن سروس ایک تصدیقی ای میل بھیجتی ہے، تجزیاتی سروس تبادلوں کو ریکارڈ کرتی ہے، اور شپنگ سروس تکمیل کا آغاز کرتی ہے۔ آرڈرنگ سروس ان صارفین کو نہیں جانتی اور نہ ہی ان کی پرواہ کرتی ہے۔
order.confirmed event
├── inventory-service → Decrement stock
├── notification-service → Send confirmation email
├── analytics-service → Record conversion
└── shipping-service → Create shipment
نیا صارف شامل کرنے کے لیے پروڈیوسر کو تبدیل کرنے کی ضرورت نہیں ہے۔ یہ خدمات کے درمیان سب سے کم قابل حصول جوڑا ہے۔
ایک قدرتی آڈٹ ٹریل بھی ہے۔ اگر آپ کا بروکر واقعات کو برقرار رکھتا ہے (کافکا پہلے سے طے شدہ طور پر ایسا کرتا ہے)، تو آپ کے پاس جو کچھ بھی ہوا اس کا مکمل ریکارڈ موجود ہے۔ آپ حالت کو دوبارہ بنانے کے لیے ایونٹس کو دوبارہ چلا سکتے ہیں، مسائل کو ڈیبگ کرنے کے لیے ایونٹس کی درست ترتیب کا معائنہ کر سکتے ہیں، یا تاریخی واقعات پر کارروائی کرکے ڈیٹا کو آباد کرنے کے لیے نئی سروسز کو اسپن کر سکتے ہیں۔
جہاں واقعہ پر مبنی کمی ہے۔
آرڈر سروس کی جانب سے ‘آرڈر کنفرمیشن’ پوسٹ کرنے کے بعد، ایک ونڈو ظاہر ہوگی جہاں انوینٹری سروس نے ابھی تک ایونٹ پر کارروائی نہیں کی ہے۔ اس مدت کے دوران ہم آہنگی کی درخواستیں پرانی انوینٹری کی سطحوں کو پڑھ سکتی ہیں۔ اگر آپ کے استعمال کے معاملے میں "آپ جو لکھتے ہیں اسے پڑھیں” کی مستقل مزاجی کی ضرورت ہوتی ہے، صرف واقعہ پر مبنی مواصلت کافی نہیں ہے۔
// The problem: order confirmed, but stock not yet decremented
async function handleCheckout(cart: Cart): Promise {
const order = await createOrder(cart);
await publishOrderConfirmed(order);
// If another request checks stock RIGHT NOW,
// it sees the old (pre-decrement) value.
// The inventory consumer hasn't processed the event yet.
return order;
}
ڈیبگنگ بھی زیادہ پیچیدہ ہو جاتی ہے۔ اسٹیک ٹریس اس وقت پیدا ہوتے ہیں جب ہم وقت ساز کال چین میں مسائل پیدا ہوتے ہیں۔ جب واقعہ سے چلنے والے بہاؤ میں کوئی مسئلہ پیش آتا ہے، تو ڈیڈ لیٹر کی قطار میں ایک پیغام ظاہر ہوتا ہے اور سوالات پوچھتا ہے جیسے: یہ کس پروڈیوسر نے بھیجا؟ کب اس وقت نظام کی کیا حالت تھی؟ تقسیم شدہ ٹریسنگ میں مدد ملتی ہے، لیکن تمام سروسز میں واقعات کو آپس میں جوڑنا فطری طور پر اس کے کال اسٹیک کے ذریعے درخواست پر عمل کرنے سے زیادہ مشکل ہے۔
آپ کے وارنٹی آرڈر میں کوئی مسئلہ ہو سکتا ہے۔ زیادہ تر بروکرز پارٹیشنز (کافکا) یا قطاروں میں آرڈر دینے کی ضمانت دیتے ہیں، لیکن عالمی سطح پر نہیں۔ اگر آرڈر سروس "آرڈر کنفرمیشن” اور پھر "آرڈر کینسلیشن” پوسٹ کرتی ہے، اگر ایونٹ کسی اور پارٹیشن تک پہنچ جاتا ہے، تو انوینٹری سروس پہلے منسوخی پر کارروائی کر سکتی ہے۔
// Use a consistent partition key to guarantee ordering per entity
await producer.send({
topic: "order.events",
messages: [
{
// All events for the same order go to the same partition
key: order.id,
value: JSON.stringify(event),
},
],
});
entity ID (آرڈر ID، کسٹمر ID) کے ذریعے پیغامات کو کلیدی بنانا اس بات کو یقینی بناتا ہے کہ ایک ہی ہستی کے واقعات ترتیب کے ساتھ پروسیس ہوتے ہیں۔ مختلف اداروں کے واقعات کو متوازی طور پر پروسیس کیا جا سکتا ہے۔
آخر میں، چیزیں زیادہ پیچیدہ ہو جاتی ہیں. پیغام بروکر چلانا مفت نہیں ہے۔ کافکا کو ZooKeeper (یا KRaft)، ٹاپک مینجمنٹ، پارٹیشن ری بیلنسنگ، کنزیومر گروپ کوآرڈینیشن، اور کنزیومر لیٹینسی مانیٹرنگ کی ضرورت ہے۔ Amazon MSK، Confluent Cloud، یا Amazon SQS جیسی منظم خدمات اس بوجھ کو کم کرتی ہیں لیکن اخراجات میں اضافہ کرتی ہیں۔
بروکر کی ناکامی کو سنبھالنا
اگر بروکر دستیاب نہ ہو تو کیا ہوگا؟ اگر کوئی سروس ڈیٹا بیس کو لکھتی ہے اور پھر ایک ایونٹ شائع کرتی ہے، تو بروکر کی بندش کا مطلب ہے کہ ایونٹ ضائع ہو جائے گا چاہے ڈیٹا بیس لکھنا کامیاب ہو جائے۔
یہ نمونے آپ کی مدد کرتے ہیں:
1. آؤٹ باکس پیٹرن
براہ راست بروکر کو پوسٹ کرنے کے بجائے، ایونٹس کو اسی ڈیٹا بیس ٹرانزیکشن میں "آؤٹ باکس” ٹیبل پر لاگ ان کیا جاتا ہے جس طرح کاروباری ڈیٹا ہوتا ہے۔ ایک الگ عمل (یا تو پولر یا تبدیلی ڈیٹا کیپچر کنیکٹر جیسے ڈیبیزیم) آؤٹ باکس ٹیبل کو پڑھتا ہے اور اسے بروکر کو پوسٹ کرتا ہے۔
// Outbox pattern: write event to the database, not the broker
// db injected via dependency injection
async function confirmOrder(order: Order, db: Database): Promise {
await db.transaction(async (tx) => {
// Business write and event write in the same transaction
await tx.update("orders", { id: order.id, status: "confirmed" });
await tx.insert("outbox", {
id: crypto.randomUUID(),
topic: "order.confirmed",
key: order.id,
payload: JSON.stringify({
orderId: order.id,
customerId: order.customerId,
items: order.items,
total: order.total,
}),
created_at: new Date(),
});
});
// A separate relay process picks up outbox rows and publishes to Kafka
}
واقعات اور کاروباری اعداد و شمار جوہری طور پر لکھے جاتے ہیں، لہذا بروکر کی بندش کی وجہ سے واقعات کبھی ضائع نہیں ہوتے ہیں۔ ریلے کا عمل بروکر کے واپس آنے تک دوبارہ کوشش کرتا ہے۔
2. کم از کم ایک بار ڈیلیوری
زیادہ تر بروکرز کم از کم ایک ڈیلیوری کی ضمانت دیتے ہیں۔ اس کا مطلب ہے کہ صارفین ایک ہی ایونٹ کو ایک سے زیادہ بار دیکھ سکتے ہیں (مثال کے طور پر، دوبارہ توازن یا دوبارہ کوشش کے بعد)۔ صارفین کو بے حس ہونا چاہئے۔ ایک ہی ایونٹ کو دو بار پروسیس کرنے سے وہی نتائج برآمد ہونے چاہئیں جو ایک بار پروسیس کرنے سے ہوتے ہیں۔
// Idempotent consumer: use the eventId to deduplicate
async function handleOrderConfirmed(event: EventEnvelope): Promise {
const alreadyProcessed = await db.query(
"SELECT 1 FROM processed_events WHERE event_id = $1",
[event.eventId]
);
if (alreadyProcessed.rows.length > 0) {
logger.info("Duplicate event, skipping", { eventId: event.eventId });
return;
}
await db.transaction(async (tx) => {
await decrementStock(tx, event.data.items);
await tx.insert("processed_events", {
event_id: event.eventId,
processed_at: new Date(),
});
});
}
آؤٹ باکس پیٹرن کا مجموعہ (پروڈیوسر کی طرف) اور قابل اعتماد صارف (صارفین کی طرف) قابل اعتماد واقعہ پر مبنی مواصلات فراہم کرتا ہے یہاں تک کہ جب بروکر کو وقفے وقفے سے ناکامیوں کا سامنا کرنا پڑتا ہے۔
سمجھوتہ کی پانچ جہتیں۔
مواصلاتی پیٹرن کا انتخاب اس بارے میں نہیں ہے کہ کون سا "بہترین” ہے۔ یہ اس بارے میں ہے کہ آپ ہر ایک خاص تعامل کے لیے کتنا سمجھوتہ قبول کرنے کے لیے تیار ہیں۔ پانچ اہم ترین جہتیں یہ ہیں:
1. تاخیر کا وقت
| پیٹرن | رشتہ دار تاخیر | کیوں |
|---|---|---|
| جی آر پی سی | سب سے کم | بائنری سیریلائزیشن، HTTP/2 ملٹی پلیکسنگ، مستقل رابطے |
| باقی | کم درمیانہ | JSON اوور ہیڈ کو پارس کرتا ہے، عام طور پر HTTP/1.1 کنکشن قائم کرتا ہے۔ |
| واقعہ پر مبنی | بہترین (ڈیزائن کے لحاظ سے) | بروکر لکھنا، نقل تیار کرنا، اور صارفین کے پولنگ کے وقفہ |
صحیح تعداد پے لوڈ کے سائز، نیٹ ورک ہاپس، اور انفراسٹرکچر پر منحصر ہے۔ ساختی ترتیب یکساں ہے۔ ہم وقت ساز کالوں کے لیے، gRPC سب سے تیز ہے، اس کے بعد REST، اور لیٹنسی کو ڈیکپلنگ کرنے کے لیے ایونٹ پر مبنی میسجنگ ٹریڈز۔
اگر بھیجنے والے کو فوری جواب کی ضرورت ہے (صارف کی طرف سے ادائیگی، اصل وقت کی تلاش)، gRPC یا REST استعمال کریں۔ ایسے واقعات کا استعمال کریں جب بھیجنے والے کو ابھی نتائج کی ضرورت نہ ہو (ای میل بھیجنا، تجزیات کو اپ ڈیٹ کرنا)۔
2. جوڑا
جوڑے کی دو جہتیں ہیں۔ عارضی (کیا بھیجنے والا وصول کنندہ کا انتظار کر رہا ہے؟) اور خاکہ (کیا وہ معاہدے بانٹتے ہیں؟)
| پیٹرن | عارضی مجموعہ | سکیما کا امتزاج |
|---|---|---|
| باقی | ہائی (کالر کو بلاک کر دیا گیا) | کم (JSON لچکدار ہے) |
| جی آر پی سی | ہائی (کالر کو بلاک کر دیا گیا) | اعلی (مشترکہ .proto فائل) |
| واقعہ پر مبنی | کوئی نہیں (آگ اور بھول جاؤ) | میڈیم (مشترکہ ایونٹ سکیما) |
REST کی ڈھیلی ٹائپنگ ایک دو دھاری تلوار ہے۔ آپ صارف کو توڑے بغیر JSON جواب میں فیلڈز شامل کر سکتے ہیں (مزید تبدیلیاں محفوظ ہیں)۔ تاہم، غلطی سے کسی فیلڈ کو ہٹانے سے صارف کمپائل ٹائم کے بجائے رن ٹائم میں ناکام ہو سکتا ہے۔
gRPC کی سخت ٹائپنگ تعمیراتی وقت میں بریکنگ تبدیلیوں کو پکڑتی ہے، لیکن اس کا مطلب یہ ہے کہ کسی بھی اسکیما تبدیلیوں کے لیے کلائنٹ کو دوبارہ تخلیق کرنے کی ضرورت ہوتی ہے۔ دو خدمات کے لیے یہ معمولی بات ہے۔ ایک ہی پروٹو استعمال کرنے والی 20 خدمات کے لیے، ایک کوآرڈینیشن عمل درکار ہے۔
ایونٹ پر مبنی پیغام رسانی کو وقت کے ساتھ الگ کیا جاتا ہے، لیکن پھر بھی ایونٹ اسکیما میں ایک ساتھ بندھا رہتا ہے۔ اگر order.confirmed جب کوئی واقعہ ڈھانچہ تبدیل کرتا ہے، تمام صارفین کو منتقلی کے دوران پرانے اور نئے دونوں فارمیٹس پر کارروائی کرنی چاہیے۔
3. اسکیما ارتقاء
سکیما ارتقاء موجودہ صارفین میں خلل ڈالے بغیر خدمات کے درمیان معاہدوں کو تبدیل کرنے کا ایک طریقہ ہے۔ یہ وہ جگہ ہے جہاں تین پیٹرن سب سے زیادہ تیزی سے مختلف ہوتے ہیں۔
REST (JSON):
// Version 1: price as a number
{ "productId": "abc-123", "price": 49.99 }
// Version 2: price as an object (breaking change)
{ "productId": "abc-123", "price": { "amount": 49.99, "currency": "USD" } }
JSON میں بلٹ ان ورژننگ نہیں ہے۔ تین میں سے ایک حکمت عملی کے ذریعے انتظام کریں:
| حکمت عملی | یہ کیسے کام کرتا ہے۔ | سمجھوتہ کی منصوبہ بندی |
|---|---|---|
یو آر ایل ورژننگ (/api/v1/ بڑا /api/v2/) |
ہر ورژن ایک الگ اختتامی نقطہ ہے۔ صارفین واضح طور پر نئے ورژن کا انتخاب کرتے ہیں۔ | یہ سمجھنا سب سے آسان ہے۔ روٹ ہینڈلر کی نقل تیار کریں۔ ایک بار جب بہت سے صارفین لاک ان ہو جاتے ہیں، تو پرانے ورژن کو چھوڑنا مشکل ہو جاتا ہے۔ /v1/. |
ہیڈر ورژننگ (Accept: application/vnd.myapi.v2+json) |
ایک واحد URL، ورژن ہیڈر کے ذریعے گفت و شنید۔ | کلینر یو آر ایل، کوئی ڈپلیکیٹ راستے نہیں۔ اس کی جانچ کرنا مشکل ہے (آپ صرف URL کو اپنے براؤزر میں پیسٹ نہیں کر سکتے ہیں)۔ پراکسی اور کیشے کا رویہ زیادہ مشکل ہے کیونکہ جواب ہیڈر پر منحصر ہے۔ |
| دفاعی تجزیہ (صارفین کی طرف رواداری) | کوئی واضح ورژن نہیں ہے۔ صارفین نامعلوم فیلڈز کو نظر انداز کرتے ہیں اور گم شدہ فیلڈز کے لیے ڈیفالٹ ویلیوز استعمال کرتے ہیں۔ | اضافی تبدیلیوں کے لیے کوئی ایڈجسٹمنٹ فیس نہیں ہے۔ ان کی درجہ بندی ساختی تبدیلیوں (فیلڈ کے نام کی تبدیلیاں، قسم کی تبدیلیاں) کے طور پر کی جاتی ہے جن کے ارادے کا صارف اندازہ نہیں لگا سکتا۔ |
کسی بھی حکمت عملی میں اضافی تبدیلیاں (نئی فیلڈز) محفوظ ہیں۔ ساختی تبدیلیاں (فیلڈ کے نام کی تبدیلیاں، قسم کی تبدیلیاں) صارفین کو اپنی رفتار سے ہجرت کرنے کی اجازت دینے کے لیے واضح ورژننگ (URL یا ہیڈر) کی ضرورت ہوتی ہے۔
gRPC (پروٹوکول بفر):
// Protocol Buffers have built-in evolution rules
message StockResponse {
string product_id = 1;
int32 available = 2;
int32 reserved = 3;
// Field 4 was removed (never reuse field numbers)
string warehouse_id = 5; // New field: old clients ignore it
optional string region = 6; // Optional: old clients don't send it
}
پروٹوکول بفرز ڈیزائن کے لحاظ سے ارتقاء کو اچھی طرح سے ہینڈل کرتے ہیں۔ آپ نئے فیلڈز شامل کر سکتے ہیں (موجودہ کلائنٹس ان کو نظر انداز کر دیں گے) اور فیلڈز کو فرسودہ کر سکتے ہیں (لکھنا بند کریں اور نمبر محفوظ رکھیں)۔ optional ان فیلڈز کے لیے جو شاید موجود نہ ہوں۔
آپ فیلڈ کا نام تبدیل نہیں کر سکتے، فیلڈ کی قسمیں تبدیل نہیں کر سکتے، یا فیلڈ نمبرز کو دوبارہ استعمال نہیں کر سکتے۔ یہ اصول ٹول کے ذریعے نافذ کیے جاتے ہیں۔
ایونٹ پر مبنی (Avro/JSON سکیما):
واقعات کے لیے، ایک اسکیما رجسٹری جیسا کہ Confluent Schema Registry مطابقت کے قوانین کو نافذ کرتی ہے۔
// Register a schema with backward compatibility
// New consumers can read old events, old consumers can read new events
const schema = {
type: "record",
name: "OrderConfirmed",
fields: [
{ name: "orderId", type: "string" },
{ name: "customerId", type: "string" },
{ name: "total", type: "double" },
// New field with default: backward compatible
{ name: "currency", type: "string", default: "USD" },
],
};
اسکیما رجسٹری پروڈیوسرز کو ایسے واقعات شائع کرنے سے روکتی ہے جو مطابقت کے معاہدے کی خلاف ورزی کرتے ہیں۔ یہ حکمرانی کا سب سے طاقتور ماڈل ہے۔ صارفین تک پہنچنے سے پہلے ہی رجسٹری غیر موافق اسکیموں کو مسترد کر دیتی ہے۔
4. ڈیبگنگ اور آبزرویبلٹی
| پیٹرن | ڈیبگنگ کا تجربہ |
|---|---|
| باقی | بہترین انسانی پڑھنے کے قابل پے لوڈ، براؤزر DevTools، curlمعیاری HTTP ٹریکنگ۔ |
| جی آر پی سی | نارمل بائنری پے لوڈ کی ضرورت ہے۔ grpcurl یا ڈاکیا۔ آپ میٹا ڈیٹا کا معائنہ کر سکتے ہیں۔ تقسیم شدہ ٹریسنگ اچھی طرح سے کام کرتی ہے۔ |
| واقعہ پر مبنی | سب سے مشکل۔ غیر مطابقت پذیر بہاؤ کے لیے ارتباطی IDs، ڈیڈ لیٹر قطار چیک، اور بروکر کے لیے مخصوص ٹولز کی ضرورت ہوتی ہے۔ |
واقعہ پر مبنی نظاموں کے لیے، ارتباطی IDs ضروری ہیں۔
// Always include a correlation ID in events
interface EventEnvelope {
eventId: string;
eventType: string;
correlationId: string; // Links related events across services
causationId: string; // The event that caused this one
timestamp: string;
source: string;
data: T;
}
async function publishEvent(
topic: string,
type: string,
data: T,
correlationId: string,
causationId?: string
): Promise {
const event: EventEnvelope = {
eventId: crypto.randomUUID(),
eventType: type,
correlationId,
causationId: causationId ?? correlationId,
timestamp: new Date().toISOString(),
source: SERVICE_NAME,
data,
};
await producer.send({
topic,
messages: [{ key: data.entityId, value: JSON.stringify(event) }],
});
}
کسی مسئلے کی چھان بین کرتے وقت، ہم تمام سروسز میں ارتباطی IDs کو بازیافت کرتے ہیں اور واقعات کے پورے سلسلے کو دوبارہ تشکیل دیتے ہیں۔ اس کے بغیر، یہ گھاس کے ڈھیر میں سوئی تلاش کرنے کے مترادف ہے۔
5. آپریشنل پیچیدگی
| پیٹرن | آپ کیا چلاتے ہیں |
|---|---|
| باقی | HTTP سرور، لوڈ بیلنسر، API گیٹ وے |
| جی آر پی سی | جی آر پی سی سرور، پروٹو رجسٹری، کوڈ جنریشن پائپ لائن، جی آر پی سی ویب پراکسی (اگر آپ کے پاس براؤزر کلائنٹ ہے) |
| واقعہ پر مبنی | میسج بروکر (کافکا/ ربیٹ ایم کیو/ ایس کیو ایس)، اسکیما رجسٹری، ڈیڈ لیٹر قطار، صارفین میں تاخیر کی نگرانی |
REST میں سب سے کم آپریشنل اوور ہیڈ ہے۔ ہر ٹیم جانتی ہے کہ HTTP سرور کیسے چلانا ہے۔
gRPC بلڈ ٹائم انحصار (پروٹو کمپلیشن) کا اضافہ کرتا ہے اور ٹیموں کو نئے ٹولز سیکھنے کی ضرورت ہوتی ہے۔
ایونٹ سے چلنے والا رن ٹائم انحصار (بروکر) کا اضافہ کرتا ہے جو بہت زیادہ دستیاب ہونا چاہیے کیونکہ اگر بروکر نیچے چلا جاتا ہے، تو خدمات کے درمیان مواصلت رک جاتی ہے۔
فیصلہ سازی کا فریم ورک
اس فریم ورک کو استعمال کریں جب یہ تعین کریں کہ خدمات کا ایک خاص جوڑا کس طرح بات چیت کرے گا۔ جواب پورے نظام کے لیے شاذ و نادر ہی ایک نمونہ ہے۔
Does the caller need an immediate response?
├── Yes → Is this a public-facing or browser-accessible API?
│ ├── Yes → REST
│ └── No → Is throughput or latency critical?
│ ├── Yes → gRPC
│ └── No → REST (simpler, good enough)
└── No → Can the caller tolerate eventual consistency?
├── No → Use synchronous call (REST or gRPC) with async follow-up
└── Yes → Does the event need to trigger multiple consumers?
├── Yes → Event-driven messaging
└── No → Is ordering critical?
├── Yes → Event-driven with partition key
└── No → Event-driven (or simple queue like SQS)
کچھ مخصوص مثالیں:
| تعامل | پیٹرن | کیوں |
|---|---|---|
| براؤزر مصنوعات کی تفصیلات حاصل کرتا ہے۔ | باقی | براؤزر پہلے سے طے شدہ طور پر gRPC کو کال نہیں کرسکتے ہیں، اور REST کیشنگ کی صلاحیتیں فراہم کرتا ہے۔ |
| چیک آؤٹ ریئل ٹائم میں ادائیگیوں کی تصدیق کرتا ہے۔ | جی آر پی سی | کم تاخیر، مضبوط ٹائپنگ، صرف اندرونی استعمال (روٹ میں کوئی براؤزر نہیں) |
| آپ کے آرڈر کی تصدیق ہونے کے بعد تکمیل شروع ہو جاتی ہے۔ | واقعہ پر مبنی | متعدد صارفین، وقتی علیحدگی |
| فرنٹ اینڈ کو صارف کا پروفائل ملتا ہے۔ | باقی | سادہ CRUD، کیش ایبل، براؤزر پر مبنی |
| ایم ایل سروس سکور کی سفارشات | جی آر پی سی | ہائی تھرو پٹ، بائنری پے لوڈ، اسٹریمنگ |
| یوزر سائن اپ ایک خوش آئند ای میل کو متحرک کرتا ہے۔ | واقعہ پر مبنی | غیر مطابقت پذیر، فوری جواب کی ضرورت نہیں ہے۔ |
| سروس کی حیثیت چیک کریں۔ | باقی | سادگی، عالمگیر ٹولنگ |
| ریئل ٹائم انوینٹری کی سطح کی نگرانی | gRPC سٹریمنگ | مسلسل اپ ڈیٹس، ضرورت پڑنے پر دو طرفہ |
ہائبرڈ فن تعمیر: تینوں کا استعمال کریں۔
زیادہ تر پیداواری نظام امتزاج کا استعمال کرتے ہیں۔ یہاں ایک پیٹرن ہے جو اچھی طرح سے کام کرتا ہے:
┌──────────┐ REST ┌──────────────┐ gRPC ┌──────────────┐
│ Browser │────────────▶│ API Gateway │───────────▶│ Order Service│
└──────────┘ └──────────────┘ └──────┬───────┘
│
publishes event
│
▼
┌─────────────┐
│ Kafka │
└──────┬──────┘
┌────────────────┼────────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Inventory │ │ Notification│ │ Analytics │
│ Service │ │ Service │ │ Service │
└────────────┘ └────────────┘ └────────────┘
-
باقی کنارے پر: براؤزر معیاری HTTP کا استعمال کرتے ہوئے API گیٹ وے کے ساتھ بات چیت کرتے ہیں۔ یہ کیش ایبل، ڈیبگ ایبل اور عالمی سطح پر تعاون یافتہ ہے۔
-
جی آر پی سی گیٹ ویز اور اندرونی خدمات کے درمیان: کم تاخیر، مضبوط ٹائپنگ، موثر سیریلائزیشن۔
-
واقعہ پر مبنی ڈاؤن اسٹریم ری ایکشنز کے لیے: ایک آرڈرنگ سروس ایک ایونٹ پوسٹ کرتی ہے اور متعدد صارفین آزادانہ طور پر ردعمل ظاہر کرتے ہیں۔
غیر مطابقت پذیر ٹریپ
ایک عام غلطی ہم وقت ساز کالز (REST یا gRPC) کا استعمال کرنا ہے جہاں ایونٹس زیادہ موزوں ہوں۔ علامت: ایک سروس ایک درخواست کے دوران پانچ ہم وقت ساز کالیں کرتی ہے اور کالر کو جواب دینے سے پہلے ہر کال کے مکمل ہونے کا انتظار کرتی ہے۔
// Anti-pattern: synchronous fan-out
async function confirmOrder(order: Order): Promise {
await inventoryService.decrementStock(order.items); // 50ms
await paymentService.capturePayment(order.paymentId); // 200ms
await notificationService.sendConfirmation(order); // 100ms
await analyticsService.recordConversion(order); // 80ms
await shippingService.createShipment(order); // 150ms
// Total: 580ms, and if any one fails, the order fails
}
اپنے آرڈر کی تصدیق کے لیے، صرف پہلی دو کالیں (اسٹاک اور ادائیگی) اہم ہیں۔ باقی ایسے ردعمل ہیں جو متضاد طور پر ہو سکتے ہیں۔
// Better: synchronous for critical path, events for reactions
async function confirmOrder(order: Order): Promise {
// Critical path: must succeed for the order to be valid
await inventoryService.decrementStock(order.items);
await paymentService.capturePayment(order.paymentId);
// Non-critical: publish event, let consumers handle the rest
await publishOrderConfirmed(order);
// Total: 250ms, and notification/analytics/shipping failures
// don't block the checkout
}
یہ وہی پرتوں والا نقطہ نظر ہے جیسا کہ لچکدار API ڈیزائن مضمون۔ اہم آپریشنز ہم وقت ساز ہیں۔ غیر تنقیدی ردعمل واقعہ پر مبنی ہیں۔ کال کرنے والے تیزی سے جواب دیتے ہیں اور نیچے کی طرف سے ہونے والی غلطیاں ہونے کا امکان کم ہوتا ہے۔
اسکیما گورننس پیمانے پر
جیسے جیسے خدمات کی تعداد میں اضافہ ہوتا ہے، اسکیما مینجمنٹ ایک اہم تشویش بن جاتی ہے۔ ذیل میں ہر پیٹرن کے لیے ایک عملی نقطہ نظر ہے۔
REST: OpenAPI بطور معاہدہ
# openapi/inventory-service.yaml
openapi: "3.1.0"
info:
title: Inventory Service
version: "1.2.0"
paths:
/api/v1/products/{productId}/stock:
get:
operationId: getStock
parameters:
- name: productId
in: path
required: true
schema:
type: string
responses:
"200":
description: Stock level for the product
content:
application/json:
schema:
$ref: "#/components/schemas/StockResponse"
components:
schemas:
StockResponse:
type: object
required: [productId, available, reserved]
properties:
productId:
type: string
available:
type: integer
reserved:
type: integer
درج ذیل ٹولز کا استعمال کرتے ہوئے OpenAPI تفصیلات سے کلائنٹ SDK بنائیں: openapi-typescript یا openapi-generator. یہ gRPC کی تعمیراتی وقت کے جوڑے کے بغیر قسم کی حفاظت فراہم کرتا ہے۔
جی آر پی سی: پروٹو رجسٹری
اسٹور .proto فائل کو مشترکہ ذخیرے یا ایک وقف شدہ پروٹو رجسٹری میں اسٹور کریں (بف اسکیما رجسٹری ایک اچھا آپشن ہے)۔ میں اپنے CI میں بف کی بریکنگ تبدیلی کا پتہ لگانے کا استعمال کرتا ہوں۔
# Detects breaking changes before they merge
buf breaking --against ".git#branch=main"
اس حکم میں buf.yaml پروٹو ڈائرکٹری کے روٹ میں موجود کنفیگریشن فائل۔ فائل ماڈیول کے نام اور کسی ایسے اصول کی وضاحت کرتی ہے جو لنٹ کی خلاف ورزی کرتے ہیں یا قواعد کو تبدیل کرتے ہیں۔ تفصیلات ترتیب دینے کے لیے براہ کرم بف دستاویز سے رجوع کریں۔
اگر آپ فیلڈ کا نام تبدیل کرتے ہیں، اقسام تبدیل کرتے ہیں، یا فیلڈ نمبرز کو دوبارہ استعمال کرتے ہیں، تو آپ کی پل کی درخواست ناکام ہو جائے گی۔ بڑی تبدیلیاں (شامل کردہ فیلڈز، اضافی خدمات) منظور کی جاتی ہیں۔
واقعہ: مطابقت موڈ کے ساتھ سکیما رجسٹری
ایونٹ پر مبنی سسٹمز کے لیے، اسکیما رجسٹری اشاعت کے وقت مطابقت کو نافذ کرتی ہے۔ سنگم اسکیما رجسٹری چار طریقوں کی حمایت کرتی ہے:
| طریقہ | حکمرانی | کیسز استعمال کریں۔ |
|---|---|---|
| واپس | نیا اسکیما پرانا ڈیٹا پڑھ سکتا ہے۔ | صارف کا پہلا ارتقاء |
| اب سے | پرانا اسکیما نئے ڈیٹا کو پڑھ سکتا ہے۔ | پروڈیوسر – پہلا ارتقاء |
| سیر شدہ | دو راستہ | سب سے محفوظ اور سب سے زیادہ محدود |
| موجود نہیں ہے | کوئی چیک نہیں | صرف ترقی |
استعمال کریں FULL پیداوار کے موضوعات پر مطابقت۔ یہ اس بات کو یقینی بناتا ہے کہ کسی موضوع پر تمام ایونٹس تمام صارفین کے پڑھنے کے قابل ہیں، قطع نظر اس کے کہ اسکیما ورژن جس میں وہ تخلیق کیے گئے تھے۔
نتیجہ
اس آرٹیکل میں، آپ نے REST، gRPC، اور ایونٹ پر مبنی پیغام رسانی کے بنیادی میکانزم سیکھے، تجارت سے متعلق پانچ جہتیں جو ان میں سے کسی ایک کا انتخاب کرتے وقت اہم ہیں (لیٹنسی، کپلنگ، سکیما ایوولوشن، ڈیبگنگ، اور آپریشنل پیچیدگی)، اور مخصوص سروس کے تعاملات کے نمونوں کو ملانے کے لیے فیصلہ سازی کا فریم ورک۔
اہم نکات:
-
کنارے کے لیے آرام کریں: براؤزر کلائنٹ، عوامی API، سادہ CRUD۔ یہ کیش ایبل، ڈیبگ ایبل اور عالمی سطح پر تعاون یافتہ ہے۔
-
اندرونی گرم راستوں کے لیے gRPC: ہائی تھرو پٹ سروس ٹو سروس کالز جہاں لیٹنسی اہم ہے اور دونوں اطراف کو کنٹرول کیا جا سکتا ہے۔
-
رد عمل کا واقعہ: یہ وہ صورت ہے جب پروڈیوسرز کو انتظار نہیں کرنا چاہیے، جب ایک سے زیادہ صارفین کو ایک ہی سگنل کی ضرورت ہوتی ہے، یا جب عارضی علیحدگی جھڑنے والی غلطیوں کو روکتی ہے۔
-
تینوں کو استعمال کریں۔ زیادہ تر پیداواری نظام پیٹرن کو یکجا کرتے ہیں۔ کنارے پر آرام، اندر کی طرف gRPC، اور غیر مطابقت پذیر ورک فلو کے لیے ایونٹس۔
-
سکیما گورننس سسٹم کو توسیع دیتی ہے۔ REST کے لیے OpenAPI، gRPC کے لیے پروٹو رجسٹری، ایونٹس کے لیے اسکیما رجسٹری۔ گورننس کے بغیر، اسکیما تبدیلیاں پیداواری واقعات کی ایک بڑی وجہ بن جاتی ہیں۔
صحیح مواصلات کا نمونہ ایک جامع فیصلہ نہیں ہے۔ یہ ایک جان بوجھ کر، تعامل کے لیے مخصوص فیصلہ ہے جو کسی خاص ڈیٹا کے بہاؤ کے لیے قابل قبول تجارتی بندش پر مبنی ہے۔