Honeybadger-এ আমরা আমাদের প্রসেসিং পাইপলাইনে সাইডকিউইকে ব্যাপকভাবে নির্ভর করি। আমরা যা করি প্রায় সব কিছু একটি কিউর থেকেই गुजর করে। ফলস্বরূপ, আমি চাই আমরা সাইডকিউইক ভালোভাবে চালাচ্ছি। আমাদের সম্প্রতি EC2-এ মুভ করার সাথে, আমরা একটি স্থির লং-লিভড সার্ভার সেট থেকে একটিEver-changing ইনস্ট্যান্স সেটে চলে এসেছি যা আমাদের জব রান করে। এটি আমাকে সাইডকিউইক কীভাবে বুট টাইমে শুরু হয় তা পুনর্বিবেচনা করতে বাধ্য করল, কারণ এটি এখন আগের চেয়ে অনেক বেশি গুরুত্বপূর্ণ।
গতকালে আমরা গড (god) ব্যবহার করতাম সকল ওয়ার্কার প্রসেস স্পিন আপ করার জন্য, যেহেতু আমরা সেগুলো মনিটর করতে চেয়েছি এবং যেগুলো খুব বেশি মেমরি ব্যবহার করত সেগুলো টার্মিনেট করতে চেয়েছি। আমাদের গড কনফিগ আমাদের যে সার্ভারগুলোতে ওয়ার্কার রান করত 그곳ার জন্য হ্যান্ড-টিউন্ড ছিল। দুর্ভাগ্যক্রমে, আমি দেখলাম যে আমাদের পুরনো গড কনফিগ নতুন ইনস্ট্যান্সে systemd ব্যবহার করে বুট করলে, কনফিগারেশনে নির্দিষ্টতার চেয়ে বেশি ওয়ার্কার চালু হচ্ছে। এতে ইনস্ট্যান্সগুলোর ওপর মেমরি প্রেশার তৈরি হত, যা খারাপ খবর। একটু ফিডল করার পর, এবং বুঝতে পারলাম যে আমরা এর ফাংশনালিটির অধিকাংশই ব্যবহার করছি না, আমি تصمیم নিয়েছি গড ব্যবহার বন্ধ করে প্রসেস ম্যানেজ করার জন্য।
একটি সিম্পল কমান্ড একাধিক সাইডকিউইক প্রসেস রান করতে
আমি যেটি আসলে চেয়েছিলাম সেটি ছিল একটি স্ক্রিপ্ট যা আমি systemd সার্ভিস হিসেবে রান করতে পারতাম যা প্রতি CPU কোরের জন্য একটি সাইডকিউইক প্রসেস স্পন করবে এবং যেগুলো খুব বেশি মেমরি ব্যবহার করত সেগুলো রিস্টার্ট করবে। স্ক্রিপ্টটি বিভিন্ন আকারের EC2 ইনস্ট্যান্সের সাথে কাজ করতে পারত, কারণ কোরের সংখ্যা এবং RAM এর পরিমাণ পরিবর্তন হতে পারে আমি বিভিন্ন ইনস্ট্যান্স সাইজ ট্রাই করতাম আমাদের ওয়ার্কলোডের জন্য কী সেরা কাজ করে তা দেখতে। যেহেতু আমি এমন কোনো স্ক্রিপ্ট খুঁজে পাইনি যা সঠিকভাবে এটি করবে, আমি নিজে একটা লিখলাম:
বিলবেচনা, সেই স্ক্রিপ্টে কিছু বরো করা কোড আছে। :) process_count মেথডের কোড সম্ভবত Stack Overflow থেকে (আমি বছরের পর বছর আমাদের ইউনিকোর্ন কনফিগারেশনে এটি ব্যবহার করছি) এবং fork_child মেথড মূলত সাইডকিউইক জেমের sidekiq বাইন।
এই স্ক্রিপ্ট উপস্থিত CPU কোরের সংখ্যা অনুযায়ী চাইল্ড প্রসেস স্পন করে, প্রতিটি চাইল্ড প্রসেস সেমান হয় যেন আপনি সরাসরি sidekiq কমান্ড রান করতেন। ফলস্বরূপ, যেসব কমান্ড-লাইন অপশন আপনি এই স্ক্রিপ্টে পাস করবেন সেগুলো পাস হবে (এবং পার্স হবে) সাইডকিউইক CLI কোডে। অন্য কথায়, আপনি এই স্ক্রিপ্টে যেকোনো অপশন পাস করতে পারেন যা আপনি সরাসরি sidekiq রান করার সময় পাস করতে পারেন, যদিও কিছু অপশন (যেমন pid ফাইল অপশন) ব্যবহার করা জিনিসপত্র নয়। একটি থ্রেডও স্পন করা হয় যেটি পেরিওডিক্যালি প্রতিটি চাইল্ড প্রসেসের মেমরি ব্যবহার চেক করে। যদি কোনো চাইল্ড প্রসেস থ্রেশহোল্ড পার করে, তবে এটি কিল করা হয় এবং এটিকে রিপ্লেস করার জন্য একটি নতুন প্রসেস স্পন করা হয়।
ক্লাস্টার সহ কাজ
প্রসেসের সংখ্যা ডিফল্টরূপে কোরের সংখ্যা (আপনি যদি একটি ইনস্ট্যান্স ডেডিকেট করেন সাইডকিউইক প্রসেস রান করার জন্য), কিন্তু আপনি এটি ওভাররাইড করতে পারেন SK_PROCESS_COUNT এনভায়রনমেন্ট ভেরিয়েবল সেট করে স্ক্রিপ্ট চালানোর আগে। একইভাবে, মেমরি থ্রেশহোল্ড সেট করা হয় ইনস্ট্যান্সের টোটাল RAM-এর পার্সেন্টেজ হিসেবে (প্রসেস_কাউন্ট ভ্যালুতে ১ যোগ করে কিছু RAM রিজার্ভ রাখা হয়েছে লাইন ৫৮-এ), কিন্তু আপনি যা খুশি পার্সেন্টেজ সেট করতে পারেন SK_MEMORY_PCT_LIMIT এনভায়রনমেন্ট ভেরিয়েবল দিয়ে। আমরা এই দুটি ভেরিয়েবল ব্যবহার করি সাইডকিউইক প্রসেসের সংখ্যা এবং মেমরি ব্যবহার সীমাবদ্ধ করতে যেসব ইনস্ট্যান্সে আমাদের UI পাওয়ার করে এমন রেলস অ্যাপ চলছে।
একটি বোনাস হিসেবে, এই স্ক্রিপ্ট সাইডকিউইক প্রসেস ম্যানেজ করতে যেসব সিগন্যাল সাধারণত ব্যবহৃত হয় সেগুলো ক্যাচ করে এবং সেগুলো চাইল্ড প্রসেসগুলোর কাছে পাস করে। এটি আমাদের অনুমতি দেয় pkill -f -USR1 skcluster ব্যবহার করে চাইল্ড প্রসেসগুলোর নতুন কাজ গ্রহণ বন্ধ করাতে (এটি আমাদের ডিপ্লয়মেন্ট স্ক্রিপ্টের একটি আর্লি টাস্ক), এবং আমরা pkill -f skcluster ব্যবহার করে সব কিছু টার্মিনেট করতে পারি।
systemd কনফিগার করা
systemd সার্ভিস ডেফিনিশন স্ট্রেইটফরওয়ার্ড:
যেহেতু আমরা প্রতিটি ইনস্ট্যান্সে pgbouncer ব্যবহার করি পোস্টগ্রেসের সাথে কানেকশন প্রক্সি করার জন্য, আমরা নিশ্চিত করি যে pgbouncer সার্ভিস চলছে সাইডকিউইক প্রসেসগুলো বুট হওয়ার আগে। যদি আমরা একই ইনস্ট্যান্সে রেডিস চালাতাম, তবে আমরা Requires এবং After লাইনে redis-server.serviceও যোগ করতাম। EnvironmentFile-এ - প্রিফিক্স ফাইলনেমের সাথে ব্যবহার করা হয়েছে systemd-কে বলতে যে ফাইল না থাকলেও চলে। এটি আমাদের সে ফাইল বাদ দিতে দেয় যখন আমরা ডিফল্ট প্রসেস কাউন্ট এবং মেমরি লিমিটের সাথে যেতে চাই। আমরা --require অপশন ব্যবহার করি সাইডকিউইকে জানাতে যে আমাদের রেলস অ্যাপ্লিকেশনের কনফিগারেশন এবং ইনিশিয়ালাইজার লোড করতে কোথায় যেতে হবে। যেহেতু skcluster স্ক্রিপ্ট SIGTERM ক্যাচ করে, আমরা systemctl restart skcluster.service ব্যবহার করে সকল ওয়ার্কার রিস্টার্ট করতে পারি (এটি আমাদের ডিপ্লয়মেন্ট স্ক্রিপ্টের একটি লেট টাস্ক)।
আমরা এই স্ক্রিপ্ট কিছুকাল ধরে ব্যবহার করছি, এবং এটি চ্যাম্পের মত কাজ করেছে। আর বুট টাইমে çok বেশি প্রসেস স্পন হওয়ার সমস্যা নেই, আর আমাদের মনিটরিং থেকে মেমরি ব্যবহার সতর্কতা নেই, এবং আমরা যেকোনো টাইপের EC2 ইনস্ট্যান্স লঞ্চ করতে পারি। Hassle-free ops হলো আমার পছন্দের ops। :)