در دنیای توسعه نرمافزار و سرویسهای توزیعشده، انتخاب روش ارتباطی مناسب میان سرویسها از اهمیت ویژهای برخوردار است. در گذشته، روشهای مختلفی برای برقراری ارتباط میان سرویسها توسعه یافتهاند که هر کدام سعی در ارائهی مزایایی نظیر سرعت بالا، سادگی و امنیت دارند. از میان این روشها میتوان به سرویسهای SOAP، REST و پیامرسانی از طریق Message Queueها اشاره کرد. اما در سالهای اخیر، رویکردی جدید با عنوان gRPC مورد توجه قرار گرفته است که بر پایه فناوری Protocol Buffers (یا ProtoBuf) طراحی شده و بر روی پروتکل اچ تی تی پی/2 کار میکند.
در این مقاله قصد داریم نگاهی به تاریخچهی gRPC، رویکردهای اصلی آن، مزایا، معایب و نحوه کارکردش بیندازیم و در نهایت نیز مقایسهای با REST داشته باشیم.
سرویس های gRPC یا Google Remote Procedure Call ابتدا در گوگل به عنوان یک پروژه داخلی با هدف بهبود ارتباط سرویسهای توزیعشده مطرح شد. گوگل برای میکروسرویسهای متعددی که در سراسر زیرساخت عظیم خود داشت، نیازمند یک روش سریع، امن و کارآمد برای تبادل دادهها بود. این پروژه به مرور زمان تکامل یافت و در سال ۲۰۱۵ به صورت متنباز عرضه شد. از آن زمان جامعه توسعهدهندگان استقبال خوبی از gRPC کردند و امروز این فناوری به یکی از راهکارهای محبوب برای ایجاد ارتباط میان سرویسها تبدیل شده است.
یکی از مهمترین انگیزههای گوگل برای توسعه gRPC، بهبود عملکرد و بهرهوری نسبت به روشهای سنتی (مانند REST مبتنی بر JSON) بود. در مقیاس بزرگ گوگل، مدیریت حجم عظیمی از درخواستها و تعاملات میان سرویسهای مختلف اهمیت بالایی داشت. استفاده از فناوری Protocol Buffers برای سریالسازی دادهها، در کنار استفاده از پروتکل اچ تی تی پی/2، سبب شد تا gRPC بتواند ویژگیهایی چون سرعت و کارایی بالا را در اختیار توسعهدهندگان قرار دهد.
بر پایه مفهوم RPC (Remote Procedure Call) بنا شده است. در این معماری، کلاینت (Client) عملکرد یا متدی که در سمت سرور وجود دارد را فراخوانی میکند و انگار در حال فراخوانی یک تابع محلی است؛ در حالی که در عمل، فراخوانی در بستر شبکه رخ میدهد. این رویکرد توسعه و درک ساختار کدهای سمت کلاینت و سرور را سادهتر میکند.
در gRPC برای سریالسازی دادهها از ProtoBuf استفاده میشود. در این مدل، پیامهایی که بین کلاینت و سرور رد و بدل میشوند در قالب فایلهای *.proto تعریف میشوند. این فایلها ضمن توصیف ساختار داده، امکان تولید خودکار کد برای زبانهای مختلف را هم فراهم میکنند. نتیجهی این کار، سریالسازی و دسریالسازی سریع و کمحجم است و از خطاهای احتمالی در تعریف واسطها جلوگیری میکند.
سرویس های gRPC برخلاف بسیاری از روشهای سنتی که بر مبنای اچ تی تی پی/1.1 هستند، از اچ تی تی پی/2 استفاده میکند. اچ تی تی پی/2 مزیتهایی مانند Multiplexing (ارسال چند درخواست به صورت همزمان در یک کانکشن واحد)، Header Compression و Server Push دارد. وقتی این ویژگیها را کنار عملکرد بالای ProtoBuf بگذاریم، سرعت و کارایی کل سیستم به شکل چشمگیری افزایش مییابد.
برای شروع کار با gRPC، پیامها و سرویسها را در یک فایل *.proto تعریف میکنید. مثلاً:
protoCopy codesyntax = "proto3" message User { int32 id = 1; string name = 2; } service UserService { rpc GetUser (UserRequest) returns (UserResponse); }
در این مثال، یک سرویس با نام UserService
تعریف شده و متدی به نام GetUser
دارد. پیامهای UserRequest
و UserResponse
نیز باید در همین فایل یا فایلهای مجزا تعریف شوند.
پس از تعریف فایل proto، ابزار کامپایلر (مثلاً protoc
) بر اساس زبان مورد نظرتان، کدهای لازم را تولید میکند. در سمت سرور، متدهای سرویس را پیادهسازی میکنید و در سمت کلاینت هم از کلاسها و توابعی که این ابزار ایجاد کرده، استفاده میکنید.
سرویس های gRPC فقط به درخواست/پاسخ ساده محدود نمیشوند و چهار الگوی اصلی را ارائه میدهد:
این الگوها باعث میشوند gRPC برای سناریوهای بلادرنگ، استریم ویدیو، گفتگوی آنی و غیره، بسیار منعطف باشد.
استفاده از اچ تی تی پی/2 و ProtoBuf باعث میشود دادهها با حجم کمتر و سرعت بیشتری رد و بدل شوند. فشردهسازی هدرها، مولتیپلکس شدن درخواستها و عدم وابستگی به فرمت متنی JSON، همگی در افزایش کارایی سیستم نقش دارند.
در gRPC با کمک فایلهای proto، توصیفی دقیق از پیامها و سرویسها ارائه میشود که بین زبانهای مختلف قابل اشتراک است. علاوه بر این، تولید خودکار کد، توسعه را بسیار تسهیل میکند و از ناسازگاری نسخههای مختلف کلاینت و سرور جلوگیری میکند.
همانطور که دیدیم، gRPC از چهار الگوی ارتباطی پشتیبانی میکند و سه مورد آن مبتنی بر استریم هستند. این ویژگی برای برنامههایی که نیاز به ارتباط لحظهای دارند (مثل سرویسهای چت، استریم ویدیو و دادههای IoT) بسیار مفید است.
سرویس های gRPC به صورت پیشفرض میتوانند از TLS استفاده کند تا ارتباط بین کلاینت و سرور رمزگذاری شود. اچ تی تی پی/2 نیز به شکل بهینهتری با TLS کار میکند و مشکلاتی مانند Head of line blocking را کاهش میدهد.
برخلاف JSON که خوانایی بالایی دارد، فرمت باینری gRPC به صورت پیشفرض برای انسان قابل خواندن نیست. هرچند ابزارهایی برای دسریالسازی وجود دارد، اما در مقایسه با سادگی JSON در بحث اشکالزدایی و بررسی سریع، دشوارتر است.
در ابتدای کار، نیاز به یادگیری مفاهیم RPC، ساختار فایلهای proto و کار با ابزارهایی مانند protoc
وجود دارد. برای تیمهایی که به معماری REST عادت دارند، کوچ به gRPC ممکن است زمانبر باشد.
در حال حاضر، مرورگرها به طور مستقیم از gRPC پشتیبانی نمیکنند. پروژه gRPC-web گوگل تا حدی این مشکل را حل میکند، اما همچنان محدودیتهایی وجود دارد. در مقابل، REST و JSON به راحتی در مرورگر قابل استفادهاند (AJAX، Fetch و غیره)(برای سرویس های gRPC نمی توان از swagger استفاده کرد).
با اینکه اکوسیستم gRPC به سرعت رشد میکند، ممکن است در برخی زمینهها ابزارهایی با سطح بلوغ مشابه REST پیدا نکنید. هرچند این فاصله در حال کمتر شدن است، اما همچنان ابزارهای مانیتورینگ و دیباگینگ REST در بسیاری از موارد گستردهتر هستند.
در معماری میکروسرویس، gRPC به دلیل کارایی بالا و حجم کم پیامها گزینهای مناسب است. توصیف سرویسها با فایلهای proto هم به تیمهایی که از زبانهای مختلف استفاده میکنند، کمک میکند.
در زیرساختهای توزیعشده و درونسازمانی، بهرهگیری از gRPC موجب کاهش سربار شبکه میشود. ضمن اینکه میتوان به راحتی امنیت TLS را در محیط داخلی پیادهسازی کرد.
به دلیل پشتیبانی از استریم، gRPC برای سرویسهای چت، اعلانهای لحظهای، استریم ویدیو و پایش دادههای بلادرنگ، بسیار کاربردی است.
فرمت باینری gRPC و پیادهسازی بر پایه اچ تی تی پی/2، پهنای باند کمتری مصرف میکند و بهینهتر است؛ به همین دلیل در اپلیکیشنهای موبایل هم مورد استقبال قرار گرفته است.
پیامها و متدهای سرویس را با جزئیات و نامگذاری واضح در فایلهای proto تعریف کنید تا در آینده در صورت نیاز، توسعه آنها راحتتر باشد.
برای تغییرات در فایلهای proto، نسخهبندی را فراموش نکنید. این کار از بروز ناسازگاری در کلاینتها و سرورها جلوگیری میکند.
در معماری میکروسرویس، ابزارهای مانیتورینگ قدرتمند ضروریاند. با استفاده از ابزارهایی مانند Prometheus، Grafana و سرویسهای ابری، میتوانید متریکهای gRPC را زیر نظر بگیرید.
در gRPC ساختار استانداردی برای گزارش خطاها دارد (Status و StatusCode). حتماً در طراحی سرویسها از این ساختار به جای فیلدهای سفارشی استفاده کنید.
فراتر از TLS، میتوانید از روشهایی مثل توکنهای JWT یا OAuth2.0 در هدر برای احراز هویت استفاده کنید تا سرویسهایتان ایمنتر شود.
سرویس هایgRPC با تکیه بر Protocol Buffers و اچ تی تی پی/2، سرعت و کارایی بالایی را برای ارتباط میان سرویسها فراهم میکند. این فناوری که توسط گوگل توسعه یافت و متنباز شده است، اکنون در پروژههای مختلفی که نیاز به مقیاسپذیری بالا، امنیت و استریم داده دارند، کاربرد گستردهای دارد. البته محدودیتهایی مثل عدم خوانایی باینری و عدم پشتیبانی کامل مرورگرها هم وجود دارد.
در مقایسه با REST، میتوان گفت gRPC سریعتر و کارآمدتر عمل میکند؛ اما REST همچنان برای بسیاری از سناریوها و سرویسهای وب سنتی گزینهای ساده و مطمئن است. اگر سرعت، مصرف بهینه منابع، و ارتباط بلادرنگ در پروژهتان اهمیت زیادی دارد، gRPC میتواند انتخاب عالی باشد. اما اگر تیم شما به معماری REST عادت دارد یا پروژهتان وبمحور است، ممکن است REST همچنان راهکار ایدهآلی باشد.