در ادامه مقاله 10 اشتباه برنامهنویسان Backend (بخش اول)
1. عدم نظارت بر میکروسرویسها برای محیط تولید
مسأله:
تولید باید تا حد امکان در دسترس باشد، بنابراین اگر هر میکروسرویسی برای چند ساعت از کار بیفتد، میتواند مشکلات بزرگی ایجاد کند. بنابراین ما باید بر همه میکروسرویسها نظارت داشته باشیم و در صورت از کار افتادن هر کدام، باید مجددا آن را در سریعترین زمان ممکن بالا بیاوریم. این یک اشتباه DevOps است، اما علاوه بر کار DevOps، توسعهدهندگان backend نیز باید برای هر میکروسرویس وضعیت endpoint را پیادهسازی کنند. وقتی یک میکروسرویس از کار میافتد، احتمالا برخی توسعهدهندگان backend باید آن را اصلاح کنند.
عواقب:
باگهای بزرگ به دلیل از کار افتادن میکروسرویسها یا از کار افتادن کل سیستم هنگام خراب شدن ضروریترین میکروسرویسها رخ میدهند.
پیشگیری:
ما باید نظارت برای هر میکروسرویس تولید را به عنوان اولین اقدامات انجام شده بعد از ایجاد محیط تولید کانفیگ کنیم.
راهکار:
ما باید نظارتهایی که انجام نشده را کانفیگ کنیم و همه میکروسرویسهای از کار افتاده را احیا کنیم.
2. ایجاد data model بدون برنامهریزی مناسب
مسأله:
دیتا مدل بخش مهمی از معماری سیستم است، بنابراین اگر بد طراحی شود، میتواند برخی مشکلاتی را که بعدا توضیح میدهیم را ایجاد کند.
عواقب:
میتواند باعث ایجاد دادههای نامعتبری در تولید شود، دادهها برای تحلیل یا نگهداری دشوار میشوند و نمایش دادهها بسیار کند میشود.
پیشگیری:
ما باید دیتا مدل را با دقت طراحی کنیم، در مورد آن با کل تیم backend، اگر نسبتا تیم کوچک باشد (حدودا 10 نفر) بحث کنیم. در رابطه با تیم بزرگتر، ما باید در مورد مدل با زیرمجموعههای تیم که مسئول منطق مربوط به این مدل هستند و علاوهبراین با برخی متخصصان عمومی داده یا کارشناسان تخصصی داده مانند متخصص key-value DBMS گفتگو کنیم.
راهکار:
اگر یک دیتا مدل بد هنوز برای تولید منتشر نشده است، میتوانیم دیتا مدل را آپدیت کنیم و دادههای نامعتبر ایجاد شده در محیطهای پایینتر را حذف کنیم. اگر یک دیتا مدل بد از قبل برای تولید منتشر شده باشد، علاوه بر آپدیت دیتا مدل، باید یک مایگریشن برای اصلاح دادههای نامعتبر بنویسیم.
متاسفانه، در برخی شرایط، اصلاح کامل دادههای نامعتبر در مرحله تولید غیر ممکن است. اگر ما برخی دادههای مبهم را ذخیره کنیم این اتفاق میافتد، مثلا نام شهر به جای شناسه شهر، زیرا شهرهای زیادی میتواند با نام مشابه وجود داشته باشد.
3. تزریق SQL (SQL injection)
مسأله:
این اشتباهی است که عمدتا توسط توسعهدهندگان تازهکار backend رخ میدهد، اما گاهی اوقات حتی توسعهدهندگان ارشد نیز میتوانند این مشکل را ایجاد کنند. SQL injection یک احتمال خطرناک است که کاربر یک کوئری را مینویسد که سپس به دلیل string concatenation اجرا میشود. به هر حال این یک اصطلاح کلی است زیرا میتواند تزریق زبان کوئری دیگری مثل AQL (ArangoDB Query Language)، GraphQL و غیره باشد. مشکل مشابهی میتواند هنگام استفاده از تابع eval یا اجرای یک دستور سیستم عامل رخ دهد.
عواقب:
کاربر (هکر) دادههایی را میگیرد که نباید بتواند آنها را بخواند یا بدتر از آن، دادههایی که آپدیت کند، وارد کند یا حذف کند.
پیشگیری:
برای جلوگیری از این اشتباه توسعهدهندگان backend، ما باید مراحلی را انجام دهیم، یک بررسی کد دقیق انجام دهیم (در بخش اول گفتیم)، از string concatenationها تا حد ممکن استفاده کنیم، مطمئن شویم هر بخش از رشته معتبر است، بنابراین با وجود استفاده از بسیاری از دیتابیسها و بسیاری از کاربران دیتابیس، کوئریهای خطرناک ایجاد نمیشود، پس اگر کاربر چیزی را استخراج کند، قدرت او محدود است، و پشتیبانگیری خودکار دیتابیس تولید شده (در بخش یک توضیح داده شد) را انجام دهید تا بتوانید دادههای حذف شده یا آسیبدیده توسط هکر را بازیابی کنید.
راهکار:
مراحل پیشگیری را اعمال کنید و آنها را در اسرع وقت برای تولید منتشر کنید.
4. عدم لاگ کردن (Log)
مسأله:
لاگ کردن برای گزارش هر گونه مشکل و جمعآوری آمار در مورد استفاده از سیستم ضروری است.
عواقب:
رفع باگهایی که قبلا، در هر مرحله استقرار یافتهاند، دشوارتر و یا حتی گاهی غیر ممکن است.
پیشگیری:
ما باید همه خطاهای سرور را برای محیط تولید لاگ کنیم، از جمله stack trace، timestamp، request body/path/headers و نام کاربری رمزگشایی شده و آدرسهای IP کلاینت. علاوهبراین، برای محیط توسعه (dev)، خوب است که هر درخواست را با یک پاسخ کامل لاگ کنیم. همچنین باید قبل از لاگ کردن آنها، گواهینامهها (credential) را تنظیم کنیم تا از نفوذ آنها جلوگیری کنیم. گاهی اوقات ممکن است ما نیاز به لاگ کردن جزئی داشته باشیم مانند نگهداری فقط چند عنصر از آرایه.
همچنین خوب است که اطلاعات خیلی پایه را در مورد هر درخواست تولید شده لاگ کنیم مثل timestamp، مسیر درخواست، نام کاربری رمزگشایی شده و client IP تا آمارهایی را جمعآوری کنیم که نشان میدهد اغلب یک endpoint معین چگونه استفاده میشود و در کدام ساعت/تاریخ از هفته ترافیک بالاتری دارد.
راهکار:
پیادهسای logging ASAP.
5. عدم جزئیات خطاهای کلاینت یا نمایش جزئیات خطاهای سرور در API
مسأله:
هر درخواست خطای کلاینت (status codeای که با 4 شروع میشود) باید حاوی جزئیاتی باشد تا کاربران (معمولا توسعهدهندگان frontend یا سایر توسعهدهندگان وب) بتوانند به راحتی پارامترهای ارسالشده را اصلاح کنند. با این حال، درخواستهای خطای سرور (status code ای که با 5 شروع میشود) نباید هر جزئیاتی را نمایش دهد زیرا آنها میتوانند برای سوءاستفاده از سیستم مورد استفاده قرار گیرند.
علاوهبراین، وقتی یک stacktrace نشان داده میشود، این خطر وجود دارد که شامل برخی credentialها باشد. بنابراین، وقتی خطای سرور وجود دارد، باید یک پیام عمومی مثل " Internal server error" برگردانیم و جزئیات خطا را لاگ کنیم (در مورد 9 توضیح دادیم).
عواقب:
عدم جزئیات خطای کلاینت، استفاده از endpoint مشخص را بسیار مشکلتر میسازد و نمایش جزئیات خطای سرور میتواند موجب سوءاستفاده از سیستم شود.
پیشگیری:
هر endpoint مطابق با قوانین تعریفشده در این مرحله را پیادهسازی کرده و بررسی کد مناسب انجام شود.
تستهای endpoint سناریوهای مختلفی را پوشش میدهد از جمله خطاهای کلاینت (به طور کلی، ما قادر به پیشبینی خطاهای سرور نیستیم).
راهکار:
پیدا کردن هر دو وضعیت و رفع آنها.
نتیجهگیری
فرقی نمیکند تجربه backend شما چقدر باشد، در هر صورت امیدواریم در مورد ارزش اجتناب از برخی اشتباهات یا عواقب آنها یا روشهایی برای جلوگیری یک اشتباه معین، مطالبی را آموخته باشید.
نظرات کاربران در رابطه با این دوره