پروتوباف، یک راهنمای عملی (Python . Go)
با گسترش معماریهای میکروسرویسی، نیاز به انتقال متعدد داده بین سرویسهای ریز و درست خیلی پررنگ شده است. گاهی یک ریکوئست ساده از از سمت کاربر، منتهی به صد ها رکوئست درون-سیستمی در یک محصول میشود. برای آشنایی بیشتر با این چالش و یکی از روزآمد ترین راه حلهای آن، شما را به خواندن ادامه متن دعوت میکنم.
انکودینگ چیست؟
به عمل تبدیل یک ساختمان داده به آرایه بایت انکد encode کردن میگویند. این عمل باید برگشت پذیر باشد. حالا چرا encoding این قدر مهم است؟ چون هر زمان قرار باشد دادهای از طریق شبکه جابجا شود یا در جایی ذخیره شود، لازم است به شیوهای انکد شود. ممکن است زبان و پلتفرم مبدا و مقصد / نویسنده و خواننده کاملا متفاوت باشند. لذا encoding های معروف، استاندارد شده هستند و در زبانهای برنامه نویسی مختلف پیادهسازی شدهاند.
در این بین، برخی encoding ها توسط انسان قابل خوانده شدن هستند. مثل json. در زیر نمونهای از یک ساختمان داده که به شکل جیسون encode شده میبینید.
امروزه اکثر زبانهای برنامه نویسی و حتی فریمورکهای سخت افزاری قابلیت encode/decode کرده جیسون را دارا هستند.
پروتوباف proto
انکد شدهی protobuf، بطور کامل قابل خواندهشدن توسط انسان نیست. اما در عوض این کاستی، سرعت encode/decode و نیز حجم بسیار پایینتر را به ارمغان میآورد. پیادهسازیهای encoder/decoder پروتو برای بیش از ۱۰ زبان برنامهنویسی پرکاربرد، از جمله گو و پایتون، توسط گوگل ارائه میشود و کاملا اپنسورس هستند.
اکنون به این شکل میتوانید کامپایلر protoc را نصب کنید:
sudo apt install protobuf-compiler
go get google.golang.org/protobuf/cmd/protoc-gen-go \
google.golang.org/grpc/cmd/protoc-gen-go-grpc
پروتوی پروفایل یوزر و کامپایل آن
حال یک نمونه فایل پروتو را با هم مشاهده میکنیم. در اینجا ساختار دادهای که میخواهیم ارسال/ذخیره، یا بطور کلی encode کنیم، آورده شده است.
اکنون این فایل پروتو را با کامپایلر protoc کامپایل میکنیم:
$ protoc --go_out=. --go_opt=paths=source_relative profile.proto
خروجی این عمل یک فایل autogen به زبان گو هست، که امکانات لازم برای encode/decode را فراهم میآورد. در فایل ساخته شده، موارد زیادی دیده میشود. از جمله آنها، یک struct، شامل فیلدهای متناظر در Message تعریف شده در فایل پروتو است:
به طریق اولی همین کار را برای پایتون هم انجام میدهیم. اما متاسفانه کدهای generate شده در پایتون، به اندازه گو خوانا نیستند. این بدلیل تفاوت در مباحثی مثل typing در این زبان و پیشفرضهای پروتو است.
لازم بود تا فایل پروتو را برای پایتون هم کامپایل کنم. چون در نظر داریم یک نمونه پروفایل را با یک کد Go encode کنیم و نتایج binary شده را در یک فایل بنویسیم. سپس با یک اسکریپت پایتون، همان فایل را بخوانیم و decode کنیم. انتظار میرود دادهها در هر دو سو یکسان باشد.
اما پیش از این کار؛ یک تفاوت مهم که تا الان بین پروتو و encodingای مثل json (که اول متن بهش اشاره کردم) دیدیم را نام ببرید؟
در پروتو باید از قبل مشخص کنیم که چه فیلدهایی داریم و نوع (type) هر فیلد دقیقاً چیست (هشدار: این جمله دقیق نیست). ولی برای json اینطور نیست (حتی این جمله هم دقیق نیست).
انکد کردن یک مسیج پروتو با Go
در اینجا یک کد نمونه به زبان گو داریم که در آن یک پروفایل مثالی میسازیم و آنرا encode شده درون یک فایل ذخیره میکنیم.
دیکد کردن مسیج انکد شده در پایتون
حالا که اطلاعات پروفایل را encodeشده ذخیره کردیم، کافیست با یک اسکریپت پایتون فایل را باز کنیم و بوسیله Message مربوطه، که در اینجا UserProfile است، محتوایات را decode کنیم:
بنچمارک عمل decode در دو زبان Go و Python
از اینجا به بعد، در نظر دارم از فرآیندهای decode در این دو زبان، بنچمارک بگیرم. با همین فایل باینری ساده Amir_Ehsandar.pb کار را انجام میدیم. برای گو تابع زیر را نوشتم که decode را انجام دهد. نتایج زیر را کسب کردیم:
سرعت خیلی بالایی در دیکد کردن با زبان گو مشاهده شد. حدود ۴.۵ میکروثانیه. حال این کار را در زبان پایتون انجام بدهیم تا بتوانیم نتایج را با هم مقایسه کنیم. در زیر کد مربوطه و نتایج آن برای زبان پایتون آمده است:
بنابراین طبق مشاهدات، بنظر میرسد هر بار decode کردن این پروتوی خاص ما، در حدود ۳۲ میکروثانیه طول میکشد. این عدد نزدیک ۷ برابر زمان سپری شده در گو است.
مطلبی دیگر از این انتشارات
جانشین دستساز انسان برای فرایند تفکر و یافتن روش حل مسائل یا یادگیری ماشین؟!؟
مطلبی دیگر از این انتشارات
چرا به Callback در جاوا اسکریپت نیاز داریم.
مطلبی دیگر از این انتشارات
بازی ساز شوید؛ با روش و اصول درست شروع کنید