اخبار وب

GraphQL Federation و میکروسرویس‌های مدرن

مفهوم Federation در میکروسرویس‌ها، تفاوت Composition و Router، Entityها، Query Plan و رفتار خطا و مجوز؛ با مثال مفهومی فروشگاه و منابع رسمی.

1404/12/04 1 دقیقه مطالعه 1,460 بازدید
GraphQL Federation و میکروسرویس‌های مدرن

GraphQL Federation به چند تیم اجازه می‌دهد بخش‌های مختلف یک graph را نگهداری کنند و مصرف‌کننده از یک ورودی مشترک داده بگیرد. این معماری می‌تواند پیچیدگی درخواست‌های فرانت‌اند را کمتر کند، اما پیچیدگی سرویس‌های پشت آن را حذف نمی‌کند. شبکه، مجوزها، خطاها و تغییر Schema همچنان باید مدیریت شوند. ادعای قبلی مقاله دربارهٔ «سریع‌ترین پیاده‌سازی» برای Apollo Router، معیار و مقایسهٔ مشخصی نداشت و حذف شده است. انتخاب Router به نیاز و محدودیت همان پروژه وابسته است.

برای فهم نیاز، یک فروشگاه فرضی را در نظر بگیرید که اطلاعات محصول، موجودی و نظرها در سرویس‌های جدا نگهداری می‌شوند. صفحهٔ محصول به دادهٔ هر سه نیاز دارد. Federation می‌تواند قراردادی واحد برای مصرف‌کننده فراهم کند، در حالی که مسئولیت تولید داده میان تیم‌ها تقسیم شده است. این مثال مطالعهٔ موردی یک شرکت واقعی نیست و هیچ وعدهٔ سرعتی از آن استخراج نمی‌شود. هدف فقط روشن کردن مرز بین قرارداد عمومی و سرویس‌های مالک داده است.

Subgraph، Supergraph و Router

Subgraph بخش مستقلی از graph است که Schema و رفتار ارائهٔ دادهٔ خود را دارد. Supergraph حاصل ترکیب قرارداد این بخش‌هاست. Router درخواست مصرف‌کننده را دریافت می‌کند و مسیر دریافت داده از بخش‌های لازم را هماهنگ می‌کند. معرفی رسمی Apollo Federation این نقش‌ها را توضیح می‌دهد. وجود یک ورودی مشترک در سمت کلاینت، به معنی یک فراخوانی داخلی یا یک پایگاه داده نیست؛ یک درخواست می‌تواند چند مرحلهٔ دریافت داده ایجاد کند.

در مثال فروشگاه، صفحه ممکن است نام محصول و تعداد موجودی را بخواهد. اگر موجودی برای شناسهٔ محصولی که از سرویس محصول آمده محاسبه شود، ترتیب وابستگی مهم است. Router نمی‌تواند هر بخش را بدون در نظر گرفتن دادهٔ لازم مستقل اجرا کند. پس طراحی Schema و رابطهٔ Entityها بر مسیر اجرای درخواست اثر دارد. برای تیم، دانستن اینکه کدام بخش مالک شناسه و کدام بخش مسئول هر فیلد است، از تصور یک «ترکیب خودکار بی‌دردسر» مفیدتر است.

Composition با اجرای درخواست فرق دارد

Composition مرحلهٔ بررسی و ترکیب قرارداد Subgraphهاست. قرار نیست هر درخواست کاربر دوباره همهٔ Schemaها را مثل رشته به هم بچسباند. نتیجهٔ این مرحله باید از نظر قواعد سازگاری قابل قبول باشد. راهنمای Schema Composition مرجع این بررسی است. اگر دو تیم دربارهٔ تعریف یک نوع یا مالکیت فیلد توافق نداشته باشند، حل آن اختلاف یک تصمیم طراحی است؛ ابزار فقط بعضی ناسازگاری‌ها را گزارش می‌کند.

در فرایند انتشار، نتیجهٔ Composition باید پیش از در دسترس قرار گرفتن تغییر معلوم باشد. به‌روزرسانی یک Subgraph می‌تواند قرارداد مشترک را تحت تأثیر قرار دهد، حتی اگر تیم صاحب آن فقط چند خط تغییر داده باشد. برای تغییر حساس، مراحل آماده‌سازی، سازگاری و استفادهٔ مصرف‌کننده را مشخص کنید. انتشار مستقل تیم‌ها به معنی بی‌نیازی از هماهنگی قرارداد نیست؛ مرز همکاری از کپی کد مشترک به نگهداری Schema و رفتار عمومی منتقل می‌شود.

Entityها به شناسهٔ پایدار نیاز دارند

اگر یک محصول در چند Subgraph دیده شود، باید روشن باشد این ارجاع‌ها چگونه به همان محصول متصل می‌شوند. معرفی Entityهای Federation مفهوم کلید و ارجاع را توضیح می‌دهد. انتخاب کلید را به چیزی که در ظاهر صفحه خوش‌خوان است محدود نکنید. عنوان محصول ممکن است تغییر کند یا تکراری باشد؛ شناسه باید با قرارداد دادهٔ سرویس‌ها سازگار بماند و امکان حل ارجاع را فراهم کند.

وجود کلید نیز کیفیت داده را تضمین نمی‌کند. ممکن است سرویس موجودی برای محصول حذف‌شده هنوز رکورد داشته باشد، یا زمان به‌روزرسانی دو بخش متفاوت باشد. تیم باید دربارهٔ نبود داده و تأخیر هماهنگ‌سازی تصمیم بگیرد. در صفحهٔ محصول، «موجودی نامعلوم» با «موجودی صفر» یکسان نیست. اگر این تفاوت در Schema یا رفتار resolver گم شود، مصرف‌کننده ممکن است دادهٔ ناقص را به‌عنوان حقیقت تجاری نمایش دهد و کاربر تصمیم اشتباه بگیرد.

Query Plan را با مسئلهٔ محصول بخوانید

Query Plan نشان می‌دهد دریافت بخش‌های درخواست چه مسیری دارد. مرجع Query Plans این ساختار را شرح می‌دهد. برای بررسی کارایی، یک Query واقعی صفحه را انتخاب کنید و وابستگی‌های آن را ببینید. فهرستی از فیلدها که هیچ مصرف‌کننده‌ای نمی‌خواهد، معیار خوبی برای تصمیم نیست. مسیر کند را باید به همان درخواست و همان داده‌ای وصل کرد که کاربر در جریان اصلی نیاز دارد.

در مثال فروشگاه، اگر نمایش نام محصول به دریافت قیمت و موجودی وابسته شده باشد، صفحه برای یک اطلاعات ساده منتظر چند سرویس می‌ماند. شاید این وابستگی در Schema ضروری باشد، شاید از طراحی نامناسب آمده باشد. قبل از افزودن cache، معنی وابستگی را مرور کنید. cache می‌تواند بعضی هزینه‌ها را کم کند، اما قراردادی که دادهٔ لازم و غیرلازم را مخلوط کرده، با cache به قرارداد روشن تبدیل نمی‌شود. انتخاب داده باید از نیاز رابط بیاید.

خطا و Nullability را به تجربهٔ کاربر وصل کنید

وقتی سرویس نظرها جواب نمی‌دهد، آیا صفحهٔ محصول باید کاملاً خالی شود؟ پاسخ به نقش آن داده بستگی دارد. برای یک بخش جانبی، نمایش محصول همراه با پیام کوتاه ممکن است کافی باشد؛ برای قیمت قابل پرداخت، ادامهٔ خرید با دادهٔ نامعلوم مناسب نیست. تصمیم دربارهٔ nullable بودن فیلد فقط انتخاب نحوی نیست و روی رفتار شکست اثر دارد. راهنمای Nullability به بررسی این قرارداد کمک می‌کند.

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

مجوز در ورودی مشترک تمام نمی‌شود

داشتن Router مشترک به معنی مجاز بودن تمام درخواست‌های رسیده به Subgraph نیست. هر عملیات باید با نقش کاربر و دامنهٔ دادهٔ او سازگار باشد. اگر سرویس چند سازمان را نگهداری می‌کند، شناسهٔ Entity نباید راهی برای دریافت دادهٔ سازمان دیگر ایجاد کند. اطلاعات لازم برای بررسی مجوز باید با قرارداد امن به بخش مربوط برسد. معماری graph، جای سیاست دسترسی محصول را نمی‌گیرد و یک Query معتبر از نظر Schema الزاماً مجاز نیست.

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

چه زمانی هزینهٔ Federation قابل توجیه است؟

مسئول رسیدگی به اختلال Router و هر Subgraph را از ابتدا تعیین کنید. اگر صفحهٔ مشترک خطا دارد، تیم رابط نباید برای پیدا کردن صاحب مشکل میان چند گروه سرگردان شود. مستند مالکیت، مسیر هشدار و نمونهٔ درخواست مرتبط کمک می‌کند مسئله به تیم درست برسد. دادهٔ مشاهده‌پذیری باید با حساسیت اطلاعات هماهنگ باشد؛ ثبت کامل ورودی کاربران برای آسان شدن عیب‌یابی، تصمیم پیش‌فرض مناسبی نیست و نیاز به دامنهٔ روشن دارد.

اگر چند تیم مالک بخش‌های مستقل داده‌اند و مصرف‌کننده‌ها بارها به ترکیب همان بخش‌ها نیاز دارند، Federation گزینه‌ای قابل بررسی است. اگر یک تیم کوچک یک سرویس و چند صفحهٔ ساده نگه می‌دارد، افزودن این لایه ممکن است هزینهٔ ابزار و عملیات را بیشتر کند. تعداد سرویس‌ها به‌تنهایی معیار کافی نیست. مرز مالکیت، نیاز مصرف‌کننده و توان نگهداری باید کنار هم دیده شوند. عبارت «راه‌حل ایده‌آل میکروسرویس‌ها» این تفاوت‌ها را پنهان می‌کند.

REST و Federation نیز الزاماً انتخاب‌های کاملاً جدا نیستند. دادهٔ پشت graph ممکن است از سرویس‌های موجود بیاید و تیم برای مهاجرت تدریجی دلیل داشته باشد. قبل از تغییر، قرارداد کنونی و هزینهٔ نگهداری آن را ثبت کنید. برای ادامهٔ سمت کلاینت، راهنمای GraphQL و Apollo Client مرتبط است. یک بخش محدود از محصول را انتخاب کنید، مالک فیلدها و رفتار خطا را بنویسید و بعد دربارهٔ لایهٔ مشترک تصمیم بگیرید.

واکنش به این مقاله

اشتراک‌گذاری این مقاله:
دیدگاه‌ها 0
۰ / ۲۰۰۰

هنوز دیدگاهی ثبت نشده

اولین نفری باشید که نظر می‌دهد!