0

web-application-scalability

ওয়েব অ্যাপ্লিকেশান এর “(Scalability) স্ক্যালাবিলিটি” এই শব্দটি আমরা যারা ওয়েব অ্যাপ্লিকেশান নিয়ে কাজ করি তারা অনেকেই মোটামুটি বুঝি। সহজভাবে বললে Scalability বলতে বোঝায় কোনো একটা এপ্লিকেশন বা সার্ভিসের স্কেল (Scale) করার ক্ষমতা, অর্থাৎ চাহিদা বা চাপ বৃদ্ধির সাথে সাথে সেই চাপ সামলে নেয়ার ক্ষমতা।
প্রতিদিন আমরা বিভিন্ন কাজের জন্য ওয়েব ব্যবহার করি। সেটা হতে পারে ব্রাউজার অথবা কোন মোবাইল অ্যাপ থেকে। তো সেটা যাই হোক না কেন, ধীরে ধীরে সিস্টেম এর ব্যবহারকারীর সংখ্যা যেমন বাড়তে থাকে, ঠিক একইভাবে অন্যান্য ডাটাও বাড়তে থাকে। যখন ডাটা কম ছিল, তখন তো ভালই চলছিল সব। কিন্তু যখন এইভাবে ডাটা সিস্টেমে অনেক বেশি হয়ে গেল, তখন কিছু সমস্যা দেখা চোখে পড়ে। সমস্যাগুলো অনেকটা এরকম-

১) আগের সিস্টেম যদি খরগোশ হয়ে থাকে, তাহলে এখন সিস্টেম কচ্ছপ এর মত আচরন করে। অর্থাৎ সিস্টেম আগের থেকে অনেক স্লো হয়ে গিয়েছে। আগে ক্লিক করলে ধুম করেই ডাটা পাওয়া যেত সার্ভার এর কাছ থেকে, কিন্তু এখন ক্লিক করে এক কাপ চা খাওয়ার পরে কাঙ্খিত ডাটা আসে।

২) বেশি ব্যবহারকারী হওয়ার কারনে অনেকে আবার সেটাও পায় না। অর্থাৎ তাদের রিকোয়েস্ট মারা যায়। আমরা সুন্দর করে সেটাকে রিকোয়েস্ট টাইমআউট (Request Timeout) বলি।

৩) সার্ভার রিস্টার্ট প্রতিদিনকার রুটিন হয়ে যায়। কারণ সার্ভার এর মেমরি সহ অন্যান্য রিসোর্স ১০০% ইউজ হতে থাকে। তখন সার্ভার আর সার্ভ করতে পারে না। অর্থাৎ সে তার সর্বোচ্চ ক্ষমতার থেকেও বেশি লোড পাচ্ছে।

৪) একইভাবে ডাটাবেস এর অবস্থাও কচ্ছপ গতির হয়ে যায়। কারন ডাটাবেস এর ডাটা সাইজ আগের থেকে অনেক বেশি থাকে। ডাটা খুঁজে আনতে হ-য-ব-র-ল অবস্থা যেটাকে বলে, সেটা হয়ে যায়।

রেজাল্ট যেটা হয় সেটা হল, কিছু কিছু ইউজারকে সার্ভার সার্ভকরতে পারে। আর কিছু কিছু ইউজারকে পারে না। ওয়েব অ্যাপ্লিকেশান, সার্ভার আর ডাটাবেস মিলে এমন একটা অবস্থা হয় যে সেটা হেডফোন এর তার প্যাঁচানোর মতন অবস্থায় গিয়ে দাঁড়ায়।

তো আমাদের সিস্টেমে এই ইউজার বাড়ার সাথে সাথে যদি তাল মিলিয়ে চলতে চায়, তাহলে কিছু ব্যবস্থা নিতে হবে। এই ব্যবস্থাকেই “(Scalability) স্ক্যালাবিলিটি” বলে।

আসেন তাহলে আমরা কিভাবে একটা সিস্টেমকে (Scalabale) স্ক্যালেবল করতে পারি তার ব্যাসিক একটু দেখে নেই।

২ ধরনের স্ক্যালাবিলিটি আছে। ভার্টিক্যাল(Vertical) এবং হরাইজন্টাল(Horizontal)। ভার্টিক্যাল হলে আমাদের মেশিন থাকবে একটি-ই, কিন্তু প্রয়োজন অনুযায়ী আমরা মেমরি এবং সিপিইউ স্পীড যোগ করে নিবো। তাহলে তো আগের থেকে ফাস্টার হওয়ার কথা, এবং সেটা হয়ও। কিন্তু যদি ডাটা সাইজ আরও বাড়তে থাকে, তাহলে এই পথে হাঁটা ঠিক হবে না। কারণ কতই বা মেমরি বাড়াবো, আর কতই বা সিপিইউ স্পীড বাড়াবো।

তাহলে বাকি থাকল হরাইজন্টাল স্কেলিং, যেখানে কিনা আমরা আরও মেশিন যোগ করব। ভার্টিক্যাল এর মতন এইখানে মেমরি, সিপিইউ ডিরেক্ট বাড়াবো না। এখানে আমাদের প্রয়োজন অনুযায়ী নতুন নতুন মেশিন যোগ করতে পারব। তারা ইন্টার-কানেক্টেড থাকবে নেটওয়ার্ক এর মাধ্যমে।ইউজার পয়েন্ট অফ ভিউ থেকে মনে হবে একটাই মাত্র মেশিন, কিন্তু আসলে ব্যাক এ তো সেই অবস্থা।

আমি আসলে এই হরাইজন্টাল স্কেলিং নিয়েই মূলত কথা বলব, কিভাবে এই ধারণাকে বিভিন্ন লেয়ার-এ এপ্লাই করা যায়।

1. আমরা ওয়েব অ্যাপ্লিকেশান/ওয়েব সার্ভিস এর হরাইজন্টাল স্কেলিং করতে পারি। এটার মানে হল আমাদের একই অ্যাপ্লিকেশান এর ক্লোন করা এবং বিভিন্ন মেশিন-এ ডেপ্লয় দেওয়া, যাকে আমরা ক্লাস্টারিং বলি। কিন্তু রিকোয়েস্ট কার কাছে যাবে, এটা নিয়ে তো একটা ঝামেলা। এটা করবে লোড ব্যাল্যান্সার, যে কিনা রিকোয়েস্ট বিভিন্ন সার্ভার এর কাছে দিবে। এটা সে বিভিন্ন অ্যালগোরিদম (Round Robin, Least Connection ইত্যাদি) ব্যবহার করে নির্ধারণ করতে পারে যে কোন সার্ভার এর কাছে দিবে। তাহলে যেটা হল যে রিকোয়েস্ট আর সার্ভার এর কাছে এসে বসে থাকল না। যেই টোটাল লোড আসবে সেটা বিভিন্ন মেশিন এর মধ্যে ভাগ হয়ে গেল।“অনেকটা দশে মিলে করি কাজ” এর মতন। তবে একটা বিষয় খেয়াল রাখতে হবে সেটা হল, এই ক্ষেত্রে ইউজারের সেশন কিভাবে রাখা হবে, এক সার্ভার এর তৈরি হওয়া সেশন অন্য সার্ভার কিভাবে পাবে ইত্যাদি। এখানে দুইটা সল্যুশন মাথায় আছে, সেটা হল সেশন রেপ্লিকেশন অথবা স্টিকি সেশন ব্যবহার করা।

  • স্টিকি সেশন ব্যবহার করার মানে হল প্রথমবার যেই সার্ভার আমার রিকোয়েস্ট সার্ভ করবে পরবর্তী সব রিকোয়েস্টগুলোও সেই একই সার্ভার হ্যান্ডেল করবে। অন্য সার্ভার এর কাছে যাবে না। সাধারণত এই ক্ষেত্রে সেশন আইডি অথবা কুকি এর সাথে সার্ভার এর আইডি ডট (.) দিয়ে জোড়া লাগানো থাকে, যাতে করে লোড ব্যাল্যান্সার রিকোয়েস্ট দেখা মাত্রই বুঝতে পারে এই রিকোয়েস্টটা আগে কে হ্যান্ডেল করেছিল।
  • সেশন রেপ্লিকেশন হল একটা সার্ভারে যদি সেশন তৈরি হয়, তাহলে ইন্টার কানেক্টেড সব সার্ভারে সেই সেশন এর রেপ্লিকা কপি হয়ে যাবে। এই ক্ষেত্রে র‍্যাডিস(Redis) ডাটাস্টোর, এক্সটারনাল কোন ডাটাবেস যেমন মেমক্যাসড(Memcached), রিমোট ইজেবি(Remote EJB) ইত্যাদি ব্যবহার করা যেতে পারে। মোট কথা হল সব সার্ভার সেশন এর ব্যাপারে সিঙ্ক(Sync) থাকবে।

তো হয়ে গেল ওয়েব অ্যাপ্লিকেশান এর হরাইজন্টাল স্কেলিং। এইভাবে কিছুদিন চলার পরে নতুন প্রব্লেম এর উদয় হবে। সেটা হল ডাটাবেস অনেক স্লো হয়ে গেছে। যদিও আমরা অ্যাপ্লিকেশান অথবা সার্ভিস লেয়ারে স্কেলিং করে ফেলেছি, কিন্তু ডাটাবেস স্লো হওয়ার কারনে আমাদের পুরা অ্যাপ্লিকেশানটাই স্লো মনে হচ্ছে। তাহলে উপায় ………??

2. ডাটাবেসকেও একই ভাবে স্কেলিং করতে হবে অর্থাৎ ডাটাবেস বিভিন্ন মেশিনে ডেপ্লয় করা থাকবে। তবে ডাটাবেস এর এই স্কেলিংটা হয় মাস্টার-স্লেভ(Master-slave) এর মাধ্যমে। মাস্টার-স্লেভ এই সম্পর্কের মধ্যে মূলত মাস্টার সার্ভারে যেটা হয় সেটা হল রাইট(Write) অপারেশান, অর্থাৎ Create-Update-Delete গুলো। আর স্লেভ-এ রিড(Read) অপারেশান। যেহেতু রাইট অপারেশান রিসোর্স ইনটেনসিভ (মানে হল বেশি রিসোর্স ব্যবহার করে), তাই এই মেশিনে বেশি র‍্যাম এবং পাওয়ারফুল সিপিইউ দেওয়া উচিৎ।

ব্যস হয়ে গেল ডাটাবেস সার্ভার এর ক্লাস্টারিং। কিন্তু কিছু দিন পরে দেখা গেল এতেও কাজ হচ্ছে না। ডাটাবেস আবারও স্লো। এই ক্ষেত্রে আসলে কিছু এক্সট্রা ব্যবস্থা নেওয়া যেতে পারে।

  • আমরা ডাটাবেসকে সারডিং(Sharding) করতে পারি। এটা হল এমন একটা প্রসেস, যেখানে কিনা ডাটাগুলোকে বিভিন্ন সার্ভারে ভাগ করে রাখা হয় এবং টপ-এ একটা ইনডেক্স থাকে। যেখান থেকে কিনা বুঝা যাবে অথবা যার কাছে ইনফরমেশন থাকবে কোন মেশিনে গেলে আমি ডাটা-টা খুজে পাব।
  • এছাড়াও আমরা ডাটাবেস এর ডিনরমালাইজেশন(De-normalization) করতে পারি। এক্ষেত্রে রিড অপারেশান ফাস্টার হবে আগের থেকে।কারণ একটা টেবিল থেকে এক বা একাধিক সারি(Row) তুলে আনা(Fetch)র চাইতে কয়েকটা টেবিলের রিলেশন ধরে সেখান থেকে কুয়েরি(Query) করে ডাটা আনা তুলনামুলকভাবে বেশ স্লো।তো এই ক্ষেত্রে আমরা নো-সিক্যুএলের (NoSQL) এর দিকে চলে যেতে পারি(যদি না বিজনেস লজিক অনুযায়ী আমার ডাটা অনেক বেশী রিলেশনাল হয়), অথবা ইনডেক্সড ভিউ (MSSQL)/ম্যাটেরিয়ালাইজড ভিউ (Postgres অথবা Oracle) ব্যবহার করতে পারি। যদি জয়েন করতেই হয় তাহলে সেটা ডাটাবেস লেভেলে না করে অ্যাপ্লিকেশান লেভেলেও করে দেখা যেতে পারে (এক্ষেত্রে লক্ষ্যনীয় যে ডাটাবেজ না এপ্লিকেশন, কোন লেভেলে জয়েন করলে সেটা পারফরমেন্সের দিক থেকে ভালো হয় তাঁর উপর ভিত্তি করে সিদ্ধান্ত নিতে হবে)।

অনেক কিছুই তো করা হল ক্লাস্টারিং নিয়ে। কিন্তু তারপরেও না, ডাটাবেসটাকে একটু স্লো-ই লাগছে।

3. এই স্টেপ-এ আমাদের চলে যেতে হবে ক্যাশিং(Caching) এর দিকে এবং সেটা হতে হবে ইন-মেমরি ক্যাশিং (In-memory Caching)যেমন মেম-ক্যাসড(Memcached) অথবা র‍্যাডিস(Redis)ক্যাশ (কারণ ইন-মেমোরী ক্যাশে যেহেতু ডাটা মূলত মেমোরীতে স্টোর হবে, সেক্ষেত্রে Read-Write অপারেশন অনেক ফাস্টার হবে)। এক্ষেত্রে যেটা হয় যে রিড করার সময় আগে ক্যাশ থেকে রিড করার চেষ্টা করব। যদি না পাই, যেটাকে টেকনিক্যালি বলে ক্যাশ মিস(Cache Miss), তাহলেই একমাত্র ডাটাবেস-এ হিট করব। এবং প্রাপ্ত ডাটা আবারও ক্যাশ মেমরিতে রাখব ভবিষ্যৎ রিকোয়েস্ট সার্ভকরার জন্য। তবে এই ডাটা ক্যাশিং আবার দুইভাবে করা যেতে পারে।

  • ডাটাবেস কুইরি ক্যাসিং(Database Query Caching), যেখানে কিনা রেজাল্ট কে সেভ করে রাখা হয় কুইরি এর হ্যাশ ভ্যালুর সাপেক্ষে। এটার লিমিটেশন হল, যদি কিনা টেবিলে একটা কলাম অ্যাড হয়, তাহলে আমাকে সবগুলো ক্যাসড কুইরি ডিলিট করতে হবে যেগুলো কিনা ওই কুয়েরি এর সাথে সম্পৃক্ত।
  • ক্যাসড অবজেক্ট(Cached Object), যেখানে কিনা অবজেক্ট ক্যাশ করে রাখা হবে। আপডেট ডাটা পেলে আবার ক্যাশ-এ আপডেট করে দিতে হবে।

হাপায় গেছি। কত ঝক্কি রে বাবা।

কিন্তু এর পরেও যদি স্লো হয়ে যায় ??

ইয়ে মানে, হতেও পারে। তখন কি উপায়?

4. এর পরেও স্লো হলে অ্যাসিঙ্ক(Async)এর দিকে চলে যেতে হবে যেখানে কিনা কতগুলো ওয়ার্কার থাকবে, যারা তাদের দেওয়া কাজ গুলো প্রসেস করবে, ফ্রন্ট এন্ড থেকে চেক করতে থাকবে কাজটা শেষ হয়েছে কিনা। শেষ হয়ে গেলে ইউজারকে প্রাপ্ত ডাটা দেখাবে। আসলে যেই কাজগুলো করতে টাইম বেশি লাগবে সেগুলোকে Asynchronous অপারেশান দিয়েই কাজ সারতে হবে।

5. এছাড়াও কিছু ক্ষেত্রে পুরো সিস্টেমটাকে মনোলিথিক না রেখে মাইক্রোসার্ভিস আর্কিটেকচারের মাধ্যমে আলাদা আলাদা সার্ভিসে ভাগ করে নিয়ে প্রত্যেকটা সার্ভিসকে আলাদা আলাদাভাবে অপটিমাইজ করা যেতে পারে। তাঁর সাথে সার্ভিসগুলোর মধ্যে ইভেন্ট ড্রিভেন কমিউনিকেশনের ব্যবহারও ফলপ্রসূ হতে পারে।

 

এরকম আরো বহুবিধও পদ্ধতি আছে যেগুলো বড় বড় জায়ান্ট কোম্পানিগুলো তাঁদের সার্ভিস ডেভেলপ করতে ব্যবহার করে। সুযোগ থাকলে সেগুলো অবলম্বন করা যেতে পারে।

তবে মোদ্দাকথা হলো, আপনি যদি সত্যিই আপনার এপ্লিকেশন বা সার্ভিসকে Highly Scalable করতে চান বা High Traffic হ্যান্ডেল করতে চান, তাহলে আপনাকে অবশ্যই প্রোফাইলিং(Profiling) এবং পারফরমেন্স মেজার (Performance Measure) করতে জানতে হবে। এবং এর মাধ্যমে আপনাকে খুঁজে বের করতে হবে আপনার এপ্লিকেশন বা সার্ভিসের বটলনেক(bottleneck) কোথায়, কোন জায়গায় সার্ভিস কাঙ্খিত পারফরমেন্স দিচ্ছে না, তারপর সেটাকে কীভাবে ইম্প্রুভ করা যায় সেটা চিন্তা করতে হবে। যেমন এমনও হতে পারে যে আপনি ব্যাকএন্ডে একেবারে তুলকালাম করে রেখেছেন অথচ ফ্রন্টএন্ডে আপনার Buggy, inefficient জাভাস্ক্রিপ্ট কোড বা আনঅপ্টিমাইজড ইমেজের জন্য পেইজ লোড হতে অনেক সময় লাগছে। তাহলে তো কোনো লাভ হলো না। অর্থাৎ আপনাকে আগে রোগ ডায়াগনোসিস করতে হবে তারপরে তাঁর ঔষধ। আপনি হুট করে একেবারে বিরাট লেভেলের আর্কিটেকচার ডেভেলপ করে অনেক অনেক সার্ভার, লোড ব্যালেন্সার, ক্যাশ মেকানিজম ব্যবহার করে নিশ্চিন্ত হয়ে বসে থাকতে পারবেন না যে ‘আমার সার্ভিস তো স্ক্যালেবল হয়ে গেছে, আমাকে আর ঠেকায় কে’। এটা একটা কন্টিনিউয়াস প্রসেস। যখন আপনার সার্ভিসের ১০০ জনও ইউজার নেই, তখন নিশ্চয়ই আপনি রাতের ঘুম হারাম করে ১০০০০০ ইউজারের জন্য আর্কিটেকচার ডেভেলপ করতে নামবেন না, তাই না? অবশ্য আপনি যদি দিব্যজ্ঞানে জানেন যে, আগামীকাল বা আগামী সপ্তাহে আপনার সার্ভিসে অবশ্যই অনেক অনেক ইউজার আসবে, তাহলে ভিন্ন কথা।

Toufiq Mahmud

Leave a Reply

Your email address will not be published.