3.12 ইভেন্ট-চালিত স্থাপত্য ও মেসেজিং
পরিচিতি ও প্রেরণা
ইভেন্ট-চালিত স্থাপত্য (EDA) এমন একটি শৈলী যেখানে উপাদান একে অন্যকে সরাসরি না ডেকে ইভেন্ট তৈরি ও তাতে সাড়া দিয়ে যোগাযোগ করে। একটি ইভেন্ট একটি তথ্য: ইতিমধ্যে ঘটে যাওয়া কিছু, যেমন “OrderPlaced” বা “PaymentCaptured”। একজন উৎপাদক তথ্যটি ঘোষণা করে এগিয়ে যায়, এবং যেকোনো সংখ্যক ভোক্তা কে শুনছে তা উৎপাদককে না জানিয়ে নিজস্ব সময়সূচিতে সাড়া দেয়। এটি অধ্যায় 2.3-এর অনুরোধ-ও-উত্তর কলের চেয়ে ভিন্ন ভঙ্গি, যেখানে একজন কলার একটি নির্দিষ্ট সার্ভিসকে কিছু করতে বলে এবং উত্তরের জন্য অপেক্ষা করে।
একটি বড় প্রতিষ্ঠানের জন্য আবেদন হলো পরিসরে বিযুক্তি। ডজন ডজন দল ও শত শত সার্ভিস থাকলে সবকিছু সরাসরি পয়েন্ট-টু-পয়েন্ট কলে জোড়া একটি ভঙ্গুর জাল তৈরি করে যেখানে এক দলের পরিবর্তন অন্যের ভাঙে এবং কেউ কেন তা বলতে পারে না। ইভেন্ট দলগুলোকে একে অন্যের অভ্যন্তরের মাধ্যমে নয়, তথ্যের একটি ভাগ করা স্ট্রিমের মাধ্যমে ইন্টিগ্রেট করতে দেয়, এবং একজন নতুন ভোক্তা সাবস্ক্রাইব করে যোগ দেয়, উৎপাদককে এক লাইন কোডও না বদলে। সেই বৈশিষ্ট্য, কাঁচা থ্রুপুটের চেয়েও বেশি, কেন ইভেন্ট-চালিত পদ্ধতি এন্টারপ্রাইজে জট পাকানো ইন্টিগ্রেশন প্রতিস্থাপন করে এবং সরকারে নিজস্ব সিস্টেমের মালিক সংস্থাগুলো জুড়ে ছড়াতে থাকে।
জনখাত একটি দ্বিতীয় সুবিধা পায় যা কম মূল্যায়ন করা সহজ: কী ঘটেছে তার একটি টেকসই, ক্রমবদ্ধ রেকর্ড একটি নিরীক্ষা ও স্বচ্ছতা সম্পদ। একজন নাগরিক যখন জিজ্ঞেস করেন একটি সুবিধা সিদ্ধান্ত কেন সেভাবে এল, তার দিকে নিয়ে যাওয়া ইভেন্টের একটি অপরিবর্তনীয় লগ সরাসরি উত্তর দেয়। কিন্তু ইভেন্ট-চালিত নকশা বিনামূল্যের নয় এবং সবসময় সঠিক নয়: অ্যাসিনক্রোনাস প্রবাহ অনুসরণ করা কঠিনতর, নিয়ে যুক্তি করা কঠিনতর, এবং অতিরিক্ত প্রয়োগ করা সহজ। এই অধ্যায় কখন বিযুক্তি ও পরিসর বাড়তি জটিলতার দাম দেয়, আর কখন একটি সাধারণ সিঙ্ক্রোনাস কল আপনাকে ভালো সেবা দিত, সে সম্পর্কে মতামতপূর্ণ। এটি অধ্যায় 3.3-এর বিতরিত-সিস্টেম বাস্তবতার ওপর গড়া, তাই এখনো না পড়ে থাকলে আগে সেটি পড়ুন।
মূল নীতিসমূহ
- ইভেন্ট তথ্য, নির্দেশ নয়। একটি ইভেন্ট বলে কী ঘটেছে; একটি কমান্ড কিছু ঘটতে বলে। এদের আলাদা রাখুন, এবং ইভেন্টের নাম অতীত কালে দিন।
- বিযুক্তিই উদ্দেশ্য। উৎপাদকের জানা বা যত্ন নেওয়া উচিত নয় কে তার ইভেন্ট ভোগ করে। করলে আপনার সংযুক্তি মেসেজিংয়ের পোশাক পরে আছে।
- অন্তত-একবার ডেলিভারির জন্য নকশা করুন। একবারমাত্র ডেলিভারি একটি মিথ। প্রতিটি ভোক্তাকে আইডেমপোটেন্ট করুন যাতে নকল নিরীহ হয়।
- ক্রম এমন নিশ্চয়তা যার জন্য আপনি দাম দেন। আপনি একটি পার্টিশনের ভেতরে ক্রম পান, একটি টপিক জুড়ে নয়। পার্টিশন কী সুচিন্তিতভাবে বাছুন।
- স্কিমাই চুক্তি। একটি ইভেন্টের আকার একটি পাবলিক ইন্টারফেস; একটি প্রকাশিত API-র মতো যত্নে তা বিবর্তিত করুন।
- অ্যাসিনক্রোনাস মানে অপর্যবেক্ষণযোগ্য নয়। একটি বার্তা শুরু থেকে শেষ অনুসরণ করতে না পারলে আপনি সিস্টেম চালাতে পারেন না।
- জটিলতা অর্জন করতে হয়। ইভেন্ট সোর্সিং, CQRS ও স্যাগা শক্তিশালী ও ব্যয়বহুল; সমস্যা দাবি করলে ধরুন, ডিফল্টে নয়।
সুপারিশ
কিছু গড়ার আগে ইভেন্ট, কমান্ড ও মেসেজ আলাদা করুন
এই তিনটি শব্দ বিনিময়যোগ্যভাবে ব্যবহৃত হয়, এবং বিভ্রান্তি প্রকৃত নকশা ভুল ঘটায়। একটি কমান্ড হলো কিছু করার অনুরোধ (“CapturePayment”), একটি হ্যান্ডলারের প্রতি নির্দেশিত, এবং তা প্রত্যাখ্যাত হতে পারে। একটি ইভেন্ট হলো কিছু ইতিমধ্যে ঘটেছে তার বিজ্ঞপ্তি (“PaymentCaptured”), আগ্রহী যে কারও কাছে সম্প্রচারিত, এবং তা প্রত্যাখ্যাত হতে পারে না কারণ তথ্য ইতিমধ্যে সত্য। একটি মেসেজ হলো নিরপেক্ষ খাম যা তারের ওপর দিয়ে দুটির যেকোনোটি বহন করে। পার্থক্য সংযুক্তি আকার দেয়: কমান্ড প্রেরককে একটি নির্দিষ্ট গ্রাহক ও ফলাফলের সঙ্গে জোড়ে, আর ইভেন্ট পরবর্তী কী ঘটবে তার ওপর নিয়ন্ত্রণ ছেড়ে দেয়। আপনার ইভেন্টের নাম অতীত কালে দিন, এবং এমন একটি “ইভেন্ট” প্রকাশ করছেন যা আসলে মানে “দয়া করে গিয়ে এই নির্দিষ্ট জিনিসটি করো” হলে, আপনি ছদ্মবেশে একটি কমান্ড লিখেছেন।
কিউ, লগ ও পাবলিশ/সাবস্ক্রাইব সুচিন্তিতভাবে বাছুন
সব মেসেজিং একই আকারের নয়, এবং ভুলটি বাছা একটি সাধারণ প্রাথমিক ভুল। একটি মেসেজ কিউ প্রতিটি বার্তা একজন ভোক্তার কাছে পৌঁছায় এবং সাধারণত প্রক্রিয়া হলে সরায়, যা কাজ বণ্টনে মানায়: অনেক ওয়ার্কার কাজ টানে, প্রতিটি একবার সম্পন্ন। একটি টেকসই ইভেন্ট লগ (একটি স্ট্রিম) ইভেন্ট ক্রমে রাখে এবং অনেক স্বাধীন ভোক্তাকে নিজস্ব গতিতে পড়তে দেয়, যেকোনো বিন্দু থেকে ইতিহাস পুনরায় চালিয়ে, যা ইভেন্ট বিতরণ ও নিরীক্ষায় মানায়। পাবলিশ/সাবস্ক্রাইবে উৎপাদকরা একটি টপিকে প্রকাশ করে এবং একাধিক গ্রাহক প্রত্যেকে নিজস্ব কপি পায়। ব্যবহারিক নিয়ম: বার্তাটি এমন একটি কাজ হলে যা একজন ওয়ার্কারের সম্পন্ন করা উচিত, কিউ ধরুন; এটি এমন একটি তথ্য হলে যা অনেক পক্ষ এখন বা পরে যত্ন নিতে পারে, একটি টেকসই লগ ধরুন, যা পুনরুদ্ধার ও নতুন ভোক্তা অনবোর্ডিংয়ের জন্য পুনঃচালনাও দেয়। এই পছন্দ আপনার ডেটা সংরক্ষণ কৌশলের সঙ্গে কীভাবে আন্তঃক্রিয়া করে তার জন্য অধ্যায় 3.4 দেখুন।
স্বায়ত্তশাসনের জন্য কোরিওগ্রাফি, নিয়ন্ত্রণের জন্য অর্কেস্ট্রেশন পছন্দ করুন
একটি ব্যবসায়িক প্রক্রিয়া কয়েকটি সার্ভিস জুড়লে আপনি দুটি উপায়ে তা সমন্বয় করেন। কোরিওগ্রাফিতে প্রতিটি সার্ভিস ইভেন্টে সাড়া দেয় এবং নিজের ইভেন্ট নির্গত করে, কোনো কেন্দ্রীয় মস্তিষ্ক ছাড়া: সর্বোচ্চ বিযুক্ত এবং দলের স্বায়ত্তশাসনের জন্য ভালো, কিন্তু সামগ্রিক প্রক্রিয়া কেবল উদ্ভূত আচরণ হিসেবে বিদ্যমান যা কোনো একক জায়গা বর্ণনা করে না। অর্কেস্ট্রেশনে একটি কেন্দ্রীয় সমন্বয়কারী ধাপ চালায় এবং পুরো প্রবাহ জানে: পর্যবেক্ষণ ও পরিবর্তন সহজ, প্রতিটি ধাপ যার ওপর নির্ভর করে এমন একটি উপাদানের খরচে। একটি ভালো ডিফল্ট হলো শিথিলভাবে সম্পর্কিত প্রতিক্রিয়ার জন্য কোরিওগ্রাফি (“একটি অর্ডার জাহাজে গেলে, আনুগত্য সার্ভিস পয়েন্ট দেয়”) এবং স্পষ্ট সাফল্যের শর্ত ও অবস্থা জানানোর প্রয়োজনসহ একটি সংজ্ঞায়িত লেনদেনের জন্য অর্কেস্ট্রেশন। একটি গুরুত্বপূর্ণ প্রক্রিয়াকে কেবল দশটি ইভেন্ট হ্যান্ডলারে ছড়ানো গোষ্ঠীগত জ্ঞান হিসেবে বাস করতে দেবেন না।
ইভেন্ট সোর্সিং ও CQRS কেবল যখন তারা নিজেদের জায়গা অর্জন করে তখন ধরুন
ইভেন্ট সোর্সিং অবস্থাকে একটি বর্তমান স্ন্যাপশট যা আপনি ওভাররাইট করেন তার বদলে ইভেন্টের কেবল-যোগ-করা ক্রম হিসেবে সংরক্ষণ করে, এবং আপনি সেগুলো পুনরায় চালিয়ে বর্তমান অবস্থা পুনর্নির্মাণ করেন। সুবিধা হলো নিখুঁত নিরীক্ষা ট্রেইল, যেকোনো অতীত অবস্থা পুনর্গঠনের সামর্থ্য এবং সময়গত কোয়েরি; খরচ হলো আপনি চিরকাল ইভেন্ট স্কিমা সংস্করণ করেন, পুনঃচালনা ও স্ন্যাপশট সামলান, এবং বেশিরভাগ ডেভেলপার কখনো ব্যবহার না করা একটি মানসিক মডেল বহন করেন। CQRS (Command Query Responsibility Segregation) লেখার মডেলকে এক বা একাধিক পড়ার মডেল থেকে আলাদা করে যাতে পড়া ও লেখা স্বাধীনভাবে স্কেল ও বিবর্তিত হয়; এটি ইভেন্ট সোর্সিংয়ের সঙ্গে স্বাভাবিকভাবে জোড় বাঁধে কিন্তু তা দাবি করে না। দুটিই প্রকৃত নিরীক্ষা, সম্মতি বা জটিল-কোয়েরি প্রয়োজনের ডোমেইনে জ্বলজ্বল করে, যে কারণে নিয়ন্ত্রিত অর্থ ও সরকার এদের কষ্ট করার যোগ্য মনে করে। একটি সরল create-read-update-delete সার্ভিসের জন্য এগুলো আকস্মিক জটিলতা যার জন্য আপনি আফসোস করবেন, তাই এগুলো প্রতিবর্তে পুরো সিস্টেমে নয়, আপনার ডোমেইনের যে অংশের দরকার সেখানে প্রয়োগ করুন।
বিতরিত লেনদেন সামলান স্যাগা দিয়ে, টু-ফেজ কমিট দিয়ে নয়
আপনি সাধারণত কয়েকটি সার্ভিস ও ডেটাবেস জুড়ে একটি পারমাণবিক লেনদেন মুড়তে পারেন না। বিতরিত টু-ফেজ কমিট নেটওয়ার্ক জুড়ে লক ধরে রাখে, উপলব্ধতা কাটে এবং খারাপভাবে স্কেল করে, তাই এটি কদাচিৎ ইভেন্ট-চালিত সিস্টেমে মানায়। স্যাগা প্যাটার্ন তা প্রতিস্থাপন করে: লেনদেনকে স্থানীয় লেনদেনের ক্রম হিসেবে মডেল করুন, প্রতিটি একটি ইভেন্ট নির্গত করে যা পরেরটি ট্রিগার করে, এবং প্রতিটি ধাপকে একটি ক্ষতিপূরণমূলক পদক্ষেপ দিন যা পরবর্তী কোনো ধাপ ব্যর্থ হলে তা পূর্বাবস্থায় ফেরায়। “ইনভেন্টরি সংরক্ষণ” সফল হলে কিন্তু “কার্ড চার্জ” ব্যর্থ হলে একটি ক্ষতিপূরণ ইনভেন্টরি মুক্ত করে। স্যাগা কোরিওগ্রাফ বা অর্কেস্ট্রেট করা যায়, এবং আপনাকে যা পর্যবেক্ষণ করতে হবে তার জন্য অর্কেস্ট্রেশন সাধারণত জেতে। কারণ স্যাগা পরিণামী সামঞ্জস্য গ্রহণ করে, সিস্টেম একত্র হওয়ার আগে মধ্যবর্তী অবস্থার (“সংরক্ষিত কিন্তু পরিশোধিত নয়”) মধ্য দিয়ে যায়, তাই আপনার ব্যবহারকারী অভিজ্ঞতা ও নিরীক্ষা ট্রেইল “চলমান” ও “ক্ষতিপূরণ করা” অবস্থা সৎভাবে দেখাতে নকশা করুন। অধ্যায় 3.3 একই বিষয় বিতরিত-সিস্টেম দিক থেকে কভার করে।
অন্তত-একবার ডেলিভারির জন্য নকশা করুন এবং ভোক্তাদের আইডেমপোটেন্ট করুন
মেসেজ সিস্টেম ব্যর্থতা জুড়ে সত্যিই একবারমাত্র ডেলিভারি করতে পারে না, কারণ “আমি এটি প্রক্রিয়া করেছি” বলা স্বীকৃতি নিজেই হারাতে পারে, পুনর্বিতরণ বাধ্য করে। আপনি যা অর্জন করতে পারেন তা হলো আইডেমপোটেন্ট প্রক্রিয়াকরণসহ অন্তত-একবার ডেলিভারি, যা একবারমাত্র প্রভাব তৈরি করে। আইডেমপোটেন্স মানে একই ইভেন্ট দুবার প্রক্রিয়া করা একবার করার মতোই ফল রাখে; প্রতিটি ইভেন্টে একটি আইডেমপোটেন্সি কী এবং আপনি ইতিমধ্যে যা সামলেছেন তার একটি রেকর্ড দিয়ে সেখানে পৌঁছান, যাতে একটি নকল চিহ্নিত হয়ে ফেলে দেওয়া হয়। অন্তত-একবারের বদলে সর্বাধিক-একবার ডেলিভারি (ফায়ার অ্যান্ড ফরগেট, পুনর্বিতরণ নেই) সরল কিন্তু নিঃশব্দে বার্তা হারায়, তাই তা সংরক্ষণ করুন এমন ডেটার জন্য যা হারানো সইতে পারেন। কিছু বিক্রেতার বিজ্ঞাপিত “একবারমাত্র” লেবেল সন্দেহের চোখে দেখুন: এর মানে সাধারণত নির্দিষ্ট অবস্থায় একটি সিস্টেমের সীমানার ভেতরে একবারমাত্র, বাক্যটি যে শুরু থেকে শেষ নিশ্চয়তা বোঝায় তা নয়।
পার্টিশন দিয়ে ক্রম নিয়ন্ত্রণ করুন, এবং আপনার ভোক্তা গ্রুপ জানুন
ক্রম বৈশ্বিক ও বিনামূল্যের নয়; এটি স্থানীয় এবং এর জন্য দাম দিতে হয়। একটি স্ট্রিম পার্টিশনে ভাগ হয়, এবং আপনি একটি পার্টিশনের ভেতরে ক্রম পান, টপিক জুড়ে নয়। ইভেন্ট একটি পার্টিশন কী দিয়ে একটি পার্টিশনে রুট হয়, তাই সেই কী বাছাই হলো আপনি কী ক্রমে রাখবেন তা নিয়ন্ত্রণ করার উপায়: গ্রাহক ID দিয়ে কী করুন এবং একজন গ্রাহকের ইভেন্ট একে অন্যের সাপেক্ষে ক্রমে থাকে, আর ভিন্ন গ্রাহক সমান্তরালে প্রক্রিয়া হয়। ভোক্তা গ্রুপ একদল ওয়ার্কারকে একটি টপিকের পার্টিশন ভাগ করতে দেয়, প্রতিটি পার্টিশন একজন ওয়ার্কার সামলায়, যেভাবে আপনি প্রতি-পার্টিশন ক্রম সংরক্ষণ করে থ্রুপুট স্কেল করেন; এখানে স্কেলেবিলিটি সঠিকতার সঙ্গে মেলে, অধ্যায় 3.5-এর সঙ্গে যুক্ত। আপনার প্রকৃত ক্রম প্রয়োজন প্রতিফলিত করে এবং লোড সমানভাবে ছড়ায় এমন একটি পার্টিশন কী বাছুন, কারণ বেশিরভাগ ট্রাফিক একটি পার্টিশনে ঢালা কী এমন একটি হট স্পট তৈরি করে যা যত ওয়ার্কারই হোক উপশম করতে পারে না।
স্কিমাকে রেজিস্ট্রি ও বিবর্তন নিয়মসহ চুক্তি গণ্য করুন
একটি ইভেন্টের কাঠামো এমন দলগুলো ভোগ করা একটি প্রকাশিত ইন্টারফেস যাদের সঙ্গে আপনার হয়তো কখনো দেখা হবে না, তাই অসাবধানে তা বদলানো দূর থেকে তাদের ভাঙে। আপনার ইভেন্ট স্কিমা একটি স্কিমা রেজিস্ট্রিতে রাখুন, একটি ভাগ করা ক্যাটালগ যা প্রতিটি স্কিমা সংরক্ষণ করে এবং উৎপাদক একটি বদলাতে চাইলে সামঞ্জস্য নিয়ম প্রয়োগ করে। একটি সুস্পষ্ট নীতি গ্রহণ করুন: পশ্চাৎ-সামঞ্জস্যপূর্ণ পরিবর্তন (একটি ঐচ্ছিক ক্ষেত্র যোগ) অনুমোদিত; ভাঙনকারী পরিবর্তন (একটি ক্ষেত্র সরানো, টাইপ বদলানো, নাম পরিবর্তন) একটি নতুন স্কিমা সংস্করণ ও স্থানান্তর পরিকল্পনা দাবি করে। এটি প্রতিটি ভোক্তা জুড়ে সমন্বিত ডিপ্লয় ছাড়াই উৎপাদকদের বিবর্তিত হতে দেয়, যা ঠিক আপনার ইভেন্ট বাছার কারণ। অধ্যায় 2.3-এর একই ইন্টারফেস-সংস্করণ শৃঙ্খলা প্রযোজ্য, কারণ একটি ইভেন্ট স্কিমা অন্য নামের একটি API।
ট্রানজ্যাকশনাল আউটবক্স দিয়ে ডেলিভারির নিশ্চয়তা দিন, এবং ব্যর্থতা সুস্পষ্টভাবে সামলান
একটি ক্লাসিক ত্রুটি: আপনার সার্ভিস তার ডেটাবেসে লেখে এবং তারপর একটি ইভেন্ট প্রকাশ করে, আর দুটির মাঝখানে ক্র্যাশ করে, তাই ডেটাবেস বদলেছে কিন্তু ইভেন্ট কখনো বেরোয়নি। ট্রানজ্যাকশনাল আউটবক্স এটি সারায় অবস্থা পরিবর্তনের একই ডেটাবেস লেনদেনে ইভেন্টটি একটি আউটবক্স টেবিলে লিখে, যাতে তারা একসঙ্গে কমিট বা ব্যর্থ হয়; একটি আলাদা রিলে তখন আউটবক্স পড়ে এবং ব্রোকারে প্রকাশ করে, প্রায়ই ডেটাবেস লগ অনুসরণ করতে চেঞ্জ ডেটা ক্যাপচার ব্যবহার করে। ভোগ ব্যর্থতার জন্য একটি ডেড লেটার কিউ বারবার ব্যর্থ বার্তা ধরে রাখে যাতে একটি পয়জন মেসেজ (যা কখনো সফল হবে না, সম্ভবত কারণ বিকৃত) তার পেছনের কিউ চিরকাল আটকাতে না পারে। ব্যাকপ্রেশার যোগ করুন যাতে একটি দ্রুত উৎপাদক ধীর ভোক্তাকে ভারাক্রান্ত করতে না পারে: আপনার কিউ সীমাবদ্ধ করুন, এবং ভরে গেলে মেমরি শেষ করার বদলে লোড ধীর বা ঝেড়ে ফেলুন। এই চারটি প্রক্রিয়া একটি ডেমো ও ভোর ৩টায় আপনি চালাতে পারেন এমন সিস্টেমের পার্থক্য।
অ্যাসিনক্রোনাস প্রবাহ শুরু থেকে শেষ পর্যন্ত পর্যবেক্ষণযোগ্য করুন
ইভেন্ট-চালিত হওয়ার সবচেয়ে কঠিন খরচ হলো একটি একক ব্যবসায়িক কর্ম এখন উৎপাদক, ব্রোকার ও ভোক্তা জুড়ে ছড়িয়ে পড়ে, তাদের জুড়ে রাখার কোনো কল স্ট্যাক ছাড়া। প্রতিটি ইভেন্টের মধ্য দিয়ে একটি সহসম্পর্ক ID প্রচার করুন যাতে আপনি প্রতিটি হপ জুড়ে একটি যৌক্তিক প্রবাহ অনুসরণ করতে পারেন, একই শৃঙ্খলা যা অধ্যায় 3.3 সিঙ্ক্রোনাস কলের জন্য নির্দেশ করে। ভোক্তা ল্যাগ (প্রতিটি ভোক্তা প্রকৃত সময় থেকে কতটা পিছিয়ে পড়ছে) প্রথম-শ্রেণির মেট্রিক হিসেবে অনুসরণ করুন, কারণ বাড়ন্ত ল্যাগ ঝামেলার আপনার সবচেয়ে প্রথম সতর্কতা, এবং ডেড লেটার কিউ গভীরতা, প্রক্রিয়াকরণ লেটেন্সি ও পুনর্বিতরণ হার পর্যবেক্ষণ করুন। এটি ছাড়া নিঃশব্দে ভোগ না হওয়া একটি ইভেন্ট এমন অদৃশ্য ত্রুটি হয়ে ওঠে যা দিন পরে হারানো ডেটা হিসেবে প্রকাশ পায়।
ট্রেড-অফ: সুবিধা ও অসুবিধা
| পদ্ধতি | সুবিধা | অসুবিধা / খরচ |
|---|---|---|
| সিঙ্ক্রোনাস অনুরোধ/উত্তর | নিয়ে যুক্তি করা সরল, তাৎক্ষণিক ফল, সহজ ট্রেসিং | কড়া সাময়িক সংযুক্তি, ধাপে ধাপে ব্যর্থতা, সীমিত স্কেল |
| ইভেন্ট-চালিত (লগের ওপর পাব/সাব) | বিযুক্তি, স্বাধীন স্কেলিং, পুনঃচালনা, নিরীক্ষা ট্রেইল | পরিণামী সামঞ্জস্য, কঠিনতর ট্রেসিং, আরও চলমান অংশ |
| মেসেজ কিউ (কাজ বণ্টন) | লোড সমতলকরণ, বাফারিং, ব্যাকপ্রেশার-বান্ধব | প্রতি বার্তায় একজন ভোক্তা, সম্প্রচারের জন্য কম উপযোগী |
| ইভেন্ট সোর্সিং + CQRS | পূর্ণ ইতিহাস, সময়গত কোয়েরি, পড়া/লেখা স্বাধীনভাবে স্কেল | চিরকাল স্কিমা সংস্করণ, পুনঃচালনা জটিলতা, খাড়া শেখার বক্ররেখা |
| স্যাগা (বনাম টু-ফেজ কমিট) | স্কেলযোগ্য, উপলব্ধ, বিতরিত লক নেই | পরিণামী সামঞ্জস্য, ক্ষতিপূরণ যুক্তি, যুক্তি করা কঠিনতর |
কেন্দ্রীয় টানাপোড়েন বিযুক্তি ও বোধগম্যতার মধ্যে। আপনার যোগ করা প্রতিটি ইভেন্ট উৎপাদক ও ভোক্তার মধ্যে সংযুক্তি ঢিলা করে, দলের স্বায়ত্তশাসন ও স্বাধীন স্কেলিং কিনে, এবং একই সঙ্গে একটি সিঙ্ক্রোনাস কল আপনাকে যে গল্পের এক লাইন সরলভাবে বলত তা সরিয়ে দেয়: প্রবাহ উদ্ভূত হয়, কোনো একক ফাইলে নয়, আন্তঃক্রিয়ায় বাস করে। নির্বাচনধর্মী হয়ে এর সমাধান করুন: যেখানে বিযুক্তি সত্যিই ফল দেয় সেখানে ইভেন্ট ব্যবহার করুন, যেমন দলের সীমানা জুড়ে ইন্টিগ্রেশন, অনেক ভোক্তায় ফ্যান-আউট, লোড স্পাইকের বাফারিং এবং নিরীক্ষা। যেখানে তাৎক্ষণিক উত্তর ও সরল মানসিক মডেল দরকার, যেমন একটি পাতা রেন্ডার করতে ডেটা পড়া, সেখানে সিঙ্ক্রোনাস কল রাখুন। যে ব্যর্থতার ধরন এড়াতে হবে তা হলো প্রতিটি অভ্যন্তরীণ ফাংশন কলকে একটি ইভেন্টে পরিণত করে একে স্থাপত্য বলা, একই স্থাপত্য বিচার যা অধ্যায় 3.2 আপনার গ্রহণ করা প্রতিটি প্যাটার্নের কাছে চায়।
আপনার দলের সঙ্গে আলোচনার প্রশ্ন
এই নির্দিষ্ট মিথস্ক্রিয়ার জন্য আমাদের কি সত্যিই একটি ইভেন্ট দরকার, নাকি একটি সিঙ্ক্রোনাস কল আরও স্পষ্ট ও নিরাপদ হত? এই প্রশ্ন এড়ানোই একটি সিস্টেম আকস্মিক জটিলতা জমানোর উপায়। সৎ পরীক্ষা হলো উৎপাদকের কি এখনই একটি ফল ফিরে চাই (একটি কল) নাকি সে এমন একটি তথ্য ঘোষণা করছে যাতে অন্যরা নিজস্ব সময়ে সাড়া দিতে পারে (একটি ইভেন্ট)। সাধারণ পছন্দ নয়, নির্দিষ্ট মিথস্ক্রিয়া আনুন, এবং জিজ্ঞেস করুন আপনি কী বিযুক্তি পান আর কোন ট্রেসিং স্পষ্টতা ছাড়েন। কলার যদি “ইভেন্ট” প্রক্রিয়া হওয়ার জন্য অপেক্ষা আটকে থাকে, আপনি একটি ধীর, ডিবাগ করা কঠিন সিঙ্ক্রোনাস কল বানিয়েছেন এবং সেই সুযোগের জন্য বাড়তি দাম দিয়েছেন। অভ্যন্তরীণ, একই-দল, উত্তর-এখনই-দরকার মিথস্ক্রিয়ার ডিফল্ট হওয়া উচিত সরাসরি কল; ইভেন্ট সংরক্ষণ করুন যেখানে শিথিল সংযুক্তি তার খরচ অর্জন করে।
একজন ভোক্তা একই ইভেন্ট দুবার পেলে কী ঘটে, এবং আমরা কি আসলে তা পরীক্ষা করেছি? অন্তত-একবার ডেলিভারি নিশ্চিত করে নকল ঘটবে, তাই প্রতিটি ভোক্তাকে আইডেমপোটেন্ট হতে হবে, তবু আইডেমপোটেন্সি দাবি করা সহজ এবং ভুল করাও সহজ। একটি প্রকৃত ভোক্তা হাঁটুন এবং ঠিক দেখুন দ্বিতীয় ডেলিভারি কীভাবে চিহ্নিত ও নিষ্ক্রিয় হয়, একটি আইডেমপোটেন্সি কী, একটি প্রক্রিয়াকৃত-ইভেন্ট লগ, বা স্বভাবতই আইডেমপোটেন্ট অপারেশন দিয়ে। একটি ব্যাচ পুনরায় ডেলিভারি করে এবং কোনো দ্বিগুণ চার্জ, নকল রেকর্ড বা পুনরাবৃত্ত বিজ্ঞপ্তি নেই নিশ্চিত করা একটি প্রকৃত পরীক্ষার ফল আনুন। আপনার ডেটাবেসের বাইরে যাওয়া পার্শ্বপ্রভাব, যেমন ইমেল, পেমেন্ট ও তৃতীয়-পক্ষ কল, বিশেষভাবে লক্ষ্য রাখুন, কারণ সেখানেই অ-আইডেমপোটেন্ট ত্রুটি গ্রাহকদের সরাসরি আঘাত করে। আপনার দল নকল-নিরাপত্তা প্রমাণ করা কোনো পরীক্ষা দেখাতে না পারলে ধরে নিন আপনি নকল-নিরাপদ নন।
প্রোডাকশনে একটি ইভেন্ট প্রবাহ ভাঙলে আমরা কতক্ষণে লক্ষ্য করি, এবং কি একটি বার্তা শুরু থেকে শেষ অনুসরণ করতে পারি? অ্যাসিনক্রোনাস ব্যর্থতা নীরব, তাই নিঃশব্দে প্রক্রিয়া বন্ধ করা একটি ভোক্তা হারানো ডেটা গ্রাহক অভিযোগ বা নিরীক্ষা ফাঁক না হওয়া পর্যন্ত অলক্ষ্যে থাকতে পারে। জিজ্ঞেস করুন আপনার সবচেয়ে প্রথম সংকেত কী, এবং আপনি ভোক্তা ল্যাগ ও ডেড লেটার কিউ গভীরতা কেউ না দেখা ড্যাশবোর্ডের বদলে অ্যালার্টিং মেট্রিক হিসেবে পর্যবেক্ষণ করেন কি না। একটি প্রকৃত ঘটনা বা গেম-ডে অনুশীলন আনুন এবং একটি একক সহসম্পর্ক ID উৎপাদক, ব্রোকার ও প্রতিটি ভোক্তা জুড়ে অনুসরণ করতে কত সময় লাগে তা মাপুন। উত্তর যদি “আমরা কয়েকটি সার্ভিস grep করি ও অনুমান করি” হয়, আপনার অবজার্ভেবিলিটি আপনি নেওয়া জটিলতার জন্য প্রস্তুত নয়। নিয়ন্ত্রিত খাতে একটি বার্তা ঠিক কীভাবে চলেছে তা পুনর্গঠন করতে পারা প্রায়ই সম্মতি প্রয়োজন, সৌজন্য নয়।
অনেক দল ইতিমধ্যে ভোগ করা একটি ইভেন্ট স্কিমা তাদের কাউকে না ভেঙে আমরা কীভাবে বিবর্তিত করব? একটি ইভেন্টের আকার একটি পাবলিক চুক্তি, এবং ডজন ডজন ভোক্তা একবার তার ওপর নির্ভর করলে একটি নিরীহ-দেখতে পরিবর্তন আপনি কখনো না শোনা সিস্টেম দূর থেকে ভাঙতে পারে, সতর্ক করার কোনো কম্পাইলার ছাড়া। টানাপোড়েন প্রকৃত: উৎপাদকরা দ্রুত এগিয়ে তাদের ইভেন্ট পরিষ্কার করতে চায়, আর প্রতিটি ভোক্তা আকার চিরকাল জমিয়ে রাখতে চায়, তাই আগে থেকে একমত হন কোন পরিবর্তন নিরাপদ (একটি ঐচ্ছিক ক্ষেত্র যোগ) এবং কোনটি একটি নতুন সংস্করণ ও স্থানান্তর জানালা দাবি করে (একটি ক্ষেত্র সরানো, টাইপ বদলানো, নাম পরিবর্তন)। প্রতি টপিকের ভোক্তাদের প্রকৃত তালিকা, একটি স্কিমা রেজিস্ট্রি আজ সামঞ্জস্য নিয়ম প্রয়োগ করে নাকি আকার অনানুষ্ঠানিক ঐকমত্যে বদলায়, এবং স্থানান্তরের সময় দুটি সংস্করণ কতক্ষণ সমান্তরালে চলতে পারে তা আনুন। একটি বড় এন্টারপ্রাইজ বা সংস্থা জুড়ে সরকারি ডেটা-ভাগ ব্যবস্থায় নিঃশব্দে ভাঙা স্কিমা আপনি মালিক নন এমন সিস্টেমে রেকর্ড নষ্ট করতে পারে এবং পরে নিরীক্ষা ব্যর্থতা হিসেবে দেখা দিতে পারে, তাই সামঞ্জস্য প্রয়োগকে ভদ্রতা নয়, শাসন গণ্য করুন।
আমাদের সবচেয়ে গুরুত্বপূর্ণ বহু-সার্ভিস লেনদেনের জন্য, প্রতিটি ক্ষতিপূরণমূলক পদক্ষেপ আসলে কী পূর্বাবস্থায় ফেরায়, এবং ব্যবহারকারী ও নিরীক্ষকরা কোন মধ্যবর্তী অবস্থা দেখবেন? স্যাগা একটি পারমাণবিক লেনদেনের সান্ত্বনাদায়ক বিভ্রম বিসর্জন দেয় স্থানীয় ধাপের ক্রমের বদলে যার প্রতিটি ব্যর্থ হতে পারে, তাই সিস্টেম সত্যিই একত্র হওয়ার আগে “সংরক্ষিত কিন্তু পরিশোধিত নয়” এবং “চার্জ কিন্তু জাহাজে নয়”-র মতো অবস্থার মধ্য দিয়ে যায়, এবং অন্যথা ভান করাই এমন স্যাগা পাঠানোর উপায় যা অর্থ ফাঁস করে বা রেকর্ড এতিম করে। প্রকৃত প্রক্রিয়া শুরু থেকে শেষ হাঁটুন, প্রতিটি ধাপের ক্ষতিপূরণের নাম দিন (কী ইনভেন্টরি মুক্ত করে, কী কার্ড রিফান্ড করে), এবং ঠিক করুন আপনি পর্যবেক্ষণ করতে পারেন এমন একটি অর্কেস্ট্রেটেড স্যাগা কোনো একক জায়গা বর্ণনা না করা উদ্ভূত কোরিওগ্রাফিকে হারায় কি না। সুখী পথ নয়, আপনি আসলে পরীক্ষা করা ব্যর্থতার কেস আনুন, এবং নিশ্চিত করুন ব্যবহারকারী অভিজ্ঞতা ও নিরীক্ষা ট্রেইল “চলমান” ও “ক্ষতিপূরণ করা” অবস্থা লুকানোর বদলে সৎভাবে দেখায়। অর্থ, সুবিধা বা কর সিস্টেমে একজন নিয়ন্ত্রক জিজ্ঞেস করবেন প্রতিটি মধ্যবর্তী মুহূর্তে রেকর্ড কেমন ছিল এবং ক্ষতিপূরণের জন্য কে জবাবদিহিযোগ্য ছিল, তাই স্যাগার অবস্থাগুলোই একটি সম্মতি নিদর্শন।
ব্রোকার বা ইভেন্ট লগ কে চালায়, এবং আমরা কি একটি ম্যানেজড বিকল্পের বিপরীতে তা পরিচালনার প্রকৃত খরচ গুনেছি? মেসেজিং মেরুদণ্ড এমন বিনামূল্যের অবকাঠামো নয় যা আপনি চিত্রে আঁকলেই আবির্ভূত হয়: কেউ এটি প্যাচ করে, তার পার্টিশন স্কেল করে, ধারণ টিউন করে, ভোর ৩টায় পেজ করলে সাড়া দেয়, এবং তার সক্ষমতা ও ব্যর্থতার ধরনের মালিক। একটি ওপেন-সোর্স ব্রোকার নিজে হোস্ট করা ও একটি ম্যানেজড সেবা কেনার মধ্যে সুচিন্তিতভাবে ঠিক করুন, পরিচালনগত বোঝা ও লাইসেন্স খরচের বিপরীতে নিয়ন্ত্রণ ও ডেটা আবাসন ওজন করে, এবং আপনার দলের একটি বিতরিত লগ ভালোভাবে চালানোর গভীরতা আছে কি না সে সম্পর্কে সৎ থাকুন। মালিকানার মোট খরচ আনুন: অন-কল বোঝা, প্রয়োজনীয় বিশেষজ্ঞ দক্ষতা, ধারণ ও সংরক্ষণ বিল, এবং একটি ব্রোকার বিভ্রাট প্রতিটি নির্ভরশীল প্রবাহের কী করে। একটি এন্টারপ্রাইজের জন্য উত্তর একটি প্ল্যাটফর্ম দলের আদেশ আকার দেয়, এবং একটি সরকারি সংস্থার জন্য ক্রয়ের নিয়ম, ডেটা-সার্বভৌমত্ব প্রয়োজন এবং বিক্রেতা লক-ইন এড়ানোর কঠিন প্রয়োজন সস্তাতম বিকল্পকে ছাপিয়ে যেতে পারে, তাই আপনি এক দশক চালাবেন এমন প্রযুক্তিতে প্রতিশ্রুতির আগে সেই সীমাবদ্ধতা প্রকাশ করুন।
খাতভেদে দৃষ্টিভঙ্গি
স্টার্টআপ। আপনার দুর্লভতম সম্পদ প্রকৌশল মনোযোগ, তাই ফ্যান-আউট সত্যিই ব্যথা না দেওয়া পর্যন্ত সিঙ্ক্রোনাস থাকুন। তিনটি জিনিস একটি কর্মে সাড়া দিতে হলে নিজস্ব ব্রোকার ক্লাস্টার দাঁড় করানোর বদলে একটি ম্যানেজড কিউ বা লগে একটি একক ইভেন্ট (“OrderPlaced”-এর মতো) প্রকাশ করুন, এবং পেমেন্ট ও যা কিছুতে তাৎক্ষণিক উত্তর দরকার তা সরাসরি কল রাখুন। পরিশীলিত দেখাতে ইভেন্ট সোর্সিং, CQRS বা স্যাগা গ্রহণ করবেন না; সেই জটিলতা একটি ক্ষুদ্র দলকে ছাড়িয়ে যাবে এবং আপনি যে পুনরাবৃত্তিতে প্রতিযোগিতা করছেন ঠিক সেটিই ধীর করবে।
ছোট ব্যবসা। আপনার মেসেজিং বিশেষজ্ঞ নেই এবং Kafka চালানোর ক্ষুধা নেই, তাই অ্যাসিনক্রোনাস ইন্টিগ্রেশনকে চালানোর বদলে কেনার কিছু গণ্য করুন। আপনার বিদ্যমান টুল ইতিমধ্যে যে ইভেন্ট নির্গত করে (ওয়েবহুক, আপনার ক্লাউড প্রদানকারী বা SaaS প্ল্যাটফর্মে ইনবিল্ট কিউ) তার ওপর ভর করুন এবং একটি ম্যানেজড সেবাকে ডেলিভারি, ধারণ ও আইডেমপোটেন্সি নল-ব্যবস্থার মালিক হতে দিন। পছন্দকে সৎভাবে কেনা-বনাম-বানানো ফ্রেম করুন: ভোর ৩টায় আপনি জোগাতে বা ডিবাগ করতে পারেন না এমন বিশেষায়িত ব্রোকারের চেয়ে হাতে-গোনা নির্ভরযোগ্য ওয়েবহুক হ্যান্ডলার ভালো।
এন্টারপ্রাইজ। আপনার সমস্যা অনেক দল জুড়ে ইন্টিগ্রেশন খরচ, তাই প্রতিদান একটি শাসিত ভাগ করা প্ল্যাটফর্ম: একটি টেকসই ইভেন্ট লগ, প্রয়োগ করা সামঞ্জস্য নীতিসহ একটি স্কিমা রেজিস্ট্রি, স্পষ্ট টপিক মালিকানা, এবং প্রমিত আইডেমপোটেন্সি ও আউটবক্স প্যাটার্ন যাতে প্রতিটি দল সেগুলো পুনরাবিষ্কার না করে। এটি সেই পরিবেশ যেখানে একটি ভঙ্গুর এন্টারপ্রাইজ সার্ভিস বাস বা পয়েন্ট-টু-পয়েন্ট লিংকের জাল প্রতিস্থাপন প্রকৃত সঞ্চয়ে চক্রবৃদ্ধি হয়, এবং যেখানে দৃশ্যমান অবস্থাসহ অর্কেস্ট্রেটেড স্যাগা পরিচালন কর্মীদের বহু-ধাপ প্রক্রিয়া পরিচালনা করতে দেয়। অবজার্ভেবিলিটি ও স্কিমা-শাসন বিনিয়োগ সুস্পষ্টভাবে বাজেট করুন, কারণ এই পরিসরে একটি নীরব ভোক্তা ব্যর্থতা ডজন ডজন সিস্টেম জুড়ে হারানো ডেটা হয়ে ওঠে।
সরকার। একটি টেকসই, ক্রমবদ্ধ ইভেন্ট লগ একটি নিরীক্ষা ও স্বচ্ছতা সম্পদ: এটি তথ্যের একটি অপরিবর্তনীয় ক্রম দিয়ে “এই সিদ্ধান্ত কেন এমন এল” এর উত্তর দেয়, তাই যেখানে জবাবদিহি দাবি করে সেখানে ইভেন্ট সোর্সিংয়ের দিকে ঝুঁকুন। আন্তঃসংস্থা ডেটা-ভাগে একটি স্থিতিশীল ইভেন্ট ID-তে ডিডুপ্লিকেশনসহ অন্তত-একবার ডেলিভারি দরকার যাতে পুনর্বিতরণ করা রেকর্ড কখনো নকল কেস তৈরি না করে, এবং ক্রয়ে ডেটা-সার্বভৌমত্ব, ব্রোকারের সীমাবদ্ধতা প্রকাশ, এবং লক-ইনের বিপরীতে বহনযোগ্যতা ওজন করা উচিত। যথাযথ ক্ষেত্রে প্রকাশ করুন প্রবাহ কীভাবে কাজ করে এবং একজন নাগরিক কীভাবে একটি স্বয়ংক্রিয় ফলাফল চ্যালেঞ্জ করতে পারেন, এবং তদারকি সংস্থা পরিদর্শন করতে চাইবে এমন রক্ষণযোগ্য রেকর্ড হিসেবে ইভেন্ট লগ রাখুন।
উদাহরণ
স্টার্টআপ। একটি ছোট ই-কমার্স স্টার্টআপ একটি সিঙ্ক্রোনাস প্রবাহ দিয়ে শুরু করে: চেকআউট পেমেন্ট সার্ভিস ডাকে এবং অপেক্ষা করে। বাড়ার সঙ্গে সে চায় অর্ডার নিশ্চিতকরণ ইমেল, ইনভেন্টরি হালনাগাদ এবং একটি আনুগত্য কর্মসূচি ক্রয়ে সাড়া দিক, এবং চেকআউটের ভেতরে প্রতিটিকে আরেকটি সিঙ্ক্রোনাস কল হিসেবে জোড়া চেকআউটকে ধীর ও ভঙ্গুর করে। দল একটি টেকসই লগে একটি একক “OrderPlaced” ইভেন্ট প্রকাশ করে এবং তিনটি স্বাধীন ভোক্তাকে সাড়া দিতে দেয়, তাই চেকআউট আবার দ্রুত, এবং পরে চতুর্থ প্রতিক্রিয়া যোগে একে বদলানোর দরকার হয় না। তারা পেমেন্ট ক্যাপচার সিঙ্ক্রোনাস রাখে, কারণ অর্ডার নিশ্চিত করার আগে তাদের হ্যাঁ-বা-না উত্তর দরকার, যা তাদের আকারে টানার ঠিক রেখা।
এন্টারপ্রাইজ। একটি বৈশ্বিক বীমাকারী পয়েন্ট-টু-পয়েন্ট ইন্টিগ্রেশন ও একটি বুড়ো এন্টারপ্রাইজ সার্ভিস বাস (ESB), একটি কেন্দ্রীয় হাব যার মধ্য দিয়ে প্রতিটি সিস্টেম রুট করে এবং যা একটি বাধা ও একক ব্যর্থতার বিন্দু হয়ে উঠেছে, তাতে ডুবছে। সে একটি টেকসই ইভেন্ট লগে স্থানান্তর করে যেখানে প্রতিটি ডোমেইন তার তথ্য (পলিসি ইস্যু, দাবি দাখিল, পেমেন্ট করা) প্রকাশ করে এবং ভোক্তা দলগুলো তাদের যা দরকার তাতে সাবস্ক্রাইব করে। একটি অর্কেস্ট্রেটেড দাবি স্যাগা, যাতে পরিচালন কর্মীরা প্রতিটি দাবির অবস্থা দেখতে পান, ব্যর্থ ধাপের ক্ষতিপূরণসহ বহু-ধাপ নিষ্পত্তি সমন্বয় করে। একটি স্কিমা রেজিস্ট্রি পলিসি দলকে চল্লিশটি ভোক্তা সিস্টেম জুড়ে সমন্বিত ডিপ্লয় ছাড়া তাদের ইভেন্ট বিবর্তিত করতে দেয়, ঠিক সেই ভঙ্গুরতা যা পুরোনো ESB চাপাত।
সরকার। একটি জাতীয় কর সংস্থাকে “আমার মূল্যায়ন কেন এমন এল” এর জন্য নাগরিক ও নিরীক্ষকদের একটি রক্ষণযোগ্য উত্তর দিতে হয়। সে মূল্যায়ন ডোমেইন ইভেন্ট সোর্সিংয়ে মডেল করে, তাই প্রতিটি পরিবর্তন একটি ক্রমবদ্ধ লগে একটি অপরিবর্তনীয় ইভেন্ট এবং বর্তমান মূল্যায়ন সেই ইভেন্টের একটি পুনঃচালনা; একজন নাগরিক একটি অঙ্ক নিয়ে বিরোধ করলে একজন কেসওয়ার্কার যেকোনো অতীত তারিখে ঠিক অবস্থা পুনর্গঠন করে এবং তা তৈরি করা তথ্যের ক্রম দেখান। আন্তঃসংস্থা ডেটা-ভাগ অন্তত-একবার ডেলিভারিসহ টেকসই টপিকে চলে, এবং প্রতিটি সংস্থার ভোক্তা একটি ইভেন্ট ID-তে ডিডুপ করে যাতে পুনর্বিতরণ করা রেকর্ড কখনো নকল কেস তৈরি না করে। ইভেন্ট লগ তদারকি সংস্থার প্রয়োজনীয় নিরীক্ষা ট্রেইলও হয়, একটি সম্মতি বাধ্যবাধকতাকে নকশার উপজাতে পরিণত করে।
ব্যবসায়িক যুক্তি: প্রেরণা, ROI ও TCO
ইভেন্ট-চালিত স্থাপত্যের প্রতিদানে একটি জিনিস প্রাধান্য পায়: সময়ের সঙ্গে ইন্টিগ্রেশনের খরচ। পয়েন্ট-টু-পয়েন্ট ইন্টিগ্রেশন সংযোগের সংখ্যার সঙ্গে সেই খরচ বাড়ায়, যা সিস্টেমের সংখ্যার চেয়ে দ্রুত বাড়ে, তাই ইন্টিগ্রেশন সেই কর হয়ে ওঠে যা আপনার সরবরাহ সক্ষমতা খেয়ে ফেলে। ইভেন্ট এটি সমতল করে, কারণ দলগুলো তথ্যের একটি ভাগ করা স্ট্রিমের মাধ্যমে ইন্টিগ্রেট করে, একজন নতুন ভোক্তা সাবস্ক্রাইব করে যোগ দেয়, এবং উৎপাদক একটি সংস্করণযুক্ত স্কিমার পেছনে বিবর্তিত হয়, তাই পরবর্তী ইন্টিগ্রেশনের প্রান্তিক খরচ তীব্রভাবে কমে। নেতৃত্বকে বলার মূল ROI গল্প হলো এটিই: কাঁচা পারফরম্যান্স নয়, অনেক দল জুড়ে পরিবর্তনের খরচের চক্রবৃদ্ধি হ্রাস।
আপনাকে বিশ্বাস করানোর জন্য মালিকানার মোট খরচের নাম সৎভাবে দিন। আপনি চালানোর ব্রোকার অবকাঠামো, রক্ষণাবেক্ষণের স্কিমা শাসন, এবং খাড়াতর পরিচালনগত শেখার বক্ররেখা নেন, কারণ অ্যাসিনক্রোনাস সিস্টেম সত্যিই ডিবাগ করা কঠিনতর, তাই অবজার্ভেবিলিটি বিনিয়োগ আগে বাজেট করুন। যেখানে মানায় সেখানে ইভেন্ট গ্রহণ না করার খরচের বিপরীতে এগুলো ওজন করুন: একটি জমে-যাওয়া ইন্টিগ্রেশন স্তর যেখানে প্রতিটি পরিবর্তন বহু-দল সমন্বয় প্রকল্প, একটি লিগ্যাসি ESB যা এমন বাধা হয়ে উঠেছে যা কেউ ছুঁতে সাহস পায় না, এবং পুরোনোগুলো না বিঘ্নিত করে সামর্থ্য যোগের অক্ষমতা। ভঙ্গুর পয়েন্ট-টু-পয়েন্ট তার প্রতিস্থাপন করা এন্টারপ্রাইজ এবং টেকসই নিরীক্ষা ট্রেইল গড়া সরকারের জন্য প্রতিদান সবচেয়ে শক্তিশালী যেখানে নিরীক্ষা ও বিযুক্তি প্রয়োজন প্রকৃত। যেখানে সেই প্রয়োজন অনুপস্থিত সেখানে সৎ উত্তর হলো একটি সরলতর সিঙ্ক্রোনাস নকশার TCO কম, এবং আপনার তা বলা উচিত।
অ্যান্টি-প্যাটার্ন ও ফাঁদ
- ছদ্মবেশে বিতরিত মনোলিথ। যে সার্ভিস অবশ্যই একসঙ্গে ডিপ্লয় করতে হয় এবং একে অন্যের অভ্যন্তরীণ ইভেন্টের ওপর নির্ভর করে। আপনি একটি ব্রোকার যোগ করেছেন কিন্তু সংযুক্তি রেখেছেন, তাই দুই শৈলীর অসুবিধাই পেয়েছেন।
- কমান্ড হিসেবে ইভেন্ট। “ইভেন্ট” প্রকাশ করা যার আসল মানে “আমার জন্য এই নির্দিষ্ট জিনিসটি করো”, বাড়তি লেটেন্সি ও খারাপ ট্রেসযোগ্যতাসহ কড়া সংযুক্তি পুনর্সৃষ্টি।
- একবারমাত্র ডেলিভারি ধরে নেওয়া। ব্রোকার অনিবার্যভাবে একটি বার্তা পুনর্বিতরণ করলে যে ভোক্তা ভেঙে পড়ে, ডাবল-চার্জ করে বা রেকর্ড নকল করে।
- সবকিছুতে ইভেন্ট সোর্সিং। ইতিহাস কখনো না লাগা সরল create-read-update-delete ডোমেইনে ইভেন্ট সোর্সিং ও CQRS প্রয়োগ, কোনো লাভ ছাড়া খাড়া জটিলতা কেনা।
- স্কিমা শাসন নেই। উৎপাদকরা ইচ্ছামতো ইভেন্টের আকার বদলায়, সামঞ্জস্য পরীক্ষা ছাড়া নিম্নধারা ভোক্তাদের দূর থেকে ভাঙে।
- আউটবক্স উপেক্ষা। ডেটাবেসে লেখা ও একটি ইভেন্ট প্রকাশ দুটি আলাদা ধাপ হিসেবে করা, তাই দুটির মাঝে ক্র্যাশ নিঃশব্দে ইভেন্ট হারায় বা ভুতুড়ে ইভেন্ট নির্গত করে।
- ডেড লেটার সামলানো নেই। একটি একক পয়জন মেসেজ একটি পার্টিশন আটকায়, বা ব্যর্থ বার্তা ধরে পরিদর্শনের মতো কোনো কিউ ছাড়া উধাও হয়।
- অদৃশ্য প্রবাহ। সহসম্পর্ক ID, ভোক্তা-ল্যাগ অ্যালার্ট ও ট্রেসিং ছাড়া অ্যাসিনক্রোনাস প্রক্রিয়াকরণ, তাই হারানো ডেটা না হওয়া পর্যন্ত ব্যর্থতা নীরব।
পরিপক্বতা মডেল
- স্তর ১, সূচনা: ইন্টিগ্রেশন অ্যাড হক পয়েন্ট-টু-পয়েন্ট কল, বা একটি ব্রোকার আছে কিন্তু সিঙ্ক্রোনাস অনুরোধ/উত্তরের মতো ব্যবহৃত। নকল ভোক্তাদের ভাঙে, কোনো স্কিমা শৃঙ্খলা বা হপ-জোড়া ট্রেসিং নেই, এবং ব্যর্থ বার্তা নিঃশব্দে উধাও হয়।
- স্তর ২, বিকাশ: কিছু প্রবাহে একটি ব্রোকার বা লগ প্রকৃত ব্যবহারে, এবং কয়েকটি দলের মৌলিক চর্চা আছে: ভোক্তা আইডেমপোটেন্ট হয়ে উঠছে এবং ডেড লেটার কিউ কিছু ব্যর্থতা ধরে। কিন্তু দল জুড়ে পদ্ধতি অসঙ্গত, ইভেন্ট ও কমান্ড এখনো গুলিয়ে, স্কিমা অনানুষ্ঠানিক ঐকমত্যে বদলায়, এবং অবজার্ভেবিলিটি পাতলা।
- স্তর ৩, মানসম্মতকরণ: প্রতিষ্ঠান জুড়ে ইভেন্ট, কমান্ড ও মেসেজ সুচিন্তিতভাবে আলাদা। ভোক্তা মান হিসেবে আইডেমপোটেন্ট, স্কিমা নথিবদ্ধ ও প্রয়োগ করা সামঞ্জস্য নীতিসহ একটি রেজিস্ট্রিতে থাকে, এবং ট্রানজ্যাকশনাল আউটবক্স ডেলিভারির নিশ্চয়তা দেয়। ক্ষতিপূরণসহ স্যাগা বহু-সার্ভিস লেনদেন সামলায়, সহসম্পর্ক ID প্রতিটি হপের মধ্য দিয়ে প্রচারিত হয়, এবং এই প্যাটার্ন লিখিত ও প্রতিটি দলের হাতে ছেড়ে না দিয়ে সামঞ্জস্যপূর্ণভাবে প্রয়োগ করা।
- স্তর ৪, ব্যবস্থাপনা: ইভেন্ট প্ল্যাটফর্ম ভিত্তিরেখার বিপরীতে তথ্য দিয়ে মাপা ও নিয়ন্ত্রিত। ভোক্তা ল্যাগ, ডেড লেটার কিউ গভীরতা, পুনর্বিতরণ হার এবং প্রক্রিয়াকরণ লেটেন্সি কেউ না দেখা ড্যাশবোর্ডের বদলে সম্মত সীমাসহ অ্যালার্টিং মেট্রিক হিসেবে অনুসরণ করা হয়; একজন উৎপাদক একটি পরিবর্তন পাঠানোর আগে স্কিমা সামঞ্জস্য স্বয়ংক্রিয়ভাবে যাচাই হয়; পুনঃচালনা, ব্যর্থতা সামলানো ও আইডেমপোটেন্সি আশার বদলে নির্দিষ্ট ছন্দে পরীক্ষা করা হয়। একটি মিথস্ক্রিয়া ইভেন্ট নাকি সিঙ্ক্রোনাস কল হওয়া উচিত তা প্রমাণে ঠিক হয়, এবং প্রতিটি ব্রোকারের সক্ষমতা, ধারণ খরচ ও নির্ভরযোগ্যতা লক্ষ্যের বিপরীতে পর্যালোচিত হয়।
- স্তর ৫, সমন্বয়: ইভেন্ট-চালিত ও সিঙ্ক্রোনাস শৈলী প্রতি মিথস্ক্রিয়ায় দ্বিতীয় স্বভাবে বাছা হয়, এবং ইভেন্ট সোর্সিং ও CQRS ঠিক সেখানে প্রয়োগ হয় যেখানে নিরীক্ষা ও কোয়েরি প্রয়োজন তা যথার্থ করে এবং অন্যত্র নয়। অ্যাসিনক্রোনাস প্রবাহ সিঙ্ক্রোনাসের মতোই পর্যবেক্ষণযোগ্য, প্ল্যাটফর্ম প্রয়োজন সরলে নিরন্তর উন্নত হয় (মৃত টপিক অবসর, স্কিমা শাসন বিবর্তন, পার্টিশন পুনর্ভারসাম্য), এবং মেসেজিং বৃহত্তর স্থাপত্য ও নিরীক্ষা কৌশলের সঙ্গে একীভূত, তাই ব্যবসা ও তার বাধ্যবাধকতা বদলালে প্রতিষ্ঠান তার ইভেন্ট নকশা খাপ খাওয়ায়।
আলোচনার ভাবনা
- আপনার বর্তমান কোন “ইভেন্ট” গোপনে কমান্ড, এবং সেগুলো সৎভাবে মডেল করলে আপনি কোন সংযুক্তি সরাতেন?
- আগামীকাল আপনার ভোক্তাদের মধ্য দিয়ে এক দিনের পূর্ণ ইভেন্ট পুনরায় চালালে কী ভাঙত, এবং তা আপনার আইডেমপোটেন্সি ও পুনঃচালনা-নিরাপত্তা সম্পর্কে কী বলে?
- আপনার ডোমেইনের কোন অংশের সত্যিই ইভেন্ট সোর্সিংয়ের নিরীক্ষা ট্রেইল দরকার, আর কোনগুলো সরল অবস্থা যা সোর্স করলে কেবল জটিল করবেন?
- কোনো ঝুঁকিপূর্ণ বিগ-ব্যাং কাটওভার ছাড়া আপনি কীভাবে একটি লিগ্যাসি এন্টারপ্রাইজ সার্ভিস বাস বা পয়েন্ট-টু-পয়েন্ট ইন্টিগ্রেশনের জাল থেকে সরবেন?
- আপনার সবচেয়ে গুরুত্বপূর্ণ বহু-সার্ভিস প্রক্রিয়া কি ক্ষতিপূরণসহ প্রকৃত অর্কেস্ট্রেটেড স্যাগা, নাকি কোনো একক জায়গা বর্ণনা না করা উদ্ভূত কোরিওগ্রাফি?
প্রধান শিক্ষা
- ইভেন্ট-চালিত স্থাপত্য বিযুক্তি, স্বাধীন স্কেলিং, পুনঃচালনা ও নিরীক্ষা ট্রেইল কেনে, এবং বোধগম্যতা ও পরিচালনগত জটিলতা খরচ করে, তাই যেখানে সুবিধা প্রকৃত সেখানে প্রতি মিথস্ক্রিয়ায় একে বাছুন।
- ইভেন্ট (যে তথ্য ঘটেছে), কমান্ড (কাজ করার অনুরোধ) ও মেসেজ (খাম) আলাদা রাখুন, কারণ বিভ্রান্তি প্রকৃত সংযুক্তি ভুল ঘটায়।
- অন্তত-একবার ডেলিভারির জন্য নকশা করুন এবং প্রতিটি ভোক্তাকে আইডেমপোটেন্ট করুন; একবারমাত্র ডেলিভারি একটি মিথ, এবং একবারমাত্র প্রভাব একটি প্রকৌশল অর্জন।
- ক্রম প্রতি পার্টিশনে, স্কিমা চুক্তি যা রেজিস্ট্রিতে থাকে, এবং আউটবক্স, ডেড লেটার কিউ ও ব্যাকপ্রেশার সেই নল-ব্যবস্থা যা মেসেজিংকে প্রোডাকশন-প্রস্তুত করে।
- টু-ফেজ কমিটের বদলে ক্ষতিপূরণসহ স্যাগা ব্যবহার করুন, এবং ইভেন্ট সোর্সিং ও CQRS ধরুন কেবল যেখানে নিরীক্ষা ও কোয়েরি প্রয়োজন তাদের খাড়া খরচ যথার্থ করে।
- অ্যাসিনক্রোনাস প্রবাহ ব্যর্থ হলে নীরব, তাই সহসম্পর্ক ID, ভোক্তা-ল্যাগ পর্যবেক্ষণ ও শুরু-থেকে-শেষ ট্রেসিং একটি চালানো-যায় সিস্টেম ও একটি অদৃশ্য সিস্টেমের পার্থক্য।
তথ্যসূত্র ও আরও পড়ার জন্য
- Martin Kleppmann, Designing Data-Intensive Applications
- Gregor Hohpe ও Bobby Woolf, Enterprise Integration Patterns
- Chris Richardson, Microservices Patterns (স্যাগা, ট্রানজ্যাকশনাল আউটবক্স, CQRS)
- Sam Newman, Building Microservices
- Ben Stopford, Designing Event-Driven Systems
- Adam Bellemare, Building Event-Driven Microservices
- Vaughn Vernon, Implementing Domain-Driven Design (ইভেন্ট সোর্সিং ও CQRS)
- Martin Fowler, “Event Sourcing” এবং “CQRS” (martinfowler.com নিবন্ধ)
- Hector Garcia-Molina ও Kenneth Salem, “Sagas” (1987)