شمارش درخواست پیش از تصمیم
یک پراکسی میتواند به درخواست جاری نگاه کند و بر اساس مسیر یا سرآیند تصمیم بگیرد. اما پرسش «این مبدأ در چند ثانیه گذشته چند درخواست فرستاده است؟» به حافظهای میان درخواستها نیاز دارد. Stick Table در HAProxy چنین امکانی فراهم میکند: دادهای با یک کلید نگه میدارد و شمارندهها را به آن پیوند میدهد. جدول میتواند برای مشاهده نرخ، محدودسازی یا تصمیمهای دیگر استفاده شود. ارزش آن فقط نوشتن یک شرط deny نیست؛ باید روشن باشد چه چیزی شمرده میشود، کلید واقعاً معرف چه کسی است و رد کردن درخواست چه اثری بر سرویس دارد.
فرض کنید یک رابط عمومی در زمان اوج مصرف کند میشود. افزودن محدودیت بر اساس نشانی مبدأ ممکن است بار را کم کند، اما اگر صدها کاربر یک سازمان پشت یک NAT باشند، همه آنها در یک سبد قرار میگیرند. در مقابل مهاجمی که مبدأهای زیادی دارد ممکن است از آستانه هر سبد عبور نکند. پس محدودیت نرخ یک کنترل وابسته به مدل ترافیک است. پیش از فعالسازی باید معلوم شود هدف حفاظت از ظرفیت، مقابله با تلاش ورود مکرر یا تضمین سهم منصفانه است؛ هر هدف میتواند کلید و پنجره متفاوتی نیاز داشته باشد.
اجزای یک جدول
تعریف stick-table نوع کلید، ظرفیت، زمان انقضا و داده ذخیرهشده را مشخص میکند. نوع ip در نمونه رسمی برای نشانی IPv4 به کار میرود. size سقف رکوردهای جدول را تعیین میکند و با تعداد درخواست مجاز یکی نیست. expire عمر رکورد بدون دسترسی را کنترل میکند؛ هر مراجعه میتواند آن را تازه کند. بخش store نیز مشخص میکند چه شمارنده یا دادهای کنار کلید نگه داشته شود. بنابراین ظرف جدول، عمر داده و معنای سنجه سه تصمیم جدا هستند و نباید با یک عدد واحد جایگزین شوند.
برای مثال http_req_rate با یک بازه زمانی، نرخ درخواست HTTP را در آن بازه نگه میدارد. conn_rate درباره نرخ اتصال است و bytes_in_rate حجم ورودی را دنبال میکند. تفاوت اتصال و درخواست در HTTP اهمیت دارد، زیرا یک اتصال میتواند چندین درخواست حمل کند. محدود کردن تعداد اتصال لزوماً بار پردازش هر درخواست را محدود نمیکند. همچنین یک درخواست بسیار پرهزینه ممکن است از صد درخواست ساده بار بیشتری بسازد. جدول ابزار اندازهگیری است؛ انتخاب سنجه باید به منبعی مربوط باشد که در سرویس واقعاً کمیاب شده است.
نمونه آموزشی و ترتیب قواعد
نمونه زیر فقط بخشی از پیکربندی یک frontend آزمایشی است. باید backend، ثبت گزارش و سایر تنظیمات لازم در پیکربندی کامل وجود داشته باشند. آستانه ده درخواست در پنجره دهثانیهای عمداً کوچک است تا رفتار آن در آزمایش دیده شود و توصیه عمومی برای محیط عملیاتی محسوب نمیشود. قبل از هر بارگذاری، صحت پیکربندی کامل با همان نسخه HAProxy بررسی شود. عدد و نوع کلید باید بر اساس ترافیک واقعی و مستندات نسخه نصبشده انتخاب شوند.
frontend limited_http
bind :8080
mode http
stick-table type ip size 100k expire 30s store http_req_rate(10s)
http-request track-sc0 src
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 10 }
default_backend application
دستور track-sc0 ارتباط درخواست با رکورد جدول را برقرار میکند. در این مثال src با نوع کلید جدول سازگار است و شمارنده وابسته به آن بهروز میشود. سپس شرط نرخ از همان جایگاه رهگیری خوانده میشود. اگر شرط پیش از رهگیری قرار گیرد یا شماره جایگاه اشتباه باشد، منطق مورد انتظار ساخته نمیشود. ترتیب قواعد بخشی از معنا است و فقط ظاهر فایل نیست. در بازبینی باید بتوان مسیر یک درخواست را از انتخاب کلید تا بهروزرسانی شمارنده و تصمیم نهایی قدم به قدم توضیح داد.
پاسخ ۴۲۹ به کلاینت میگوید درخواست بیش از حد مجاز بوده، اما استفاده از این کد به تنهایی رفتار درست کلاینت را تضمین نمیکند. اگر برنامه بدون وقفه تلاش دوباره کند، ترافیک اضافی تولید میشود. راهبرد تلاش دوباره باید فاصله و پراکندگی مناسب داشته باشد و در سمت برنامه مستند شود. همچنین رد کردن عملیات خواندن ساده با رد کردن مرحله نهایی یک تراکنش تجربه یکسانی ندارد. مسیرهای حساس باید با مالک برنامه بررسی شوند تا کنترل ظرفیت به از دست رفتن عملیات مجاز منجر نشود.
کلید مبدأ پشت چند پراکسی
وقتی HAProxy مستقیماً اتصال کاربر را دریافت نمیکند، src ممکن است نشانی پراکسی قبلی باشد. در این حالت همه کاربران آن پراکسی در یک رکورد جمع میشوند. خواندن یک سرآیند ارسالی کاربر برای حل فوری این مشکل خطرناک است، زیرا فرستنده میتواند مقدار دلخواه بگذارد. ابتدا زنجیره اعتماد باید مشخص شود: کدام پراکسی مجاز است هویت مبدأ را اعلام کند، آیا دسترسی مستقیم به HAProxy بسته است و کدام لایه سرآیندهای جعلی ورودی را پاک میکند؟ بدون این قرارداد، شمارنده دقیق روی هویت نادرست قرار میگیرد.
برای سرویس احراز هویتشده ممکن است شناسه حساب یا کلید مصرفکننده مناسبتر از IP باشد، ولی این انتخاب هم هزینه دارد. باید اعتبار آن شناسه پیش از استفاده روشن شود و طول و فضای کلید محدود باشد. ورودی کنترلنشده میتواند تعداد کلیدها را زیاد کند و ظرفیت جدول را مصرف کند. از سوی دیگر درج اطلاعات شخصی خام در کلیدهای قابل مشاهده از رابط مدیریت میتواند دامنه دسترسی به داده را گسترش دهد. انتخاب کلید باید با مدل اعتماد، کاردینالیتی و نیاز واقعی پایش هماهنگ شود.
پنجره نرخ، انقضا و برداشت اشتباه
پارامتر پنجره در http_req_rate و زمان expire یک مفهوم نیستند. پنجره به سنجه نرخ مربوط است و expire به عمر رکورد در جدول. اگر رکورد زودتر از نیاز تحلیلی حذف شود، سابقه مورد انتظار باقی نمیماند؛ اگر بسیار دیر بماند، کلیدهای غیرفعال حافظه اشغال میکنند. برای نرخ دهثانیهای، عمر رکورد باید آگاهانه با رفتار مورد انتظار هماهنگ شود. افزایش expire نیز به خودی خود محدودیت را به سهمیه روزانه یا یک شمارنده دائمی تبدیل نمیکند.
این کنترل را نباید بدون بررسی معادل یک سطل توکن دقیق یا یک سامانه سهمیه مالی دانست. ترتیب ورود، پنجره سنجه، زمان انقضا و توزیع درخواست میان چند گره روی نتیجه اثر میگذارند. اگر قرارداد تجاری میگوید هر مشتری دقیقاً تعداد معینی عملیات در روز دارد، معمولاً به ثبت معتبر و مشترک در لایه دیگری نیاز است. Stick Table برای تصمیم سریع روی مسیر ترافیک مناسب است؛ تضمین حسابداری جهانی نیازمند طراحی مستقل است. این مرز از ادعاهای بیش از توان کنترل جلوگیری میکند.
ظرفیت حافظه و تعداد کلیدها
ظرفیت جدول را باید با تعداد مبدأهای فعال در مدت نگهداری برآورد کرد. ده هزار درخواست از یک کلید با ده هزار درخواست از ده هزار کلید از نظر رشد جدول یکسان نیست. افزوده شدن شمارندههای بیشتر نیز اندازه هر رکورد را تغییر میدهد. بنابراین نمیتوان فقط از روی نرخ درخواست اندازه حافظه را تعیین کرد. در آزمایش بار، تعداد کلیدهای یکتا و الگوی بازگشت آنها باید شبیه محیط واقعی باشد؛ یک ابزار بارساز با یک مبدأ، فشار کاردینالیتی را نشان نمیدهد.
پر شدن جدول و سیاست نگهداری یا حذف رکورد باید در نسخه و تنظیمات انتخابی بررسی شود. نباید فرض کرد که هر درخواست تازه همیشه رکورد کامل میگیرد. شاخصهای مصرف حافظه، تعداد رکورد و نرخ رد شدن باید کنار هم دیده شوند. اگر زیر بار، رکوردها به سرعت جابهجا شوند، اثر محدودیت ممکن است با آزمون کمبار تفاوت داشته باشد. هدف ظرفیتسنجی فقط جلوگیری از توقف فرایند نیست؛ حفظ معنای سیاست در شرایط اوج نیز بخشی از پذیرش عملیاتی است.
محدودیت محلی در معماری چندگرهی
اگر دو HAProxy مستقل درخواستهای یک کاربر را بپذیرند، بدون طراحی اشتراک وضعیت هر کدام برداشت محلی خود را دارد. در نتیجه عددی که روی یک گره آستانه محسوب میشود الزاماً سقف کل سامانه نیست. تغییر مسیر کاربر پس از خرابی یا توزیع متناوب ترافیک میتواند سهم دیدهشده هر گره را تغییر دهد. پیش از محاسبه نرخ باید واحد تصمیم روشن باشد: حفاظت از هر گره، حفاظت از backend مشترک یا سهمیه سراسری مشتری. این سه هدف راهحل کاملاً یکسان ندارند.
قابلیت peers برای هماهنگی داده جدول در سناریوهای پشتیبانیشده وجود دارد، اما آن را نباید به طور خودکار یک پایگاه داده با سازگاری تراکنشی جهانی تصور کرد. نسخهها، تعریف جدول، اتصال همتاها و رفتار هنگام قطع ارتباط باید بررسی شوند. در تست خرابی، یک گره را از شبکه همتاسازی جدا کنید و اثر بر تصمیمها را ببینید. حتی با اشتراک وضعیت، انتخاب آستانه باید تأخیر و شرایط شکست را در نظر بگیرد. یک کنترل حفاظتی عملی میتواند مفید باشد بدون اینکه ادعای سهمیه دقیق جهانی داشته باشد.
از مشاهده به اعمال سیاست
فعال کردن رد درخواست بدون دیدن توزیع ترافیک میتواند کاربران واقعی را غافلگیر کند. مرحله نخست میتواند فقط رهگیری و مشاهده سنجه باشد. نرخهای معمول، جهش هنگام باز شدن صفحه، رفتار برنامه تلفن همراه و درخواستهای خودکار داخلی را جمع کنید. سپس آستانهای انتخاب کنید که با ظرفیت backend و تجربه مجاز سازگار باشد. اگر صفحه برای یک بازدید دهها درخواست همزمان میفرستد، آستانهای که فقط بر اساس شمار بازدید انتخاب شده ممکن است بسیار پایین باشد.
استثناها نیز باید محدود و قابل توضیح باشند. کنار گذاشتن همه شبکه داخلی از کنترل ممکن است حساب یا سرویس معیوب داخلی را بیمهار کند. برای health check، مسیر مدیریتی یا مشتری شناختهشده میتوان سیاست مناسب داشت، اما باید دلیل، مالک و زمان بازبینی آن ثبت شود. بهتر است ردها بر اساس مسیر و گروه مصرفکننده تحلیل شوند تا مشخص شود کاهش بار از مهار رفتار نامطلوب آمده یا از قطع کاربران مجاز. تعداد پاسخ ۴۲۹ به تنهایی شاخص موفقیت نیست.
عیبیابی و آزمون پذیرش
در محیط آزمایش، ابتدا چند درخواست پراکنده از یک مبدأ بفرستید، سپس یک جهش کنترلشده ایجاد کنید و بعد به مدت کافی صبر کنید. باید افزایش شمارنده، آغاز رد و بازگشت امکان دسترسی با انتظار هماهنگ باشد. آزمایش را با دو کلید مستقل تکرار کنید تا جداسازی رکوردها روشن شود. برای سامانه پشت پراکسی، یک تست مستقیم و یک تست از مسیر واقعی نشان میدهد کلید انتخابی همان هویت مورد نظر است یا به نشانی واسطه فروکاسته شده است.
در رخداد عملیاتی، پیکربندی فعال، نسخه HAProxy، وضعیت جدول و نمونه گزارش درخواستها را با زمان مشترک جمع کنید. ابتدا مشخص کنید کدام قاعده رد را ایجاد کرده؛ هر پاسخ خطا الزاماً از Stick Table نیست. سپس کلید، شماره رهگیری، پنجره و مسیر واقعی درخواست بررسی شوند. داده رابط مدیریتی باید فقط در اختیار افراد مجاز باشد، زیرا میتواند نشانیها و الگوی مصرف را نشان دهد. تغییر آستانه نیز باید با مسیر بازگشت روشن انجام شود تا کاهش فشار به قیمت خطای طولانی برای کاربران تمام نشود.
پذیرش نهایی زمانی است که هم حفاظت از backend و هم دسترسی کاربران مجاز بررسی شده باشند. زمان پاسخ، نرخ خطا، تعداد عملیات موفق و هزینه حافظه را در بار مشابه مقایسه کنید. اگر ردها زیاد شدهاند ولی ظرفیت مؤثر برنامه بهتر نشده، ممکن است سنجه اشتباه یا مسیر پرهزینه دیگری انتخاب شده باشد. Stick Table زمانی بیشترین فایده را دارد که مدل هویت و بار را به یک تصمیم سریع و قابل مشاهده تبدیل کند؛ کیفیت سیاست از شناخت برنامه میآید و با صرف افزودن یک دستور deny کامل نمیشود.