درگاههای متمرکزکننده VPN و سرورهای مسیریابی امن در مقیاس سازمانی همواره تحت فشارهای سنگین تخصیص حافظه رم قرار دارند. هنگام پردازش همزمان دهها هزار تونل رمزنگاری شده با پهنای باند تجمیعی ۴۰ تا ۱۰۰ گیگابیت بر ثانیه بر پایه ترافیک مختلط UDP و TCP، زیرسیستم شبکه هسته لینوکس به صورت پیوسته بافرهای سوکت (sk_buff)، جداول وضعیت اتصال و صفهای رمزنگاری را ایجاد و آزاد میکند. هنگام وقوع جهشهای ناگهانی ترافیک در ظرفیت کامل شبکه، کاهش سریع رم فیزیکی در دسترس، هسته سیستمعامل را ناچار به آغاز فرآیند بازیافت صفحات حافظه میکند.
برای بیش از دو دهه، هسته لینوکس بر الگوریتم دو فهرستی سنتی LRU یعنی فهرستهای فعال و غیرفعال (Active/Inactive) متکی بود. اگرچه این معماری بر روی سرورهای کاربرد عمومی پایدار است، اما در گرههای حساس به تاخیر شبکه، جهشهای مخربی در شاخص تاخیر نهایی (tail latency) ایجاد میکند. هنگامی که میزان حافظه آزاد به پایینتر از سطح آستانه بحرانی میرسد، هسته وارد وضعیت بازیافت مستقیم (direct reclamation) میشود: رشتههای پردازشگر بستههای داده به مدت دهها یا حتی صدها میلیثانیه برای پیمایش زنجیرههای پیچیده نگاشت معکوس متوقف میشوند که این امر منجر به افت شدید بستهها و قطع ارتباطات ویدئویی و صوتی زنده میگردد.
معرفی ساختار Multi-Gen LRU (ادغام شده در هسته لینوکس ۶.۱) در کنار سیستم Pressure Stall Information (معرفی شده در لینوکس ۴.۲۰) تحولی بنیادین در مهندسی حافظه شبکه لینوکس پدید آورده است. این ترکیب با ارائه دستهبندی نسلی صفحات، پیمایش بدون قفل جداول حافظه و رصد توقفها در مقیاس میکروثانیه، تضمین میکند که مسیریابهای شبکه پرسرعت بتوانند نرخ انتقال دادهها را بدون افت ناگهانی کارایی حفظ کنند.
گلوگاههای الگوریتم سنتی دو فهرستی LRU
برای ریشهیابی افت عملکرد درگاههای شبکه در زمان بازیافت رم، باید به بررسی ساختار سنتی دو فهرستی پرداخت:
معماری سنتی دو فهرستی LRU:
[ فهرست صفحات فعال (Active) ] <--- رقابت شدید بر سر قفل کلی (zone->lru_lock) ---> [ فهرست صفحات غیرفعال (Inactive) ]
| |
پیمایش kswapd آزادسازی / سوآپ
(پیمایش سنگین rmap، مصرف بالای CPU) (توقف مستقیم رشتهها)
تقسیمبندی ساده حافظه به دو فهرست فعال و غیرفعال، چهار چالش اساسی در پردازش دادهها ایجاد میکند:
- رقابت مخرب بر سر قفل کلی: هرگونه جابهجایی یا آزادسازی صفحه در یک ناحیه رم نیازمند دریافت قفل سراسری
zone->lru_lockاست. هنگامی که دهها هسته پردازشی به طور همزمان بستهها را پردازش میکنند، رشتههای شبکه زمان زیادی را در انتظار آزادسازی این قفل هدر میدهند. - سربار پیمایش نگاشت معکوس (rmap): برای تشخیص اینکه آیا صفحهای در فهرست غیرفعال به تازگی خوانده شده یا خیر، هسته باید کل زنجیره نگاشتهای معکوس را در فضای تمام فرآیندها پیمایش کند. این پرشهای متوالی اشارهگرها، موجب اتلاف شدید حافظه کش پردازنده و افزایش مصرف CPU میشود.
- تفکیک زمانی بسیار ضعیف: صفحات تنها به عنوان فعال یا غیرفعال شناخته میشوند. هسته نمیتواند تفاوتی میان بافری که ۲ ثانیه قبل فراخوانی شده با دادهای که ۱۰ دقیقه دستنخورده مانده قائل شود. در نتیجه، جداول مسیریابی فعال ممکن است به اشتباه تخلیه شوند.
- افت بستهها بر اثر بازیافت مستقیم: زمانی که فرآیند پسزمینه
kswapdنتواند رم را با سرعت جهش بستهها آزاد کند، رشتههای شبکه مستقیما وارد عملیات همگام آزادسازی حافظه میشوند. در این شرایط، رشته پردازش شبکه ناگهان متوقف شده و موجب پر شدن صفهای ورودی و افت بستهها میشود.
معماری Multi-Gen LRU: لایهبندی نسلی و پیمایش بدون قفل
ساختار Multi-Gen LRU این تقسیمبندی نادقیق را با یک خطلوله نسلی منظم جایگزین میسازد. در این مدل، صفحات فیزیکی در نسلهای گوناگون بر اساس یک شمارنده افزایشی مرتب میشوند:
خطلوله نسلی MGLRU:
[ نسل N (تازهترین) ] ---> [ نسل N-1 ] ---> [ نسل N-2 ] ---> [ نسل N-3 (قدیمیترین) ]
^ |
|------------- ارتقای نسل هنگام فراخوانی مجدد -------------------|
v
آزادسازی منظم صفحات
(بدون توقف بستههای شبکه)
ارتقای نسلها و پیمایش بدون قفل جداول صفحات
به جای وابستگی به ساختارهای سنگین نگاشت معکوس، MGLRU از پیمایشگر جداول صفحات (page-table walker) بهره میبرد که بیتهای دسترسی سختافزاری را مستقیما از رکوردهای جدول صفحه (PTE) میخواند. این پیمایش به کمک سازوکار RCU کاملا بدون نیاز به قفلهای کلی انجام میگیرد:
- ارتقای پویای نسل: با ورود بسته داده و مراجعه به حافظه، بیت دسترسی سختافزاری فعال میشود. در بازههای بررسی دورهای، صفحات پرکاربرد به جدیدترین نسل (
max_seq) ارتقا مییابند و صفحات کمکاربرد به نسلهای قدیمیتر (min_seq) منتقل میگردند. - تخلیه دقیق صفحات غیرفعال: آزادسازی تنها بر روی صفحات حاضر در قدیمیترین نسل (
min_seq) صورت میپذیرد. از آنجا که فاصله میان نسل جدید و قدیم نشاندهنده مدت زمان واقعی عدم استفاده است، MGLRU به شکل موثری بافرهای فعال شبکه را از ترافیکهای موقت تفکیک میکند. - تعادل هوشمند کش سیستم: الگوریتم به شکلی پایدار میان حافظه نهان فایل و حافظه ناشناس توازن برقرار میکند و بدون وابستگی به تخمینهای سنتی swappiness، فضای حافظه فرآیندهای رمزنگاری را در امنیت نگه میدارد.
پایش زودهنگام فشار رم با Pressure Stall Information (PSI)
افزون بر مدیریت ساختار نسلها توسط MGLRU، مدیران شبکه به ابزاری دقیق برای آگاهی از کمبود رم پیش از وقوع افت بستهها نیازمندند. فناوری PSI این سازوکار را فراهم میکند.
شاخص PSI نسبت زمان واقعی توقف وظایف پردازشی در انتظار منابع حافظه را در دو مولفه اصلی میسنجد:
/proc/pressure/memory:
some avg10 = 0.05 avg60 = 0.02 avg300 = 0.00 total = 142083
full avg10 = 0.00 avg60 = 0.00 avg300 = 0.00 total = 0
- شاخص
some: درصد زمانی که دستکم یک رشته پردازشی به علت انتظار برای تخصیص یا بازیافت حافظه متوقف مانده، در حالی که هستههای دیگر به فعالیت خود ادامه میدهند. - شاخص
full: درصد زمانی که تمام رشتههای فعال یک هسته به طور کامل به دلیل نبود رم متوقف شدهاند. در درگاههای شبکه، ثبت هر مقداری بالاتر از صفر برایfullنشاندهنده خطر قریبالوقوع افت دادهها است.
هسته لینوکس به برنامههای سمت کاربر اجازه میدهد تا با فراخوانیهای epoll(2) یا select(2) مستقیما روی فایل /proc/pressure/memory ناظر تعیین کنند. در صورتی که زمان توقف از آستانه تعریفشده فراتر رود، هسته بلافاصله برنامه مانیتورینگ را فعال میکند.
پیکربندی عملیاتی MGLRU و PSI در درگاههای شبکه
برای فعالسازی MGLRU در توزیعهای مبتنی بر هسته لینوکس ۶.۱ یا جدیدتر، ابتدا وضعیت تنظیمات هسته را بررسی نمایید:
# بررسی پشتیبانی هسته از قابلیت MGLRU
zcat /proc/config.gz | grep CONFIG_LRU_GEN
CONFIG_LRU_GEN = y
CONFIG_LRU_GEN_ENABLED = y
تنظیم پویا از طریق Sysfs
گزینههای شتابدهنده را در مسیر /sys/kernel/mm/lru_gen تنظیم و بررسی کنید:
# شرح بیتهای پیکربندی:
# بیت 0 (1): فعالسازی MGLRU برای پیمایش جداول صفحات
# بیت 1 (2): فعالسازی پیمایشگر چندرشتهای جداول صفحات
# بیت 2 (4): فعالسازی تفکیک نسلها بر اساس هر گره NUMA
# مقدار 7 (1 + 2 + 4): فعالسازی کامل قابلیتهای شتابدهی
echo 7 > /sys/kernel/mm/lru_gen/enabled
# تعیین حداقل طول عمر برای پیرسازی نسلها (مثلا ۲۰۰۰ میلیثانیه)
# جلوگیری از افت زودهنگام نسل در هنگام جهشهای ترافیکی
echo 2000 > /sys/kernel/mm/lru_gen/min_ttl_ms
رصد ناهمگام رویدادهای PSI با پایتون
فرآیند مدیریت تونل شبکه میتواند رویدادهای فشار حافظه را به صورت آسنکرون دریافت کرده و بافرهای موقت را تنظیم کند:
import select, os
# باز کردن فایل کنترل فشار حافظه در حالت غیرمسدودکننده
psi_fd = os.open("/proc/pressure/memory", os.O_RDWR | os.O_NONBLOCK)
# ثبت رویداد: هشدار در صورت توقف بیش از ۱۵ میلیثانیه در بازه ۵۰۰ میلیثانیهای
trigger = "some 15000 500000"
os.write(psi_fd, trigger.encode("ascii"))
epoll = select.epoll()
epoll.register(psi_fd, select.POLLPRI)
print("پایش وضعیت فشردگی حافظه با PSI آغاز شد...")
try:
while True:
events = epoll.poll(timeout = 5)
for fd, event in events:
if event & select.POLLPRI:
print("[هشدار] آستانه شاخص PSI فعال شد! فشار بر حافظه رم بالا است.")
# کاهش تطبیقی بافرهای سوکت و سبکسازی دادههای وضعیت
finally:
os.close(psi_fd)
کاربرد در معماری درگاههای RiceGuard VPN
موتور هدایت ترافیک لایه ۳ شرکت VPNRice با نام RiceGuard، به طور مستقیم از قابلیتهای MGLRU و PSI در ساختار خود بهره میبرد:
- حفاظت نسلی از بافرهای شبکه: رشتههای مسیریابی RiceGuard بافرهای داده را در برشهای اختصاصی cgroup v2 همراه با تضمین حداقل حافظه با
memory.minاجرا میکنند. ساختار MGLRU اطلاعات نشستهای فعال را در نسلهای برتر نگه میدارد و مانع از افت دادهها در انتقال فایلهای پرحجم میشود. - پیشگیری فعالانه از بحران حافظه: سرویس مدیریت RiceGuard به جای انتظار برای اقدامات مخرب OOM-killer، مداوما شاخصهای PSI را دنبال میکند. هرگاه مولفه
someاز مرز ۲ درصد عبور کند، سامانه ظرفیت بافرهای دریافتی (SO_RCVBUF) را متعادل ساخته و ترافیک را به مسیرهای جانبی توزیع میکند. - حذف جهشهای تاخیر نهایی: در آزمایشهای پرفشار با پردازش ۱.۲ میلیون بسته در ثانیه بر روی ۸۰۰۰ تونل همزمان، پیادهسازی MGLRU توانست نوسان تاخیر در صدک ۹۹.۹ را از ۴۸.۲ میلیثانیه به تنها ۱.۴ میلیثانیه در مقایسه با سیستمهای سنتی کاهش دهد.
پرسشهای متداول
آیا به کارگیری MGLRU بار پردازنده مسیریاب را افزایش میدهد؟
خیر. در ارزیابیهای محیط عملیاتی، MGLRU بار مصرف پردازنده توسط فرآیند kswapd را بین ۱۵ تا ۴۰ درصد کاهش میدهد، زیرا پیمایش بدون قفل جداول صفحات از اتلاف وقت در قفلهای سراسری و پردازشهای سنگین نگاشت معکوس جلوگیری میکند.
آیا MGLRU با محدودیتهای حافظه cgroup v2 سازگاری دارد؟
بله، این ساختار به طور کامل درون ساختار cgroup v2 عمل میکند (memory.high و memory.max). فرآیند پاکسازی در داخل هر گروه مجزا بوده و دادههای مسیریابی فضاهای نام شبکه مجاور را تحت تاثیر قرار نمیدهد.
تفاوت بنیادین میان PSI و آمارهای سنتی vmstat چیست؟
آمارهای گذشته نظیر pgscan صرفا شمار صفحات جابهجا شده را گزارش میدهند بدون اینکه تاثیری بر کندی سیستم را بازتاب دهند. در مقابل، شاخص PSI دقیقا مدت زمان تلف شده پردازنده در انتظار حافظه را اندازهگیری میکند که این معیار مستقیما با تاخیر انتقال دادهها در ارتباط است.



