gRPC در مقابل REST: شروع به کار با بهترین پروتکل API


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

بسیاری از فن‌آوری‌های استاندارد نیازهای ارتباطی بین سرویس‌های سیستم‌های توزیع‌شده، مانند REST، SOAP، GraphQL یا gRPC را برطرف می‌کنند. در حالی که REST یک رویکرد مطلوب است، gRPC یک رقیب شایسته است که عملکرد بالا، قراردادهای تایپ شده و ابزار عالی را ارائه می دهد.

نمای کلی REST

انتقال حالت نمایشی (REST) ​​وسیله ای برای بازیابی یا دستکاری داده های یک سرویس است. یک REST API به طور کلی بر روی پروتکل HTTP ساخته شده است که از یک URI برای انتخاب یک منبع و یک فعل HTTP (به عنوان مثال، GET، PUT، POST) برای انتخاب عملیات مورد نظر استفاده می کند. بدنه‌های درخواست و پاسخ حاوی داده‌هایی هستند که مختص عملیات هستند، در حالی که هدرهای آن‌ها ابرداده را ارائه می‌کنند. برای نشان دادن، اجازه دهید به یک مثال ساده از بازیابی یک محصول از طریق REST API نگاه کنیم.

در اینجا، ما یک منبع محصول با شناسه درخواست می کنیم 11 و API را هدایت کنید تا در قالب JSON پاسخ دهد:

GET /products/11 HTTP/1.1
Accept: application/json

با توجه به این درخواست، پاسخ ما (سرصفحه های نامربوط حذف شده اند) ممکن است به شکل زیر باشد:

HTTP/1.1 200 OK
Content-Type: application/json

{ id: 11, name: "Purple Bowtie", sku: "purbow", price: { amount: 100, currencyCode: "USD"  }  }

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

بررسی اجمالی gRPC

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

gRPC که بر روی HTTP/2 ساخته شده است، از ویژگی هایی مانند جریان دو طرفه و امنیت لایه حمل و نقل داخلی (TLS) بهره می برد. gRPC ارتباط کارآمدتری را از طریق بارهای باینری سریالی امکان پذیر می کند. استفاده می کند بافرهای پروتکل به طور پیش فرض به عنوان مکانیزم آن برای سریال سازی داده های ساخت یافته، مشابه استفاده REST از JSON است.

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

  • زبان تعریف قرارداد موجود در .proto فایل ها (ما از proto3، آخرین مشخصات زبان بافر پروتکل پیروی می کنیم.)
  • کد تابع دسترسی ایجاد شد
  • کتابخانه های زمان اجرا مخصوص زبان

عملکردهای راه دوری که در یک سرویس در دسترس هستند (تعریف شده در a .proto فایل) در داخل گره سرویس در فایل بافر پروتکل فهرست شده اند. به عنوان توسعه دهندگان، ما می توانیم این توابع و پارامترهای آنها را با استفاده از سیستم نوع غنی بافرهای پروتکل تعریف کنیم. این سیستم از انواع مختلف عددی و تاریخ، لیست ها، فرهنگ لغت ها و nullable ها برای تعریف پیام های ورودی و خروجی ما پشتیبانی می کند.

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

این مثال .proto فایل تابعی را برای بازگرداندن ورودی محصول با داشتن یک شناسه تعریف می کند:

syntax = "proto3";

package product;

service ProductCatalog {
    rpc GetProductDetails (ProductDetailsRequest) returns (ProductDetailsReply);
}

message ProductDetailsRequest {
    int32 id = 1;
}

message ProductDetailsReply {
    int32 id = 1;
    string name = 2;
    string sku = 3;
    Price price = 4;
}

message Price {
    float amount = 1;
    string currencyCode = 2;
}
قطعه 1: ProductCatalog تعریف خدمات

تایپ دقیق و ترتیب فیلدهای proto3 باعث می‌شود که سریال‌زدایی پیام به‌طور قابل‌توجهی نسبت به تجزیه JSON مالیات کمتری داشته باشد.

مقایسه REST در مقابل gRPC

برای جمع بندی، مهمترین نکات در مقایسه REST در مقابل gRPC عبارتند از:

باقی مانده gRPC
کراس پلت فرم آره آره
فرمت پیام سفارشی اما به طور کلی JSON یا XML بافرهای پروتکل
پیام اندازه بار متوسط ​​/ بزرگ کم اهمیت
پیچیدگی پردازش بالاتر (تجزیه متن) پایین (ساختار دوتایی به خوبی تعریف شده)
پشتیبانی مرورگر بله (بومی) بله (از طریق gRPC-Web)

در مواردی که قراردادهای کمتر سختگیرانه و اضافه شدن مکرر به محموله مورد انتظار است، JSON و REST مناسب هستند. وقتی قراردادها بیشتر ثابت می مانند و سرعت از اهمیت بالایی برخوردار است، gRPC به طور کلی برنده می شود. در اکثر پروژه‌هایی که من روی آنها کار کرده‌ام، gRPC سبک‌تر و کارآمدتر از REST است.

پیاده سازی سرویس gRPC

بیایید یک پروژه کارآمد بسازیم تا بررسی کنیم که پذیرش gRPC چقدر ساده است.

ایجاد پروژه API

برای شروع، ما یک پروژه .NET 6 در Visual Studio 2022 Community Edition (VS) ایجاد خواهیم کرد. را انتخاب خواهیم کرد سرویس ASP.NET Core gRPC الگو و نام هر دو پروژه (ما استفاده خواهیم کرد InventoryAPI) و اولین راه حل ما در آن (Inventory).

آ

حال، بیایید انتخاب کنیم.NET 6.0 (پشتیبانی بلند مدت) گزینه ای برای چارچوب ما:

گفتگوی اطلاعات اضافی در Visual Studio 2022. در این صفحه ما انتخاب کردیم

تعریف خدمات محصول ما

اکنون که پروژه را ایجاد کرده‌ایم، VS نمونه سرویس تعریف نمونه اولیه gRPC را به نام نمایش می‌دهد Greeter. ما تغییر کاربری خواهیم داد Greeterفایل های اصلی مطابق با نیازهای ما.

  • برای ایجاد قرارداد خود، محتویات را جایگزین می کنیم greet.proto با قطعه 1، تغییر نام فایل product.proto.
  • برای ایجاد سرویس خود، محتویات را جایگزین می کنیم GreeterService.cs فایل با قطعه 2، تغییر نام فایل ProductCatalogService.cs.
using Grpc.Core;
using Product;

namespace InventoryAPI.Services
{
    public class ProductCatalogService : ProductCatalog.ProductCatalogBase
    {
        public override Task<ProductDetailsReply> GetProductDetails(
            ProductDetailsRequest request, ServerCallContext context)
        {
            return Task.FromResult(new ProductDetailsReply
            {
                Id = request.Id,
                Name = "Purple Bowtie",
                Sku = "purbow",
                Price = new Price
                {
                    Amount = 100,
                    CurrencyCode = "USD"
                }
            });
        }
    }
}
قطعه 2: ProductCatalogService

این سرویس اکنون یک محصول سخت کد شده را برمی گرداند. برای اینکه سرویس کار کند، فقط باید ثبت نام سرویس را در آن تغییر دهیم Program.cs برای ارجاع به نام سرویس جدید. در مورد ما، ما تغییر نام می دهیم app.MapGrpcService<GreeterService>(); به app.MapGrpcService<ProductCatalogService>(); تا API جدید ما قابل اجرا شود.

هشدار منصفانه: تست پروتکل استاندارد شما نیست

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

ایجاد مشتری

برای آزمایش سرویس خود، بیایید از الگوی اصلی برنامه کنسول VS استفاده کنیم و یک کلاینت gRPC برای فراخوانی API ایجاد کنیم. اسمم را گذاشتم InventoryApp.

برای مصلحت، اجازه دهید یک مسیر فایل نسبی را ارجاع دهیم که از طریق آن قرارداد خود را به اشتراک بگذاریم. ما مرجع را به صورت دستی به آن اضافه می کنیم .csproj فایل. سپس، مسیر را به روز می کنیم و تنظیم می کنیم Client حالت توجه: توصیه می کنم قبل از استفاده از ارجاع نسبی با ساختار پوشه محلی خود آشنا شوید و به آن اطمینان داشته باشید.

اینجا هستند .proto منابع، همانطور که در فایل های پروژه سرویس و مشتری ظاهر می شوند:

فایل پروژه خدمات
(کد برای کپی در فایل پروژه مشتری)
فایل پروژه مشتری
(پس از چسباندن و ویرایش)
  <ItemGroup>
    <Content Update="Protos\product.proto" GrpcServices="Server" />
  </ItemGroup>
  <ItemGroup>
    <Protobuf Include="..\InventoryAPI\Protos\product.proto" GrpcServices="Client" />
  </ItemGroup>

اکنون، برای تماس با سرویس ما، محتویات را جایگزین می کنیم Program.cs. کد ما تعدادی از اهداف را انجام می دهد:

  1. کانالی ایجاد کنید که مکان نقطه پایانی سرویس را نشان دهد (پورت ممکن است متفاوت باشد، بنابراین با آن مشورت کنید launchsettings.json فایل برای مقدار واقعی).
  2. شی مشتری را ایجاد کنید.
  3. یک درخواست ساده بسازید
  4. درخواست را ارسال کنید.
using System.Text.Json;
using Grpc.Net.Client;
using Product;

var channel = GrpcChannel.ForAddress("
var client = new ProductCatalog.ProductCatalogClient(channel);

var request = new ProductDetailsRequest
{
    Id = 1
};

var response = await client.GetProductDetailsAsync(request);

Console.WriteLine(JsonSerializer.Serialize(response, new JsonSerializerOptions
{
    WriteIndented = true
}));
Console.ReadKey();
قطعه 3: جدید Program.cs

آماده شدن برای راه اندازی

برای آزمایش کد خود، در VS، روی راه حل راست کلیک کرده و انتخاب می کنیم راه اندازی پروژه های راه اندازی. در گفتگوی صفحات ویژگی راه حل، ما:

  • دکمه رادیویی کناری را انتخاب کنید چندین پروژه استارت آپیو در منوی کشویی Action، هر دو پروژه را تنظیم کنید (InventoryAPI و InventoryApp) به شروع کنید.
  • کلیک خوب.

اکنون می توانیم راه حل را با کلیک کردن شروع کنیم شروع کنید در نوار ابزار VS (یا با فشار دادن F5 کلید). دو پنجره کنسول جدید نمایش داده می شود: یکی برای اینکه به ما بگوید سرویس در حال گوش دادن است، دیگری برای نمایش جزئیات محصول بازیابی شده.

به اشتراک گذاری قرارداد gRPC

حال بیایید از روش دیگری برای اتصال مشتری gRPC به تعریف سرویس خود استفاده کنیم. قابل دسترس ترین راه حل اشتراک قرارداد برای مشتری این است که تعاریف خود را از طریق URL در دسترس قرار دهیم. گزینه‌های دیگر یا بسیار شکننده هستند (فایل از طریق یک مسیر به اشتراک گذاشته می‌شود) یا نیاز به تلاش بیشتری دارند (قرارداد از طریق یک بسته بومی به اشتراک گذاشته می‌شود). اشتراک گذاری از طریق URL (همانطور که SOAP و Swagger/OpenAPI انجام می دهند) انعطاف پذیر است و به کد کمتری نیاز دارد.

برای شروع، را بساز .proto فایل موجود به عنوان محتوای ثابت. ما کد خود را به‌صورت دستی به‌روزرسانی می‌کنیم زیرا رابط کاربری در اکشن ساخت روی «Protobuf Compiler» تنظیم شده است. این تغییر کامپایلر را هدایت می کند تا آن را کپی کند .proto فایل بنابراین ممکن است از یک آدرس وب ارائه شود. اگر این تنظیمات از طریق VS UI تغییر می کرد، بیلد خراب می شد. پس اولین قدم ما این است که قطعه 4 را به آن اضافه کنیم InventoryAPI.csproj فایل:

  <ItemGroup>
    <Content Update="Protos\product.proto">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <Content Include="Protos\product.proto" CopyToPublishDirectory="PreserveNewest" />
  </ItemGroup>
قطعه 4: کد برای افزودن به InventoryAPI فایل پروژه خدمات

در مرحله بعد، کد را در قطعه 5 در بالای قسمت وارد می کنیم ProductCatalogService.cs فایل برای تنظیم یک نقطه پایانی برای بازگشت ما .proto فایل:

using System.Net.Mime;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
قطعه 5: Namespace واردات

و اکنون، قطعه 6 را درست قبل اضافه می کنیم app.Run()، همچنین در ProductCatalogService.cs فایل:

var provider = new FileExtensionContentTypeProvider();
provider.Mappings.Clear();
provider.Mappings[".proto"] = MediaTypeNames.Text.Plain;
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(Path.Combine(app.Environment.ContentRootPath, "Protos")),
    RequestPath = "/proto",
    ContentTypeProvider = provider
});

app.UseRouting();
قطعه 6: کد برای ساخت .proto فایل های قابل دسترسی از طریق API

با اضافه شدن Snippets 4-6، محتویات .proto فایل باید در مرورگر قابل مشاهده باشد.

یک مشتری آزمایشی جدید

اکنون می‌خواهیم یک کلاینت کنسول جدید ایجاد کنیم که با VS’s Dependency Wizard به سرور موجود خود متصل می‌شویم. مسئله این است که این جادوگر HTTP/2 صحبت نمی کند. بنابراین، باید سرور خود را طوری تنظیم کنیم که از طریق HTTP/1 صحبت کند و سرور را راه اندازی کند. با سرور ما در حال حاضر .proto فایل موجود است، ما می توانیم یک کلاینت آزمایشی جدید بسازیم که از طریق جادوگر gRPC به سرور ما متصل شود.

  1. برای تغییر سرور خود به صحبت از طریق HTTP/1، ما خود را ویرایش می کنیم appsettings.json فایل JSON:
    1. تنظیم Protocol فیلد (در مسیر پیدا شد Kestrel.EndpointDefaults.Protocols) خواندن Https.
    2. فایل را ذخیره کنید.
  2. برای اینکه مشتری جدید ما این را بخواند proto اطلاعات، سرور باید در حال اجرا باشد. در اصل، ما هم کلاینت قبلی و هم سرورمان را از گفتگوی Set Startup Projects VS شروع کردیم. راه حل سرور را طوری تنظیم کنید که فقط پروژه سرور شروع شود، سپس راه حل را شروع کنید. (اکنون که نسخه HTTP را اصلاح کرده ایم، کلاینت قدیمی ما دیگر نمی تواند با سرور ارتباط برقرار کند.)
  3. سپس، کلاینت آزمایشی جدید را ایجاد کنید. نمونه دیگری از VS را راه اندازی کنید. ما مراحل را همانطور که در قسمت توضیح داده شده تکرار می کنیم ایجاد پروژه API بخش، اما این بار، ما را انتخاب می کنیم برنامه کنسول قالب. ما پروژه و راه حل خود را نام می بریم InventoryAppConnected.
  4. با ایجاد شاسی کلاینت، به سرور gRPC خود متصل خواهیم شد. پروژه جدید را در VS Solution Explorer گسترش دهید.
    1. کلیک راست وابستگی ها و در منوی زمینه، را انتخاب کنید مدیریت خدمات متصل.
    2. در تب Connected Services، کلیک کنید یک مرجع خدمات اضافه کنید و انتخاب کنید gRPC.
    3. در گفتگوی افزودن مرجع مرجع، گزینه را انتخاب کنید URL گزینه و ورودی http نسخه آدرس سرویس (به یاد داشته باشید که شماره پورت تولید شده به طور تصادفی را از آن بگیرید launchsettings.json).
    4. کلیک پایان برای اضافه کردن یک مرجع سرویس که به راحتی قابل نگهداری باشد.

احساس رایگان برای بررسی کار خود را در برابر کد نمونه برای این مثال. از آنجایی که VS در زیر کاپوت همان کلاینت مورد استفاده ما در اولین دور آزمایش را ایجاد کرده است، می‌توانیم از محتویات آن استفاده مجدد کنیم. Program.cs فایل از سرویس قبلی کلمه به کلمه.

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

نامزد پروژه بعدی شما: gRPC

پیاده سازی gRPC ما نگاهی اجمالی به مزایای استفاده از gRPC ارائه می دهد. REST و gRPC هر کدام بسته به نوع قرارداد موارد استفاده ایده آل خود را دارند. با این حال، وقتی هر دو گزینه مناسب هستند، من شما را تشویق می‌کنم که gRPC را امتحان کنید – این شما را در آینده APIها جلوتر از منحنی قرار می‌دهد.



منبع

Matthew Newman

Matthew Newman Matthew has over 15 years of experience in database management and software development, with a strong focus on full-stack web applications. He specializes in Django and Vue.js with expertise deploying to both server and serverless environments on AWS. He also works with relational databases and large datasets
[ Back To Top ]