عملکرد بهترین شیوه ها با GRPC

ساخت وبلاگ

GRPC برای خدمات با کارایی بالا طراحی شده است. این سند نحوه به دست آوردن بهترین عملکرد ممکن از GRPC را توضیح می دهد.

استفاده مجدد از کانال های GRPC

در هنگام برقراری تماس GRPC باید از یک کانال GRPC استفاده شود. استفاده مجدد از یک کانال اجازه می دهد تا تماس ها از طریق اتصال HTTP/2 موجود چند برابر شوند.

اگر یک کانال جدید برای هر تماس GRPC ایجاد شود ، مقدار زمان لازم برای تکمیل می تواند به میزان قابل توجهی افزایش یابد. هر تماس برای ایجاد یک اتصال جدید HTTP/2 به چندین سفر به دور شبکه بین مشتری و سرور نیاز دارد:

  1. باز کردن سوکت
  2. ایجاد اتصال TCP
  3. مذاکره TLS
  4. شروع اتصال HTTP/2
  5. برقراری تماس GRPC

کانال ها برای به اشتراک گذاشتن و استفاده مجدد بین تماس های GRPC ایمن هستند:

  • مشتریان GRPC با کانال ها ایجاد می شوند. مشتری های GRPC اشیاء سبک وزن هستند و نیازی به ذخیره یا استفاده مجدد ندارند.
  • چندین مشتری GRPC را می توان از یک کانال ، از جمله انواع مختلف مشتری ایجاد کرد.
  • یک کانال و مشتری های ایجاد شده از کانال می توانند با اطمینان از چندین موضوع استفاده شوند.
  • مشتریانی که از کانال ایجاد شده اند می توانند چندین تماس همزمان برقرار کنند.

کارخانه مشتری GRPC یک روش متمرکز برای پیکربندی کانال ها ارائه می دهد. به طور خودکار از کانال های زیرین استفاده می کند. برای اطلاعات بیشتر ، به ادغام کارخانه مشتری GRPC در . NET مراجعه کنید.

همزمانی اتصال

اتصالات HTTP/2 به طور معمول در تعداد حداکثر جریان های همزمان (درخواست های فعال HTTP) در یک زمان محدودیت دارند. به طور پیش فرض ، بیشتر سرورها این حد را روی 100 جریان همزمان قرار می دهند.

یک کانال GRPC از یک اتصال HTTP/2 استفاده می کند و تماس های همزمان در این اتصال چند برابر می شوند. هنگامی که تعداد تماس های فعال به حد جریان اتصال می رسد ، تماس های اضافی در مشتری صف می شوند. تماس های صف انتظار برای تکمیل تماس های فعال قبل از ارسال آنها. برنامه های با بار زیاد یا تماس های جریان طولانی در حال اجرا GRPC ، می توانند مشکلات عملکرد ناشی از تماس های صف را به دلیل این حد مشاهده کنند.

. NET 5 ویژگی Socketshttphandler. enablemultiplehtp2coections را معرفی می کند. هنگامی که روی True تنظیم شد ، اتصالات اضافی HTTP/2 توسط یک کانال ایجاد می شود که به حد مجاز جریان همزمان رسید. هنگامی که یک grpcchael ایجاد می شود Socketshttphandler داخلی آن به طور خودکار پیکربندی می شود تا اتصالات اضافی HTTP/2 ایجاد کند. اگر یک برنامه کنترل کننده خود را پیکربندی می کند ، تنظیمات enablemultiplehttp2coections را به True تنظیم کنید:

var chael = grpcchael. foraddress ("https: // localhost" ، grpcchaeloptions جدید>); 

برای برنامه های . NET Core 3. 1 چند راه حل وجود دارد:

  • کانال های GRPC جداگانه ای را برای مناطقی از برنامه با بار زیاد ایجاد کنید. به عنوان مثال ، سرویس GRPC Logger ممکن است بار بالایی داشته باشد. برای ایجاد LoggerClient در برنامه از یک کانال جداگانه استفاده کنید.
  • به عنوان مثال از استخر کانال های GRPC استفاده کنید ، لیستی از کانال های GRPC ایجاد کنید. تصادفی برای انتخاب کانال از لیست هر بار که به یک کانال GRPC نیاز باشد ، استفاده می شود. با استفاده از تماس تصادفی به طور تصادفی تماس ها را از طریق چندین اتصالات توزیع می کند.

افزایش حداکثر حد همزمان جریان همزمان روی سرور روش دیگری برای حل این مشکل است. در Kestrel این با MaxstreamsperCoection پیکربندی شده است.

افزایش حداکثر حد همزمان جریان توصیه نمی شود. بیش از حد بسیاری از جریان در یک اتصال HTTP/2 تنها موارد عملکرد جدید را معرفی می کند:

  • بحث موضوع بین جریانی که سعی در نوشتن آن دارند.
  • از بین رفتن بسته بسته باعث مسدود شدن تمام تماس ها در لایه TCP می شود.

ServergarbageCollection در برنامه های مشتری

جمع کننده زباله های NET دارای دو حالت است: جمع آوری زباله های ایستگاه کاری (GC) و مجموعه زباله های سرور. هر کدام برای بار کاری مختلف تنظیم شده اند. برنامه های اصلی ASP. NET به طور پیش فرض از سرور GC استفاده می کنند.

برنامه های بسیار همزمان به طور کلی با سرور GC عملکرد بهتری دارند. اگر یک برنامه مشتری GRPC در همان زمان تعداد زیادی از تماس های GRPC را ارسال و دریافت می کند ، ممکن است در به روزرسانی برنامه برای استفاده از سرور GC یک مزیت عملکردی وجود داشته باشد.

برای فعال کردن سرور GC ، در پرونده پروژه برنامه تنظیم کنید:

 درست است، واقعی  

برای کسب اطلاعات بیشتر در مورد جمع آوری زباله ، به ایستگاه کاری و جمع آوری زباله سرور مراجعه کنید.

برنامه های اصلی ASP. NET به طور پیش فرض از سرور GC استفاده می کنند. فعال کردن فقط در برنامه های مشتری غیر سرور GRPC ، به عنوان مثال در یک برنامه کنسول مشتری GRPC مفید است.

تعادل بار

برخی از تعادل بار با GRPC به طور مؤثر کار نمی کنند. L4 (حمل و نقل) با توزیع اتصالات TCP در نقاط پایانی ، در سطح اتصال کار می کنند. این روش برای بارگیری تماس های API متعادل ساخته شده با HTTP/1. 1 به خوبی کار می کند. تماس های همزمان با HTTP/1. 1 در اتصالات مختلف ارسال می شود و اجازه می دهد تا تماس ها در نقاط پایانی متعادل شوند.

از آنجا که تعادل بار L4 در سطح اتصال کار می کند ، با GRPC خوب کار نمی کنند. GRPC از HTTP/2 استفاده می کند ، که چندین تماس با یک اتصال TCP را چند برابر می کند. تمام تماس های GRPC از این اتصال به یک نقطه پایانی می روند.

دو گزینه برای بارگذاری موثر GRPC وجود دارد:

  • متعادل کردن بار مشتری
  • L7 (برنامه) تعادل بار پروکسی

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

متعادل کردن بار مشتری

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

تعادل بار مشتری Lookaside تکنیکی است که حالت تعادل بار در یک مکان مرکزی ذخیره می شود. مشتریان به طور دوره ای از مکان اصلی برای اطلاعات در هنگام تصمیم گیری در مورد تعادل بار استفاده می کنند.

تعادل بار پروکسی

پروکسی L7 (برنامه) در سطح بالاتری نسبت به پروکسی L4 (حمل و نقل) کار می کند. پروکسی های L7 HTTP/2 را درک می کنند. پروکسی تماسهای GRPC را در یک اتصال HTTP/2 چند برابر می کند و آنها را در نقاط پایانی چند پس زمینه توزیع می کند. استفاده از یک پروکسی ساده تر از تعادل بار در سمت مشتری است ، اما تأخیر اضافی به تماس های GRPC اضافه می کند.

بسیاری از پروکسی های L7 در دسترس است. برخی از گزینه ها عبارتند از:

  • فرستاده - یک پروکسی منبع باز محبوب.
  • Linkerd - مش خدمات برای Kubeetes.
  • YARP: با این حال یک پروکسی معکوس دیگر - یک پروکسی منبع باز نوشته شده در . NET.

ارتباط بین فرآیند

تماس های GRPC بین مشتری و سرویس معمولاً از طریق سوکت های TCP ارسال می شود. TCP برای برقراری ارتباط از طریق یک شبکه بسیار عالی است ، اما ارتباطات بین فرآیند (IPC) وقتی مشتری و سرویس در همان دستگاه قرار دارند ، کارآمدتر است.

استفاده از حمل و نقل مانند سوکت های دامنه یونیکس یا لوله های نامگذاری شده را برای تماس های GRPC بین فرآیندهای موجود در همان دستگاه در نظر بگیرید. برای اطلاعات بیشتر ، به ارتباطات بین فرآیند با GRPC مراجعه کنید.

پینگ های زنده را نگه دارید

برای نگه داشتن اتصالات HTTP/2 در دوره های عدم فعالیت ، می توان از پینگ های زنده نگه دارید. داشتن یک اتصال HTTP/2 موجود در هنگام از سرگیری فعالیت ، امکان برقراری تماس اولیه GRPC را به سرعت انجام می دهد ، بدون تأخیر ناشی از ایجاد مجدد اتصال ، امکان برقراری تماس های GRPC اولیه را فراهم می کند.

پینگ های زنده نگه دارید در Socketshttphandler تنظیم شده اند:

var handler = socketshttphandler جدید؛var chael = grpcchael. foraddress ("https: // localhost: 5001" ، grpcchaeloptions جدید); 

کد قبلی کانال را پیکربندی می کند که هر 60 ثانیه در طول دوره عدم فعالیت ، یک پینگ را به سرور می فرستد. پینگ تضمین می کند که سرور و هرگونه پروکسی مورد استفاده به دلیل عدم فعالیت ، اتصال را ببندد.

کنترل جریان

کنترل جریان HTTP/2 ویژگی ای است که مانع از غرق شدن برنامه ها با داده ها می شود. هنگام استفاده از کنترل جریان:

  • هر اتصال و درخواست HTTP/2 دارای یک پنجره بافر در دسترس است. پنجره Buffer این است که برنامه به یکباره داده می تواند دریافت کند.
  • اگر پنجره بافر پر شود ، کنترل جریان فعال می شود. هنگام فعال شدن ، برنامه ارسال شده برای ارسال داده های بیشتر مکث می کند.
  • هنگامی که برنامه دریافت کننده داده ها را پردازش کرد ، سپس فضای موجود در پنجره بافر در دسترس است. برنامه ارسال کننده داده ارسال را از سر می گیرد.

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

با افزایش اندازه پنجره بافر می توان مشکلات عملکرد کنترل جریان را برطرف کرد. در Kestrel ، این با استفاده از InitialCoectionWindowsize و InitialStreamWindowsize در APP تنظیم شده است:

builder.WebHost.ConfigureKestrel(options => ); 
  • اگر یک سرویس GRPC اغلب پیام های بزرگتر از 96 کیلوبایت ، اندازه پنجره جریان پیش فرض Kestrel را دریافت می کند ، افزایش اتصال و اندازه پنجره را در نظر بگیرید.
  • اندازه پنجره اتصال همیشه باید برابر یا بیشتر از اندازه پنجره جریان باشد. یک جریان بخشی از اتصال است و فرستنده توسط هر دو محدود است.

برای کسب اطلاعات بیشتر در مورد نحوه عملکرد کنترل جریان ، به کنترل جریان HTTP/2 (پست وبلاگ) مراجعه کنید.

افزایش اندازه پنجره Kestrel به Kestrel اجازه می دهد تا داده های بیشتری را از طرف برنامه بافر کند ، که احتمالاً باعث افزایش استفاده از حافظه می شود. از پیکربندی اندازه پنجره غیر ضروری بزرگ خودداری کنید.

جریان

جریان دو طرفه GRPC می تواند برای جایگزینی تماس های GRPC Unary در سناریوهای با کارایی بالا استفاده شود. پس از شروع جریان دو طرفه ، پخش پیام ها به جلو و عقب سریعتر از ارسال پیام با چندین تماس GRPC Unary است. پیام های پخش شده به عنوان داده در مورد درخواست HTTP/2 موجود ارسال می شوند و سربار ایجاد یک درخواست جدید HTTP/2 برای هر تماس متناوب را از بین می برد.

Override Async Task Sayhello (IaSyncStreamReader RequestStream ، IserVerstreamWriter ResponseStream ، ServerCallContext متن); await responseStream.WriteAsync(helloReply);>> 
var client = New Reale. GreeterClient (کانال) ؛با استفاده از var call = client. sayhello () ؛Console. Writeline ("یک نام را تایپ کنید و Enter را فشار دهید.") ؛در حالی که (درست)); await call.ResponseStream.MoveNext(); Console.WriteLine($"Greeting: ");> 

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

استفاده از تماس های جریان انتخاب خوبی است که:

  1. توان بالا یا تأخیر کم مورد نیاز است.
  2. GRPC و HTTP/2 به عنوان یک تنگنا عملکرد شناخته می شوند.
  3. یک کارگر در مشتری در حال ارسال یا دریافت پیام های منظم با سرویس GRPC است.

از پیچیدگی و محدودیت های اضافی استفاده از تماس های جریان به جای Unary آگاه باشید:

  1. با یک سرویس یا خطای اتصال می توان جریان را قطع کرد. در صورت بروز خطایی ، منطق برای راه اندازی مجدد جریان لازم است.
  2. RequestStream. writeasync برای چند رشته ای ایمن نیست. فقط یک پیام را می توان در یک زمان به یک جریان نوشت. ارسال پیام از چندین موضوع از طریق یک جریان واحد نیاز به یک صف تولید کننده/مصرف کننده مانند کانال به پیام های مارشال دارد.
  3. یک روش جریان GRPC محدود به دریافت یک نوع پیام و ارسال یک نوع پیام است. به عنوان مثال ، RPC StreamingCall (Stream RequestMessage) باز می گردد (جریان پاسخ (جریان پاسخ) درخواست را دریافت می کند و پاسخ را ارسال می کند. پشتیبانی Protobuf از پیام های ناشناخته یا مشروط با استفاده از هر یک از و یک و یک می تواند حول این محدودیت کار کند.

بارهای دوتایی

بارهای باینری در ProtoBUF با نوع ارزش مقیاس بایت پشتیبانی می شوند. یک ویژگی تولید شده در C# از Bytestring به عنوان نوع خاصیت استفاده می کند.

syntax = "proto3" ؛پیام PayloadResponse

ProtoBUF یک قالب باینری است که به طور موثر بار باینری بزرگ را با حداقل سربار سریال می کند. قالب های مبتنی بر متن مانند JSON نیاز به رمزگذاری بایت به Base64 دارند و 33 ٪ به اندازه پیام اضافه می کنند.

هنگام کار با بارهای بزرگ با استفاده از بارهای بزرگ ، بهترین روشها برای جلوگیری از نسخه های غیر ضروری و تخصیصی که در زیر مورد بحث قرار می گیرد ، وجود دارد.

بارهای باینری ارسال کنید

نمونه های bytestring به طور معمول با استفاده از bytestring. copyfrom (داده های بایت []) ایجاد می شوند. این روش یک بایت جدید و یک بایت جدید را اختصاص می دهد []. داده ها در آرایه جدید بایت کپی می شوند.

از تخصیص و کپی های اضافی با استفاده از ansafbyteporations. unsafewrap (بایت های readonlymmory) برای ایجاد نمونه های دوربینی جلوگیری می شود.

var data = await file. readallbytesasync (مسیر) ؛var payload = جدید PayloadResponse () ؛payload. data = ansafebyteoprations. unsafewrap (داده) ؛ 

بایت ها با ansafebyteoperations. unsafewrap کپی نمی شوند ، بنابراین در حالی که در حال استفاده است ، نباید اصلاح شوند.

Unsafbyteoperations. unsafewrap به Google. protobuf نسخه 3. 15. 0 یا بالاتر نیاز دارد.

بارهای باینری را بخوانید

داده ها را می توان با استفاده از خصوصیات bytestring. memory و bytestring. span از نمونه های bytestring خواند.

var bytestring = ansafebyteoprations. unsafewrap (بایت جدید []<0, 1, 2>) ؛var data = bytestring. span ؛برای (var i = 0 ؛ i

این خصوصیات به کد اجازه می دهد تا داده ها را مستقیماً از یک محوطه بدون تخصیص یا کپی بخوانند.

بیشتر API های NET دارای اضافه بار ReadonlyMemory و Byte [] هستند ، بنابراین Bytestring. Memory روش توصیه شده برای استفاده از داده های اساسی است. با این حال ، شرایطی وجود دارد که ممکن است یک برنامه نیاز به دریافت داده ها به عنوان یک آرایه بایت داشته باشد. در صورت نیاز به یک آرایه بایت ، می توان از روش MemoryMarshal. TryArray استفاده کرد تا یک آرایه را از یک محوطه استفاده کنید بدون اینکه یک نسخه جدید از داده ها را اختصاص دهید.

var bytestring = getByTestring () ؛محتوای BytearRayContent ؛if (memorymarshal. trygetarray (bytestring. memory ، out var segment))دیگرvar httprequest = جدید httpRequestMessage () ؛httprequest. content = محتوا ؛ 

کد قبلی:

  • تلاش برای بدست آوردن آرایه ای از bytestring. memory با memorymarshal. trygetarray.
  • در صورت بازیابی موفقیت آمیز از آرایه استفاده می کند. این بخش اشاره ای به آرایه ، جبران و شمارش دارد.
  • در غیر این صورت ، به تخصیص یک آرایه جدید با bytestring. tobytearray () بازگشت.

خدمات GRPC و بارهای باینری بزرگ

GRPC و ProtoBUF می توانند بارهای باینری زیادی را ارسال و دریافت کنند. اگرچه Protobuf باینری در سریال سازی بارهای باینری ، از JSON مبتنی بر متن کارآمدتر است ، اما هنوز هم ویژگی های عملکرد مهمی وجود دارد که باید هنگام کار با بارهای باینری بزرگ در نظر داشته باشید.

GRPC یک چارچوب RPC مبتنی بر پیام است ، به این معنی:

  • قبل از اینکه GRPC بتواند آن را ارسال کند ، کل پیام در حافظه بارگذاری می شود.
  • وقتی پیام دریافت می شود ، کل پیام در حافظه رها می شود.

بارهای باینری به عنوان یک آرایه بایت اختصاص می یابد. به عنوان مثال ، یک بار باینری 10 مگابایتی یک آرایه بایت 10 مگابایتی را اختصاص می دهد. پیام هایی با بارهای باینری بزرگ می توانند آرایه های بایت را در پشته شیء بزرگ اختصاص دهند. تخصیص های بزرگ بر عملکرد و مقیاس پذیری سرور تأثیر می گذارد.

مشاوره برای ایجاد برنامه های با کارایی بالا با بارهای باینری بزرگ:

  • از بارهای باینری بزرگ در پیام های GRPC خودداری کنید. یک آرایه بایت بزرگتر از 85000 بایت یک شیء بزرگ در نظر گرفته می شود. نگه داشتن در زیر این اندازه از تخصیص روی پشته شیء بزرگ جلوگیری می کند.
  • در نظر بگیرید که بارهای باینری بزرگ را با استفاده از جریان GRPC تقسیم کنید. داده های باینری روی چندین پیام جمع شده و پخش می شوند. برای کسب اطلاعات بیشتر در مورد نحوه پخش پرونده ها ، به نمونه هایی در مخزن GRPC-DOTNET مراجعه کنید:
    • بارگیری فایل جریان GRPC.
    • بارگذاری فایل جریان GRPC.
    • بدن درخواست را با استفاده از حداقل API وب بخوانید
    • پاسخ جریان را با استفاده از حداقل API وب بازگرداند

    بازخورد

    ارسال و مشاهده بازخورد برای

آموزش مقدماتی فارکس...
ما را در سایت آموزش مقدماتی فارکس دنبال می کنید

برچسب : نویسنده : علیرام نورایی بازدید : <-PostHit-> تاريخ : چهارشنبه 15 شهريور 1402 ساعت: 17:34