عرفان
عرفان
خواندن ۶ دقیقه·۶ سال پیش

آموزش صفر تا ۵۰ پروتوبافر

اگر قبلا درمورد HTTP/2 نخوندید بهتره اول این مطلب رو بخونید.

همچنین ازتون انتظار میره درمورد API و همچنین رست‌فول بدونید، اینجا میتونید بیشتر درموردشون بخونید.

خیلی خب، حالا که درمورد HTTP/2 و انواع API میدونید، باید اینو متوجه شده باشید که استانداردهای فعلی با HTTP/2 سازگاری ندارن (یا بهتره بگم از ویژگیای HTTP/2 استفاده نمی‌کنند). برای مثال در استانداردهای گذشته کاربر یک استرینگ (در قالب جیسون، CSV ،XML یا...) به سمت سرور ارسال میکنه و سرور هم یک استرینگ به کاربر برمی‌گردونه، برای هر ریکوئست یک ارتباط TCP برقرار میشه و...

اگر می‌خواید بدونید پروتوباف چیه بهتره اول انواع ساختار مرسوم دیتا چیه، در مرحله اول CSV وجود داشت که یک سری ستون تعریف میکردید و برای اون ستون ها ردیف اضافه می‌کردید.

میشد راحت ساختش، راحت خوندش، راحت درکش کرد ولی نمیشد نوع دیتاهارو تعریف کرد، وقتی توی دیتاتون ویرگول داشته باشید کارِتون خیلی سخت میشه، نمی‌تونید مطمئن باشید دارید دیتارو توی ستون درست ذخیره می‌کنید یا نه.

در مرحله بعد XML داشتیم که فکر نمیکنم دیگه هیچ‌جایی استفاده بشه پس توضیح نمیدم ولی توی وب خیلی کاربرد داشت تا اینکه جی‌سون معرفی شد.

جی‌سون هر نوع دیتایی تو خودش جا میداد (آرایه، آبجکت، تو در تو)، تو اپلیکیشن‌های وب خیلی محبوب بود، با تمام زبان‌های برنامه نویسی سازگار بود، به راحتی توی شبکه انتقال داده میشد. ولی چندتایی مشکل داشت، برای مثال الگویی نداشت و توی هر ریکوئست میتونست شکل متفاوتی داشته باشه، چون کلید‌هارو هر دفعه تکرار میکنه حجم بزرگتری داشت، همچنین هیچ داکیومنت یا کامنتی همراشون ندارن.


و اما پروتوباف (protocol buffers) در سال ۲۰۰۸ توسط گوگل ایجاد شد (که در اون تاریخ SPDY نام داشت)، یک استاندارده که بیشتر برای ارتباط داخلی (ارتباط سرویس‌ها با یکدیگر) استفاده میشه اما این روزها دارن تلاش میکنند که این استاندارد سمت کاربر هم قابل استفاده باشه که فعلا در اندروید امکان پذیره و نمونه‌هایی هم برای مرورگر آماده شده، به علت باینری بودن قابل استفاده در HTTP/2 است از همین جهت سرعت و پرفورمنس خیلی بهتری داره.

نمونه‌ای از یک فایل پروتوباف
نمونه‌ای از یک فایل پروتوباف

پروتوباف همچین شکلی داره، یک فایل تکست با پسوند proto که به سادگی برای انسان قابل خوندن و درکه، در خط اول ورژن پروتوباف رو مشخص میکنیم، در خط سه یک مسیج تعریف میکنیم که یک فیلد از جنس int با تگ ۱ و یک فیلد از جنس استرینگ با تگ ۲ و یک فیلد از جنس بولین با تگ ۳ داریم.

مزیت‌های پروتوباف: تایپ دیتاها تعریف شدس، دیتاها بصورت اتوماتیک کمپرس میشن، تمام مسیج‌های ارسالی و دریافتی ساختار (schema) دارن (توی فایل proto تعریف میشن و بعدا توسط جنریتور کد مخصوص زبان شما جنریت میشه)، داکیومنت میتونه توی فایل proto نوشته بشه، دیتاها میتونه توی هر زبان برنامه نویسی‌ای خونده بشه، ساختار (schema) میتونه هرزمانی توسعه پیدا کنه، حدود ۷ برابر سریعتر از جیسونه، کدها بصورت اتوماتیک برای زبان شما جنریت میشه.

و معایب پروتوباف: ممکنه کد جنریتورش بعضی از زبانها رو ساپورت نکنه، نمی‌تونید دیتاهارو موقع انتقال با تکست ادیتور باز کنید (چون باینتریه).


تایپ‌ها:

‌اعداد صحیح: می‌تونید از int32 و int64 برای اعداد صحیح استفاده کنید.

اعداد اعشاری: می‌تونید از float32 یا float64 استفاده کنید.

رشته: برای تعریف یک رشته میتونید از نوع string استفاده کنید، طول این متغیر خودکار تعین میشه، پس نگرانی بابت بزرگ بودن مقدار نداشته باشید، اینکد فایل باید UTF-8 یا 7-bit ASCII باشه.

باینری: برای تعریف آرایه‌ای از بایت‌ها از bytes استفاده می‌کنیم، به شما بستگی داره چی چیزی میخواید توش ذخیره کنید، میتونه یک عکس کوچیک یا هر چیز باینری دیگه‌ای باشه.

میتونید انواع تایپ‌های دیگه‌رو از داکیومنت اصلی بخونید.

https://gist.github.com/ErFUN-KH/d660d1ae9ae95a0c8101f055fc49b02c

تگ‌ها

در پروتوبافر اسم فیلدها مهم نیستند (البته منظورمون بعد از بیلد هست، وگرنه موقع دولوپ خیلی هم مهمه!)، چیزی که مهمه تگ‌ها هستند، منظورمون همون عدادی هستند که در انتهای هر فیلد به ترتیب ۱ ۲ ۳ می‌نویسیم، در پروداکشن برای شناسایی فیلدها از اسمشون استفاده نمیشه بلکه از تگشون استفاده میشه، پس هر فیلد باید یک تگ منحصر به فرد داشته باشه، کوچیکترین تگی که میتونید استفاده کنید ۱ هست و بزرگترین ۵۳۶،۸۷۰،۹۱۱ هستش، اگر فکر میکنید این مقدار براتون کافی نیست احتمالا برنامه‌تون منطق اشتباهی داره، همچنین شما نمیتونید از تگهای ۱۹۰۰۰ تا ۱۹۹۹۹ استفاده کنید، این تگها توسط گوگل برای استفاده‌های خاص رزرو شدن.

چیزی که لازمه بدونید تگ‌های ۱ تا ۱۵ فقط یک بایت فضا اشغال میکنند و تگ‌های ۱۶ تا ۲۰۴۷ دو بایت فضا اشغال می‌کنند.


آرایه‌ها

آرایه‌ها در پروتوبافر با عنوان repeated شناخته میشن، برای مثال شاید بخوایم برای پروفایلی که داشتیم چندین شماره تلفن درنظر بگیریم، پس فایل رو به این صورت تغییر میدیم:

https://gist.github.com/ErFUN-KH/b702a01f149cc981e3e3d11744f7bae1

همینطور که میبینید فقط کافیه کلمه repeated قبل از تایپ فیلدمون اضافه کنیم.


کامنت

شما می‌تونید کامنتاتون به فایل پروتوباف اضافه کنید تا نیازی به نوشتن داکیومنت ضافه مثل سرویس‌های رست‌فول نباشید، شما فقط فایل‌های پروتو در اختیار بقیه دولوپرها قرار میدید و اونها سرویس مورد نظر رو کال می‌کنند.

https://gist.github.com/ErFUN-KH/3c31c711685c924cef9423ef000f2859

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


مقادیر پیش‌فرض

چیزی که خیلی مهمه تا بدونید مقدار پیش فرض در پروتوبافه، تمام فیلدها مقدار پیش‌فرض دارن، برای بولین مقدار false هستش، برای نامبر عدد ۰ هستش، برای استرینگ یک رشته خالی، برای بایت یک رشته بایت خالی، برای ای‌نام (enum) اولین مقدار لیست، برای آرایه یک آرایه خالی.

تمام فیلدهایی که بعد از اجرای برنامه مقدار دهی نشن، شناخته نشن و... مقدار پیش‌فرض رو میگیرن.


ای‌نام - enum

اگر با ای‌نام آشنا نیستید باید بگم یک لیست از مقدایره، همونطور که بولین یک لیست دوتایی از true و false هستش، ای‌نام میتونه یک لیست چندتایی از هر تایپی باشه.

اگر فراموش کردید باید دوباره بگم مقدار اول ای‌نام میشه مقدار پیش‌فرض، نباید اینو فراموش کنید.

ای‌نام باید از تگ ۰ شروع بشه که مقدار پیش‌فرض هستش.

پس میریم که رنگ چشم کاربر توسط ای‌نام تعریف کنیم:

https://gist.github.com/ErFUN-KH/594834635e9c056863422a6c5e90076a

فکر میکنم کد خیلی سادس و توضیح بیشتری لازم نداره، یک ای‌نام تعریف کردیم و در پایین ازش برای رنگ چشم استفاده کردیم.


مسیج‌های تو در تو

علاوه بر ای‌نام شما میتونید از مسیج‌های دیگه داخل مسیج اصلی‌تون استفاده کنید، اینکار خیلی سادس، تو نمونه پایین تاریخ تولد به پروفایل کاربر اضافه میکنیم:

https://gist.github.com/ErFUN-KH/ec9a0c1685ffafe00a5093b7b7235f9c

تو خط ۳۴ میبینم تاریخ تولد رو تعریف کردیم که از جنس Date هست، که خود دیت یک مسیجه که شامل سال، ماه و روز از جنس int هستش که در خط ۳۷ تعریفش کردیم.

همیشه می‌تونید داخل مسیجاتون یک مسیج دیگه رو استفاده کنید.


ایمپورت کردن فایل‌های proto

شاید شما کلی فایل پروتو داشته باشید و نخواید مسیج Date همه جا تعریف کنید، بلکه توی یک فایل تعریف کنید و جاهای دیگه ایمپورت کنید، برای این کار به این صورت اقدام میکنید:

https://gist.github.com/ErFUN-KH/34b750e736cfcc330f391c760d8fdeb7

همینطور که توی خط ۴ فایل پروفایل میبینید فایل date.proto ایمپورت کردیم، تنها نکته‌ای که هست شما باید آدرس کامل فایل رو از روت پروژه وارد کنید، شاید فایلها کنار هم باشن ولی نمیتونید فقط اسم فایل رو وارد کنید، در اینصورت موقع جنریت کردن کد حتما به خطا می‌خورید.


پکیج‌ها

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

https://gist.github.com/ErFUN-KH/8f4027095a71dedbf5674194d9d32bcd

تو کد بالا برای هر فایل یک package name تعریف کردیم، خیلی ساده بود، تنها نکته اینه وقتی تو فایل پروفایل داشتیم Date تعریف میکردیم اول پیکج‌نیم رو نوشتیم و بعد...



فکر میکنم ۵۰٪ مسئله روشن شده، توی پست بعدی ۵۰٪ دیگه رو توضیح میدم.


https://virgool.io/@erfun/%D9%BE%D8%B1%D9%88%D8%AA%D9%88%D8%A8%D8%A7%D9%81-%D9%82%D8%B3%D9%85%D8%AA-%D8%AF%D9%88%D9%85-cc7sre2bvnwb
پروتوبافprotobufprotocol buffersgrpcmicroservices
یه دولوپر که سعی می‌کنه عمیق و کم هزینه باشه، از هرچیزی که بلدم می‌نویسم تا مطمئن‌شم درست یادش گرفتم.
شاید از این پست‌ها خوشتان بیاید