برنامه نویسی

بهینه سازی درخواست های همزمان در C++: درس هایی از پروژه سرور HTTP من – انجمن DEV

در دنیای توسعه وب، کارایی کلیدی است و بهینه‌سازی نحوه رسیدگی سرورها به درخواست‌های مشتری همزمان یکی از حیاتی‌ترین جنبه‌ها است. در حین یادگیری در مورد شبکه و برنامه نویسی سیستم، خودم را به چالش کشیدم تا یک سفارشی بسازم سرور HTTP در C++.

این پروژه فقط نوشتن کد نبود. این در مورد غواصی عمیق در مورد چگونگی مدیریت سیستم های دنیای واقعی همزمانی و تخصیص منابع بود. در طول مسیر، با چالش های مختلفی مواجه شدم و چندین بهینه سازی را برای قوی و مقیاس پذیر ساختن سرور پیاده سازی کردم.

در این وبلاگ، شما را با طراحی، چالش ها و راه حل ها همراه با توضیحات مفصل و کدهای کد آشنا می کنم.

درباره من

سلام، من Priyanshu Kumar Sinha هستم، در حال حاضر مدرک B.Tech خود را در علوم کامپیوتر و سیستم های تجاری در دانشکده مهندسی Dayananda Sagar دنبال می کنم. من همیشه مشتاق حل مشکلات دنیای واقعی از طریق فناوری بودم.

پریانشو کومار سینها

چرا از ابتدا یک سرور HTTP بسازیم؟

به عنوان فردی که مشتاق درک چگونگی کار کردن همه چیز است، ساخت یک سرور HTTP پروژه عملی عالی برای یادگیری بود:

  • ارتباط مشتری و سرور: استفاده از TCP/IP برای چرخه های درخواست-پاسخ.
  • همزمانی: رسیدگی به چندین درخواست مشتری به طور همزمان.
  • مدیریت موضوع: استفاده بهینه از منابع سیستم.

با پرداختن به این پروژه، بینش ارزشمندی در مورد اینکه سرورهای وب چگونه دوست دارند به دست آوردم آپاچی یا Nginx بارهای ترافیکی عظیم را به طور موثر مدیریت کنید.

مرد آهنی

چگونه سرور به درخواست ها رسیدگی می کند

سرور از پروتکل TCP برای ایجاد ارتباط بین مشتری و سرور.

بیایید با گردش کار اصلی سرور شروع کنیم و قیاس هایی را برای روشن کردن مفاهیم فنی در نظر بگیریم.

1. ایجاد سوکت

یک سوکت سرور ایجاد می شود و به یک پورت خاص متصل می شود. سپس سرور به اتصالات مشتری ورودی گوش می دهد.

به عبارت ساده تر، سرور یک “در” (سوکت) ایجاد می کند که مشتریان برای درخواست اتصال به آن ضربه می زنند. مانند باز کردن باجه بلیط در ایستگاه قطار که مشتریان برای خرید بلیط صف می کشند، فکر کنید.

سوکت سرور مانند “ورودی اصلی” یک ساختمان است که همیشه آماده پذیرایی از مهمانان جدید است.

2. هندلینگ اتصال

هنگامی که یک کلاینت متصل می شود، سرور اتصال را می پذیرد و یک “دستیار” (رشته) جدید برای سرویس دهی به مشتری ایجاد می کند. در ابتدا من از 1 رشته در هر اتصال مدل

به عنوان مثال، رستورانی را تصور کنید که در آن هر مشتری پیشخدمت خود را دارد. در حالی که این خدمات عالی را تضمین می کند، اگر 1000 مشتری به یکباره وارد شوند، به سرعت ناپایدار می شود!

3. درخواست تجزیه:

سرور درخواست HTTP را تجزیه می کند و اطلاعات کلیدی مانند روش HTTP، URI و هدرها را استخراج می کند.

4. تولید پاسخ:

سرور درخواست را پردازش می کند و یک پاسخ HTTP مناسب (به عنوان مثال، یک صفحه HTML یا پیام خطا) را ارسال می کند.

چالش ها با درخواست های همزمان

در حین اجرای چند رشته ای، با چندین چالش مواجه شدم:

چالش 1: مدیریت موضوع

ایجاد یک موضوع جدید برای هر مشتری مانند استخدام یک پیشخدمت شخصی برای هر مشتری در یک رستوران است. همانطور که ترافیک افزایش می یابد، این رویکرد تحت وزن بیش از حد نخ ها از بین می رود.

به عنوان مثال، رسیدگی به هر درخواست مشتری در یک رشته مجزا می تواند منجر به ایجاد رشته بیش از حد، به خصوص در ترافیک بالا شود. این اغلب نامیده می شود “1 رشته در هر اتصال” مدل، که به خوبی مقیاس نمی شود و تعداد مشتریان افزایش می یابد.

راه حل:

به جای ایجاد موضوعات به صورت پویا، a را پیاده سازی کردم استخر نخکه مانند استخدام تعداد ثابتی از پیشخدمت‌ها (رشته‌ها) که از چندین میز سفارش می‌گیرند (به درخواست‌های متعدد رسیدگی می‌کنند) عمل می‌کند و هزینه‌های ایجاد و تخریب نخ را به حداقل می‌رساند.

چگونه کار می کند:

  1. سوکت های مشتری ورودی به یک صف مشترک اضافه می شوند.
  2. تعداد ثابتی از thread های کارگر وظایف را از صف می گیرند و آنها را پردازش می کنند.

باور نکردنی

به عبارت ساده‌تر، The Thread Pool مانند داشتن تیمی از پیشخدمت‌ها است که در هنگام ورود به مشتریان خدمات ارائه می‌دهند. اگر همه پیشخدمت ها مشغول باشند، مشتریان در نوبت منتظر می مانند. این تضمین می کند که رستوران با منابع (یا پیشخدمت) تمام نشود.

چالش 2: شرایط مسابقه

هنگامی که چندین رشته به منابع مشترک دسترسی پیدا می کنند، مانند این است که دو پیشخدمت سعی می کنند در یک دفترچه یادداشت سفارشات را دریافت کنند. نتیجه؟ هرج و مرج و خطا.

راه حل:

من استفاده کردم قفل های موتکس برای همگام سازی بخش های حیاتی این تضمین می کند که تنها یک رشته می تواند در یک زمان به منابع مشترک دسترسی داشته باشد.

دو رشته، یک منبع... بدترین چیزی که ممکن است اتفاق بیفتد چیست؟

به عبارت ساده تر، قفل های Mutex مانند اختصاص یک دفترچه یادداشت به هر پیشخدمت است. هیچ کس دیگری نمی تواند از آن استفاده کند در حالی که پیشخدمت در حال گرفتن سفارش است و از اختلاط جلوگیری می کند.

چالش 3: مسدود کردن تماس ها (در حال اجرا…)

عملیات مسدود کردن مانند accept() یا recv() مانند یک صندوقدار هستند که تمام کارها را متوقف می کند تا منتظر بماند تا مشتری کیف پول خود را پیدا کند. وقت با ارزش را تلف می کند.

راه حل:

من استفاده کردم سوکت های غیر مسدود کننده و زمان‌بندی برای اتصالات سرویس گیرنده تنظیم کنید، و اطمینان حاصل کنید که سرور در انتظار کلاینت‌ها (یا داده‌های) بی‌پاسخ نمی‌ماند.

وقتی recv() برای همیشه بلاک می شود و سرور شما مانند: 💤 است

به عبارت ساده‌تر، سوکت‌های غیرمسدود مانند یک صندوقدار است که از مشتری بعدی در صف می‌خواهد تا در حالی که مشتری اول کیف پولش را جستجو می‌کند، حرکت کند. جریان را در حرکت نگه می دارد.

نتایج و نکات مهم

نتایج:

  • مقیاس پذیری: Thread Pool به سرور اجازه می‌دهد تا بیش از 1000 اتصال همزمان را بدون خرابی مدیریت کند.
  • کارایی: سوکت های غیر مسدود زمان پاسخگویی سریع تر را برای مشتریان تضمین می کند.
  • قابلیت اطمینان:قفل‌های Mutex از شرایط مسابقه جلوگیری می‌کنند و یکپارچگی داده‌ها را تضمین می‌کنند.

سرور بهینه شده مانند: آن را روشن کنید!

فراخوان برای اقدام

اگر به شبکه سازی و بهینه سازی سرور علاقه دارید، این پروژه را امتحان کنید! README.md در مخزن سرور HTTP حاوی دستورالعمل های دقیق، جزئیات پیاده سازی اضافی و نکات بیشتری برای بهبود سرور است.

با خیال راحت مخزن را جدا کنید، پیشرفت‌هایی را پیشنهاد دهید یا حتی در پیشرفت‌های آینده همکاری کنید. بیایید با هم چیزی عالی بسازیم!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا