در این مقاله می خواهیم به معرفی فریم ورک متن باز Remote Procedure Call (RPC) بپردازیم، همانطور که از نام آن پیدا است این فریم ورک برای ارتباط بین دستگاه‌ها، برنامه‌های کاربردی تلفن همراه و مرورگرها قابل اجرا است، در ادامه به شرح کامل آن می پردازیم.

معرفی gRPC

PRC که مخفف Remote Procedure Call می باشد، یک پروتکل برای فراخوانی یک سرویس از یک برنامه، داخل یک برنامه دیگر است. یعنی برنامه A برای اینکه یه فانکشنی داخل برنامه B رو بتونه فراخوانی کنه از این پروتکل استفاده میکنه، پس تا اینجا متوجه شدیم برای اینکه دوتا برنامه بخواهند بین همه دیگه دیتا ارسال و دریافت کنن از طریق این پروتکل میتوانند عمل کنن.

نکته: این را همه در نظر داشته باشید این ارتباط در پروتکل TCP/IP بر روی لایه Application از طریق HTTP2 اطلاعات را ارسال و دریافت می کند.

یکی از مزیت های خوب دیگر فریم ورک این است که میتوانیم ارتباط بین چندین برنامه به زبان های مختلف را برقرار کنیم، به این معنی که مهم نیست مبداء یا مقصد هر دو با زبان PHP نوشته شده باشند، پروتکل RPC این امکان را می دهد که تمام برنامه های که می خواهند ارتباط با همدیگر برقرار کنند باید طبق استانداردی به نام proto برای ارسال و دریافت داده ها عمل کنند.

همانطور که در تصویر بالا مشاهده می کنید یک سرویس که با زبان ++ C نوشته شده است امکان ارتباط برقرار کردن بر روی gRPC server فراهم کرده است که از طریق استانداری به نام proto باهمدیگر ارتباط برقرار کرده اند، توجه داشته باشید که این ارتباط دارای یک Proto Request و Proto Response می باشد که تعیین می کنند که بین کلاینت و سرور چه دیتای ارسال و دریافت شود.

به صورت کلی ارتباط بین سرور و کلاینت ها به صورت RESTFull می باشد که مرسوم ترین روش ارسال و دریافت اطلاعات است که از طریق پروتکل HTTP بر روی بستر شبکه این کار را انجام می دهند. در ادامه می خواهیم تفاوت بین درخواست های RESTFull , gRPC را بررسی کنیم و همچنین در کنار آن فایل proto را معرفی کنیم و اینکه gRPC چگونه ارتباط و بین کلاینت ها برقرار می کند را شرح دهیم.

آشنایی و معرفی proto

همانطور که قبلا هم اشاره کردیم برای اینکه یک درخواست و پاسخ بین سرویس ها و کلاینت ها ارسال و دریافت بشه باید یک پروتکل یا استانداری را داشته باشید، برای همین منظور یک فایل در کنار پروژه شما وجود دارد، برای اینکه بهتر متوجه شوید مثالی که گفته می شود را هم خط به خط بررسی می کنیم، در اینجا سرویسی به نام support (پشتیبانی) را داریم که امکان ارتباط برقرار کردن از طریق پروتکل RPC در آن وجود دارد، ساختار فایل آن به شکل زیر می باشد :

syntax = "proto3";

package support;

service Ticket {
    rpc CreateTicket (CreateTicketRequest) returns (TicketInfo) {}
}

message TicketInfo {
  string id = 1;
  CustomerInfo customer = 2;
  UserInfo user = 3;
  string subject = 4;
  string content = 5;
  string status = 6;
  int32 priority = 7;
  string created_at = 8;
  repeated ReplyInfo replies = 9;
  string payload = 10;
}

message CreateTicketRequest {
  string subject = 1;
  string content = 2;
  int32 priority = 3;
  CustomerInfo customer = 4;
  UserInfo user = 5;
  string payload = 6;
}

همانطور که در بالا مشاهده می کنید ساختار فایل gRPC به این شکل است، ولی این دستورات چه کاری را انجام می دهند ؟! بیاین با یک مثال پیش بریم، در اینجا می خواهیم امکان ثبت یک تیکت و پاسخش را از طریق این فایل قرارداد کنیم.

ساختار فایل

در این بخش می خواهیم خط به خط کد را باهم بررسی کنیم و ببنیم چگونه یک استاندارد برای ارتباط RPC تعریف می شود.

syntax = "proto3"

اولین چیزی که با آن مواجه می شوید این خط کد می باشد، در بحث ارتباط ها معمولا برای اینکه بروز رسانی های مختلفی انجام می شود ورژن های مختلف proto با عدد جدا می شود، در این فایل ما از proto3 برای استاندارد ارسال و دریافت اطلاعات استفاده می کنیم، پس هر کلاینت دیگر بخواهد ارتباط برقرار کند باید آن هم قوانین را طبق استاندارد proto3 نوشته باشد.

package support

همانطور که اول هم گفتیم می خواهیم این ارتباط را برای سیستم پشتیبانی طراحی کنیم پس پکیجی که معرفی می کنیم به نام supportمی باشد.

service Ticket

به صورت ساده بخواهم این بخش را توضیح دهم برای تمام حالت های که می خواهیم این ارتباط برقرار شود باید یک متد تعریف کنیم که ورودی و خروجی مشخصی دارد، پس درون سرویسی که برای Ticket تعریف کرده ایم، به عنوان مثال می خواهیم عملیات ایجاد تیکت را از طریق RPC مشخص کنیم.

rpc CreateTicket (CreateTicketRequest) returns (TicketInfo) {}

خط کد بالا به این معنی می باشد که یک ارتباط از نوع rpc برای عملیات CreateTicket می باشد که به عنوان ورودی CreateTicketRequest را دریافت کرده و TicketInfo را برمیگرداند.

پس تا اینجا ما توانستیم درون سرویس ایجاد شده یک عملیات را طبق استانداری که برایش تعیین کردیم مدیریت کنیم.

message TicketInfo

همانطور که در بخش متد داخل سرویس مشاهده کردین ورودی توابع و خروجی تابع مشخص شده بود، TicketInfo دقیقا خروجی هست که قرار است از عملیات ایجاد تیکت برگشت داده شود، تمام پارامتر های داخل این آبجکت طبق مدل های دیتابیس معمولا تعریف می شود یا برحسب نیاز آن را قرارداد می کنیم. پارامتر ها بر حسب نوعی که دارن مشخص شده اند. فقط یک مورد را به عنوان نکته اینجا مطرح می کنم، داخل بدنه یک پارامتر به نام CustomerInfo customer = 2 وجود دارد، خود مقدار CustomerInfo درونش یکسری پارامتر های مثل customer_key وجود دارد، این نوع تعاریف دقیقا مثل ارتباطی است که بین موجودیت ها برقرار می شود، در اینجا می خواهیم بفهمیم که تیکت فرستاده شده توسط کدام کاربر(مشتری) می باشد پس اطلاعات خود مشتری میتواند یک آبجکت جدا باشد.

message TicketInfo {
  string id = 1;
  CustomerInfo customer = 2;
  UserInfo user = 3;
  string subject = 4;
  string content = 5;
  string status = 6;
  int32 priority = 7;
  string created_at = 8;
  repeated ReplyInfo replies = 9;
  string payload = 10;
}

message CreateTicketRequest

در اینجا هم ما پارامتر های ورودی برای ثبت یک تیکت جدید مشخص کرده ایم، توجه داشته باشید که messge یک کلمه کلید می باشد و بعد آن نامی است که می خواهیم مشخص کنیم برای چه عملیات؟ چه دیتای؟ باید دریافت یا ارسال شود.

message CreateTicketRequest {
  string subject = 1;
  string content = 2;
  int32 priority = 3;
  CustomerInfo customer = 4;
  UserInfo user = 5;
  string payload = 6;
}

دقیقا تعریف ورودی های CreateTicketRequest شبیه به TicketInfo می باشد.

مقایسه RESTFull و gRPC

معمولا برای نوشتن api های که از سمت سرور می آید از معماری RESTFull استفاده می شود که از طریق پروتکل HTTP عملیات ارسال و دریافت اطلاعات انجام می شود در واقعا gRPC هم خیلی به شبیه به آن می باشد که با این تفاوت که بر روی پروتکل HTTP2 دیتا را ارسال و دریافت می کند و هم ایمن تر و سریع تر می باشد، در ادامه یکسری از مزیت های آن را مطرح می کنیم .

این پروتکل برای ارسال و دریافت اطلاعات به صورت پیش فرض برای سریالایز کردن اطلاعات از ProtocolBuffer استفاده می کنه که توسط گوگل نوشته شده.

فرمت اطلاعاتی که داخل ProtocolBuffer هست به صورت باینری می باشد، به معنی که حجم اطلاعات کاهش پیدا می کند به این معنی که اطلاعات قبل از ارسال فشرده میشن و حجم کمتری از ترافیک شبکه را اشغال میکنن.

یکی از خوبی های دیگ gRPC اینکه که schema تعریف شده در سمت سرور توابع ورودی و خروجی را برای کلاینت مشخص می کند. با این کار میتونیم بفهمیم چه متدهای با چه ورودی و خروجی در سمت سرور وجود دارد.

قابلیت خوب دیگ اینکه Bi-directional Streaming برای جریانی از داده ها استفاده میکنه، به این معنی که ارسال و دریافت اطلاعات به صورت همه زمان صورت می گیرد پس برای کار با داده های مثل فیلم بسیار مناسب است.

اخرین مورد که قبلا هم اشاره کردیم اینکه بر روی پروتکل HTTP2 ارسال و دریافت اطلاعات انجام میدهد که خیلی امن و سریع می باشد.

در نهایت این فریم ورک توسط گوگل نوشته شده است و توسط شرکت های بسیار مطرح که در پایین اشاره می شود مورد استفاده قرار گرفته است.

اگر نیاز به تست درخواست های RPC خود داشتید میتوانید نرم افزار BloomRPC را نصب کنید.

توجه داشته باشید که تمام قطع کدهای که در این مقاله اورده شد در فایلی به نام support.proto قرار گرفته است، امیدوارم این مقاله برایتان مفید باشد.