--- title: سِروِرلِس tags: serverless uuid: 8faa207b-ab9c-489f-9b75-f1aadb6f76bc --- سرورلس (یا بی‌سرور) یک سبک جدید و متفاوت برای راه‌اندازی سرویس‌های اینترنتی است. برنامه‌های سازگار با سرورلس ارزانتر و پایدارتر هستند و در مقیاس بسیار بالا قابل اجرا. آشنایی من با سرورلس از استاتیک کردن وبسایتم شروع شد و به سرورلس کردن برنامه‌های بزرگتر رسید. وبسایتم را استاتیک کردم تا از دردسر سی‌پنل و خرید هاست و خرابی‌های گاه و بی‌گاه و پیش‌بینی‌ناپذیری هاست‌ها نجات پیدا کنم. از ویژگی‌های دلپذیر رایج گذشتم و به وبسایت ساده‌تری قناعت کردم که در عین سادگی در درازمدت همواره پایدار است و نگهداری‌اش خیلی ساده. نقل و انتقالش هم از یک سرور به سرور دیگر هیچ کاری ندارد (مثلا برعکس انتقال یک سایت وردپرس). برخی اجزای لازم مثل کامنت‌دونی رو هم به صورت حداقلی حل کردم. حتی در صورت انتقال به سرور شخصی هم باز وبسایت نگهداری‌اش بسیار ساده خواهد بود چون وابستگی به دیتابیس و وب‌سرور پیچیده‌ای ندارد. > چه خوب می‌شد اگر برنامه‌نویس فقط برنامه‌اش را می‌نوشت و بقیه کارها به خودی خود انجام می‌شد. مشابه همین کار را برای برنامه‌هایی غیر از یک وبسایت نیز می‌توان انجام داد. یک برنامه به یک محیط برای اجرا احتیاج دارد حتی اگر یک برنامه‌ی تک‌خطی باشد. محیط اجرا یعنی سیستم‌عامل و حافظه و فضای ذخیره‌سازی و شبکه و مانند اینها. یعنی باید ابتدا برنامه را یک جایی نصب کرد. حالا اگر با یک سرویس اینترنتی طرف باشیم باید جایی در اینترنت یک سرور دست و پا کنیم و برنامه را آنجا اجرا کنیم. ناگفته پیداست که کار به اینجا ختم نمی‌شود. باید از سرور نگهداری کرد و بروزرسانی‌های امنیتی سیستم عامل را نصب کرد و الی آخر. در حقیقت برنامه‌نویس نه فقط باید برنامه را بنویسد بلکه باید زمان قابل توجهی را صرف راه‌اندازی و نگهداری از برنامه بکند. چه خوب می‌شد اگر او فقط برنامه‌اش را می‌نوشت و بقیه کار به خودی خود انجام می‌شد. به همین خاطر ما سیستم‌عامل و سرور را از معادله حذف می‌کنیم. ولی مگر می‌شود یک برنامه را بدون سیستم‌عامل و سرور به صورت دائمی اجرا کرد؟ جواب کوتاه اینست که خیر نمی‌شود. ما فقط نگهداری از سیستم‌عامل را به پلتفرم و برنامه‌ی دیگری واگذار می‌کنیم. برای اینکه تفاوت یک برنامه‌ی سرورلس را با یک برنامه‌ی سنتی نشان بدهیم مثل همیشه به سراغ «[ساقی‌بات]» می‌رویم. من این برنامه را در دو نسخه‌ی ‏[معمولی] و [سرورلس] نوشته‌ام. بگذارید نگاهی بکنیم به نحوه‌ی اجرای این دو برنامه. نسخه‌ی معمولی ساقی‌بات یک برنامه‌ی جاوااسکریپ است که باید مستقیما توسط [نود] اجرایش کنیم. یعنی باید روی یک کامپیوتر وابستگی‌های لازم از جمله خود نود را نصب کنیم و متغیرها را در محیط اجرا اضافه کنیم و بعد برنامه را اجرا کنیم. اگر برنامه کرش بکند باز این خودمان هستیم که باید آن را دوباره اجرا کنیم یا از یک برنامه‌ی دیگر مثل [pm2] استفاده کنیم تا همواره آن را در حال اجرا نگاه دارد. یکی از دلایلی که بسیاری از سرویس‌های اینترنتی و بات‌ها بعد از مدتی از کار می‌افتند و می‌میرند همین است. برنامه کرش می‌کند یا سرور خراب می‌شود یا دیگر پولی و حوصله‌ای برای نگهداری از آن نیست. ساقی‌بات معمولی هم همینطور بود. نسخه‌ی سرورلس ساقی‌بات اما به کلی متفاوت است. از سویی آن هم یک برنامه‌ی جاوااسکریپت ساده است که به نود و همه‌ی نیازمندی‌های ساقی‌بات معمولی محتاج است (آن را دوباره با فریم‌ورک بهتری نوشته‌ام). ولی نحوه اجرای برنامه کاملا فرق می‌کند. مهمترین تفاوت این است که «واحد اجرای برنامه» یک «تابع» یا «فانکشن» است نه یک برنامه‌ی کامل یا همان پراسس. تفاوت‌های مهم: - دیپلوی یک فانکشن بجای کل برنامه - دیپلوی روی یک سرویس‌دهنده‌ی ابری (کامپیوتر دیگران یا هر یک کلاستر با پشتیبانی از سرورلس) بجای نصب مستقیم روی سرور - شکستن برنامه به بخش‌های مختلف و دیپلوی جداگانه آنها دیپلوی کردن همان عملیات نصب نرم‌افزار روی محیط هدف است. مثلا روی یک سرور اینترنتی. معمولا تیم‌های خوب اینکار را به صورت اتوماتیک توسط راه‌حل‌های مختلف [CI] انجام می‌دهند. اگر به سورس‌کد ساقی‌بات سرورلس نگاه کنید به جز فایلهای خود برنامه یک فایل بنام `serverless.yml` می‌بینید. در این فایل متاداده‌های ساقی‌بات و نیز توابع آن را تعریف کرده‌ام. ساختار این فایل اختیاری نیست بلکه طبق دستورالعمل‌های [فریم‌ورک سرورلس] ساخته شده است. این فریم‌ورک یکی از روشهای ایجاد برنامه‌های سرورلس است که از انواع مختلفی از [سرویس‌دهنده‌ها] پشتیبانی می‌کند. در حال حاضر برای مخاطبین داخل ایران سرویس‌دهنده‌های معروف خارج از دسترس هستند ولی نکته‌ی خوب ماجرا اینست که می‌توان مشابه این سرویس را با کیفیت قابل قبولی شخصا ساخت که در آینده به آن خواهم پرداخت. اگر مشتاق هستید [Kubeless] و [Knative] و [fn] و [OpenFaaS] را ببینید. بگذارید نگاهی به این فایل بکنیم: ```yaml service: saaghibot provider: name: aws region: eu-central-1 runtime: nodejs10.x memorySize: 128 environment: SAAGHIBOT_TOKEN: ${ssm:/saaghibot_token} functions: saaghia: handler: handler.saaghia events: - http: path: saaghia method: post cors: true - schedule: rate(5 minutes) ``` این فایل سه بخش اصلی دارد. نام سرویس و شرح سرویس‌دهنده و لیست توابع. البته می‌تواند شاخ و برگ فراوانی داشته باشد ولی ساقی به همین راضی است! بخش سرویس‌دهنده برای اجرا روی سرویس‌های ابری آمازون نوشته شده است. براحتی می‌توان آن را به منظور انتقال به یک سرور شخصی تغییر داد که قصد دارم در آینده به آن بپردازم. لیست توابع شامل تنها یک تابع است به نام `saaghia`. اگر با دقت بیشتری به آن نگاه کنیم دو مدخل مهم دارد: ```yaml saaghia: handler: handler.saaghia events: - http: path: saaghia method: post cors: true - schedule: rate(5 minutes) ``` اولی `handler` است که به کد واقعی تابعی اشاره می‌کند که داریم تعریف می‌کنیم. دیگری `events` است که می‌گوید چه رویدادهایی منجر به اجرای این تابع می‌شوند. رویداد اول `http` است و دومی `schedule`. اولی باعث می‌شود که یک آدرس وب توسط سرویس‌دهنده‌ی ابری برای این تابع خلق بشود و دومی هم هر پنج دقیقه این تابع را اجرا می‌کند. با داشتن این فایل و کد پروژه (که با نود نوشته شده) می‌توانیم این تابع را بسته‌بندی و در سرویس‌دهنده ابری آپلود کنیم. برای همه این موارد از دستور `sls` که توسط فریم‌ورکی که استفاده کردیم فراهم شده استفاده می‌کنیم. خلاصه دستورات را در ادامه می‌آورم. و همانطور که پیشتر اشاره کردم از شرح جزئیات خاص آمازون صرف نظر می‌کنم چون در ایران کاربردی ندارد و البته می‌تواند جایگزین بشود. ``` $ git clone https://github.com/mehdisadeghi/saaghibot-serverless && cd saaghibot-serverless $ npm install # install saaghibot dependencies $ npm insgall -g serverless # install serverless framework $ sls deploy # aws cli should be configured ``` همین چند دستور کافیست که تابع در آمازون آپلود و آماده‌ی اجرا بشود.توجه کنید که سیستم‌عامل و وب‌سرور و شبکه و مانند اینها اینجا برای ما اصلا مهم نیست و از دید ما پنهان است. ما فقط یک تابع تعریف کردیم و همان را هم اجرا می‌کنیم. بگذارید شرح توابع دیپلوی شده را ببینیم. ``` $ sls info Service Information service: saaghibot stage: dev region: eu-central-1 stack: saaghibot-dev resources: 13 api keys: None endpoints: POST - https://xxxxxxxxxx.execute-api.eu-central-1.amazonaws.com/dev/saaghia functions: saaghia: saaghibot-dev-saaghia layers: None ``` می‌بینید که تابع ما آدرس وب خاص خودش را دارد که می‌توان درخواست وب به آن POST کرد. من برای این تابع هیچگونه کنترلی ننوشته‌ام. یعنی هرکس با داشتن لینک می‌تواند آن را صدا بزند. به همین خاطر آدرس را تغییر داده‌ام. به کمک همین دستور کارهای بیشتری می‌شود کرد. مثل اجرای تابع از راه دور، دیدن لاگ تابع، لیست توابع دیپلوی شده و مانند اینها. فقط کافیست تایپ کنید `sls` و مستندات را ببینید. در ضمن ممکن است برایتان سوال پیش آمده باشد که چگونه ساقی‌بات سرورلس را به [بات تلگرام ساقی] وصل کرده‌ام. برای اینکار لینک بالا را خورانده‌ام به API تلگرام. هربار پیام جدیدی برای ساقی به تلگرام می‌رسد او فورا یک درخواست HTTP به لینک بالا POST می‌کند و تابع هم جوابش را می‌دهد. دستور را در ادامه می‌آورم. ``` ➜ saaghi git:(master) ✗ 2051 curl --request POST --url https://api.telegram.org/bot/setWebhook --header 'content-type: application/json' --data '{"url":"https://xxxxxxxxxx.execute-api.eu-central-1.amazonaws.com/dev/saaghia"}' ``` تا مطلب بعدی خوش و خرم باشید! [ساقی‌بات]: https://t.me/SaaghiBot [معمولی]: https://github.com/mehdisadeghi/SaaghiBot/ [سرورلس]: https://github.com/mehdisadeghi/saaghibot-serverless [نود]: https://nodejs.org/en/ [pm2]: https://pm2.keymetrics.io/ [CI]: https://en.wikipedia.org/wiki/Continuous_integration [فریم‌ورک سرورلس]: https://serverless.com/ [سرویس‌دهنده‌ها]: https://serverless.com/framework/docs/providers/ [kubeless]: https://kubeless.io/ [knative]: https://knative.dev/ [fn]: https://fnproject.io/ [OpenFaaS]: https://www.openfaas.com/ [بات تلگرام ساقی]: https://t.me/SaaghiBot