داستان مهاجرت به اسکریپی:
ما قبل از اسکریپی، انجینی را برای جمع آوری استفاده میکردیم که از PHP قدرت گرفته و از پایه توسط تیم فنی دیتاک توسعه داده شده بود.
با توجه به حیاتی شدن جمع آوری اطلاعات و زیاد شدن تعداد کراولرها و رشد نمایی دیتایی که وارد مجموعه می شد، مدیریت این زیرساخت جمع آوری کم کم داشت به پروسهی سختی تبدیل می شد. از طرفی هم اگر سروری که کراولر PHP را در حال اجرا داشت به هر دلیلی پایین می آمد، سرور دیگری هوشمندانه داخل مدار وارد نمیشد که کار جمع آوری را به عهده بگیرد.
از سوی دیگر با افزایش بار و پیچیده شدن جمع آوری امکان داشت منابع اختصاص داده شده به سروری که انجین جمع آوری PHP رایدک می کشید، کفایت نکند. پس مجبور بودیم منابع را افزایش بدهیم و این اسکیل کردن عمودی ما را با محدودیت رو به رو می کرد.
بعد از مواجهه با همهی این چالش ها تصمیم براین شد که انجین PHP را بزرگتر نکنیم و اجازه بدهیم به زندگی معمولش ادامه دهد ، در عوض کلاستر اسکریپی را برای جمع آوری راه بندازیم. البته اسکریپی خودش به صورت پیش فرض امکان کلاستر بودن را ارائه نمی دهد و نمی تواند روی چند Node هوشمندانه شروع به جمع آوری و همهی جوانب را مدیریت کند. برای کلاستر کردن اسکریپی هم مجبور شدیم به سراغ گلوگاههایی که محدودمان می کردند برویم. اینجا بود که پروژهی اسکریپی کنترلر استارت خورد.
آغاز اسکریپی کنترلر:
همانطور که پیشتر در داستان ‘مهاجرت به اسکریپی’ گفته شد، اسکریپی خودش به صورت پیشفرض قابلیت کلاستر بودن را ارائه نمی دهد و وقتی چند Node را بالا می آورید، این Nodeها هیچ ارتباطی با هم ندارند. در این بین یک رابط لازم است تا بین Nodeها و وضعیت شان ارتباط برقرار کند.
توقع ما از اسکریپی کنترلر چه چیزهایی بود؟
۱. برای تعریف، تغییر و حذف رویهی اجرای اسپایدرها یک API داشته باشد:
برنامه هایی مثل Spiderkeeper و Scrapymon قابل تامل بودند، اما طراحی سادهی آنها و عدم وجود قابلیت مدیریت بیش از یک Node اسکریپی باعث شد که بعد از کمی بررسی کنار گذاشته شوند و خودمان شروع به افزودن این قابلیت به کنترلرمان کنیم.
فرمان صادر شده به APIهای کنترلر شامل (افزودن، ویرایش و حذف) بدون در نظر گرفتن تعداد Nodeهای فعال اسکریپی اجرا میشود.
۲. نمایش وضعیت در لحظهی اسپایدر:
شاید در نگاه اول تعجب کنید و از خودتان بپرسید وقتی خود scrapyd این قابلیت را دارد و می شود وضعیت در لحظهی اسپایدرها را مشاهده کرد، چرا باید این کار را انجام دهیم!؟
بله درست است، اما موقعی که تعداد Nodeها زیاد می شود، فهمیدن این که اسپایدر مورد نظر را روی کدام Node اجرا کرده اید دشوار می شود. اسکریپی کنترلر این قابلیت را به ما می دهد که فارغ از دانستن اینکه کدام اسپایدر روی کدام سرور است، وضعیتش رابررسی کنیم. امکان دارد هر دفعه اسپایدر روی یکی از Node ها اجرا شود. آن گاه اپراتور باید چند tab باز کند و با refresh کردن متوجه بشود که آن اسپایدر خاص، الان روی کدام Node در حال اجراست.
۳. بالانس کردن بار بین Nodeهای اسکریپی:
داخل مورد ۲ گفته شد که ممکن است هربار اسپایدر روی یکی از Nodeها اجرا شود. اسکریپی کنترلرمان برای تخصیص اسپایدر به Nodeهای اسکریپی چند حالت دارد. یک حالت این است که سلامت Node بررسی می شود و به شکل خاص موقع تعریف اسپایدر به Node خاصی تخصیص داده میشود. حالت دیگری که وجود دارد این است که موقع تعریف اسپایدر به سرور خاصی اشاره نکنیم و انتخاب سرور را به عهدهی اسکریپی کنترلر بگذاریم. با این الگوریتم اسکریپی کنترلر آمار اسپایدرهای در حال اجرای همهی Nodeهای اسکریپی را در می آورد، سلامت Nodeها را بررسی می کند و بعد از همهی این ها آن اسپایدر را روی اسکریپی سروری اجرا می کند که از همه خلوتتر است و اسپایدرهای کمتری رویش در حال اجرا هستند. دراین حالت اگر یکی از Nodeهای اسکریپی از دسترس خارج شود کنترلر از آن پاسخی دریافت نمی کند و بدون اینکه جمع آوری با اختلال روبرو شود، اسپایدر روی اسکریپی سرور دیگری به زندگیاش ادامه می دهد.
۴. زمانبندی اجرای اسپایدر:
دراکثر مواقع جمعآوریهای ما به این حالت است که دیتا را دائم به روز می کنیم و نیاز داریم با یک زمان بندی مشخص به یک سورس خاص سر زده و دیتای روز را دریافت کنیم. خیلی از مواقع اسپایدرها باید دائم در حال اجرا باشند. بعضی مواقع لازم است اسپایدر با چند ثانیه تاخیر دوباره شروع به اجرا کند. ما توانستیم همهی این حالت ها را با یک جدول زمانبندی به کنترلرمان اضافه کنیم.
با همین جدول زمانبندی و مقداری تغییر توانستیم این قابلیت را به کنترلر اضافه کنیم که اسپایدرهای تکراری روی یک یا چند Node اجرا نشوند. بگذارید با یک مثال تازه تر توضیح بدهم.
برفرض اگر اسپایدر جمع آوری از یک سایت خبری را به این حالت تعریف کنیم که هر ۳ ثانیه اجرا شود، اگر هنوز اسپایدر در حال اجرا بود و کارش تمام نشده بود و به هر دلیل زمان اجرا از آن interval که برایش در نظر گرفتیم بیشتر شد منتظر بماند که اولین پروسس اجرا شده، از حالت اجرا خارج شود و بعد پروسس جدید اجرا شود.شاید در نگاه اول و تعداد اسپایدر کم و پروژهی کوچک قابلیت خاصی به نظر نرسد، اما در تعداد بالا و وقتی چندین Node اسکریپی داشته باشید، از هدر رفت منابع، شلوغ شدن و زیر لود رفتن سرورها، گرفتن دیتای تکراری هم زمان و لود گذاشتن روی دیتابیس مقصد جلوگیری میکند.
نقاط ضعف و ادامهی مسیر توسعه:
بعد از این همه تعریف و تمجید از فیچرهایی که به کنترل اضافه کردیم، برسیم به نقطه ضعف.
۱. طبق ماهیت و تعریف کلاستر، برای هرکدام از Nodeهای داخل شبکه معمولا برنامه و رویهی خاصی برای شرایط disaster و از بین رفتن Nodeها وجود دارد. این قابلیت را با اسکریپی کنترلر برای Nodeهای اسکریپی فراهم کردیم. ولی نقطهی ضعفمان اینجاست که اگر زمانی خود کنترلر از بین برود هیچ روند اتوماتیکی برای برگرداندن کنترلر و یا جایگزین کردن یک Node بکاپ به جای کنترلر از دست رفته، وجود ندارد و کل کلاستر از دست می رود تا اینکه متوجه شویم و مشکل راحل کنیم، در برنامه های آتی مان هست که این قابلیت را نیز به کلاستر اسکریپی اضافه کنیم.
۲. فعلا هیچ UI خوبی برای این که اپراتور بتواند در یک پنل منظم اسکریپی کنترلر را مدیریت کند و وضعیت Nodeهای اسکریپی را ببیند نداریم و همه درخواستها باید دستی با برنامههایی مثل Postman یا Insomnia توسط اپراتور زده شود، که فرایند را کمی خسته کننده می کند.