日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
使用gRPC和.NET7構建高性能服務

.NET 7 正式推出標準期限支持,支持期限為 18 個月。 其中包括許多令人興奮的新功能,包括 Web API、gRPC、ASP.NET 和 C#11 的性能升級。

創(chuàng)新互聯(lián)建站堅持“要么做到,要么別承諾”的工作理念,服務領域包括:成都網(wǎng)站設計、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的天柱網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!

本文涵蓋以下主題:

  1. .NET 7 中的性能改進。
  2. gRPC JSON 轉碼。
  3. 在 .NET 7 中創(chuàng)建 gRPC 服務。
  4. 在 Postman 使用 gRPC 服務。
  5. 使用服務器反射和 Postman
  6. 添加 Swagger 規(guī)范。

除了討論 .NET 7 中 gRPC 的新特性,我們還將實現(xiàn)一個能夠在一分鐘內(nèi)流式傳輸 500 萬條記錄的真實微服務。

這是一個快速回顧:

  • gRPC 是由 CNCF 開發(fā)的流行的開源 RPC 框架。
  • 作為契約優(yōu)先、獨立于語言的框架,客戶端和服務器必須就消息的內(nèi)容和傳遞方式達成一致,契約在 .proto 文件中定義,然后使用 .NET7 的工具生成代碼。
  • 在單個 tcp 連接上,HTTP/2 支持多路復用,您可以同時發(fā)送多個請求。
  • 此外,gRPC 支持數(shù)據(jù)流,其中服務器可以同時向客戶端發(fā)送多個響應,反之亦然。

.NET 7 中有哪些新功能?

1、性能改進

為了讓 gRPC 支持多路復用,HTTP/2 是必需的。 但是,Kestrel 的 HTTP/2 實現(xiàn)存在一個已知問題,該問題會在連接繁忙時通過 HTTP/2 寫入響應時出現(xiàn)瓶頸。 當您在同一個 TCP 連接上同時運行多個請求,但一次只有一個線程能夠?qū)懭朐撨B接時,就會發(fā)生這種情況。 這是通過 .NET 6 中的線程鎖完成的,這會導致鎖爭用。

NET 7 使用一種巧妙的方法來解決此瓶頸,即實現(xiàn)一個隊列,該隊列會在寫入完成時通知所有其他線程,讓它們等待寫入完成。 因此,性能大大提升,CPU資源得到更好的利用——不再需要爭鎖。

.NET gRPC 團隊的基準測試表明服務器流式處理提高了 800%。

  • .NET 6–0.5M RPS
  • .NET 7–4.5M RPS

HTTP/2 上傳速度

通過增加緩沖區(qū)大小可將延遲減少 600%。 與 .NET 6 相比,.NET 7 將上傳 100MB 文件的時間從 26.9 秒減少到 4.3 秒。

.NET 7 gRPC 的性能現(xiàn)在超過了 Rust、Go 和 C++ 等流行框架。

2、gRPC JSON轉碼

.NET7 為 ASP.NET Core gRPC 提供了擴展,以使 gRPC 服務能夠作為 RESTful Web 服務公開。 您現(xiàn)在可以通過 HTTP 調(diào)用 gRPC 方法而無需任何重復。

gRPC JSON 轉碼支持:

  • HTTP 動詞
  • URL參數(shù)綁定
  • JSON請求/響應

在此擴展中,HTTP 動詞通過使用 protobuf 注釋的概念映射到 gRPC 服務,擴展在 ASP.NET Core 應用程序中運行,然后將 JSON 反序列化為 protobuf 消息并直接調(diào)用 gRPC 服務,而不必編寫自己的 gRPC 客戶端應用程序。

我們將在下一節(jié)中研究如何實現(xiàn)它。

3、開放API規(guī)范

現(xiàn)在有一個 Open API 規(guī)范,用于 .NET 7 中的 gRPC JSON 轉碼,使用以下 Nuget 包:

?https://www.nuget.org/packages/Microsoft.AspNetCore.Grpc.Swagger?

4、 Azure 應用服務支持

最后但同樣重要的是,Azure 應用服務現(xiàn)在完全支持 gRPC。 這是在 .NET 中使用 gRPC 構建和部署高性能服務的一大進步。

現(xiàn)在我們已經(jīng)完成了討論,讓我們實現(xiàn) gRPC 并看看新功能是什么樣的。

先決條件:

  • 下載并安裝 .NET 7 SDK
  • Visual Studio 2022 17.4+

我們需要做的第一件事是啟動 Visual Studio 并創(chuàng)建一個新項目。 選擇“ASP.NET Core gRPC 服務”,這將創(chuàng)建一個示例 hello world gRPC 服務。

確保選擇了 .NET7。

這將分別在 protos 和服務文件夾中的 GreeterService 中創(chuàng)建一個隨時可用的 gRPC 應用程序。

這是一個用作契約的 greeting.proto 文件,定義了客戶端將接收的消息和服務。

syntax = "proto3";

option csharp_namespace = "gRPCUsingNET7Demo";

package greet;

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings.
message HelloReply {
string message = 1;
}

契約可以被認為是接口,這些接口的實現(xiàn)將由服務定義,在我們的例子中是 GreeterService.cs——這個文件將描述契約的實現(xiàn)。

GreeterService 類是一個標準的 C# 類,它向響應返回 hello。 protobuf 的實際實現(xiàn)是通過代碼生成實現(xiàn)的,并使用 GreeterBase 抽象出來。 如果您想確切地知道引擎下發(fā)生了什么,您可以轉到 GreeterBase,您會在那里找到所有底層細節(jié)。

public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger _logger;
public GreeterService(ILogger logger){
_logger = logger;
}

public override Task SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}

代碼生成是 .NET 7 的一項不錯的功能,它允許您生成服務器端和客戶端 gRPC 代碼。 通過設置代碼生成設置,可以更改 .CS 項目文件中代碼生成過程的行為(例如從服務器到客戶端)。

  

讓我們啟動 Kestral 并在打開應用程序后在瀏覽器中瀏覽 gRPC 端點。

我們無法通過網(wǎng)絡訪問我們的 gRPC 服務,因為它需要使用 gRPC 客戶端。 但是,我們不需要使用 gRPC 客戶端,而是使用流行的測試工具 Postman 對其進行測試。 它最近在其功能中添加了對 gRPC 請求的支持。

第一步是打開 Postman 并創(chuàng)建一個新的 gRPC 請求。

請在下面的框中輸入服務器地址(您的應用程序運行的地址)。 例如,https://localhost:7211。

Postman目前不了解我們的服務如何運作,因此我們有幾個選擇。 一種是導入 .proto 文件或使用稱為“服務器反射”的東西。 它可以被認為是 gRPC 調(diào)用的 OpenAPI 規(guī)范。

在 gRPC 服務中啟用服務器反射。

按照以下步驟啟用服務器反射非常簡單。

下載并安裝以下 nuget 包:

Install-Package Grpc.AspNetCore.Server.Reflection -Version 2.49.0

2、在Program.cs文件中,需要注冊如下服務,并將該服務映射到我們的http管道中,如下:

builder.Services.AddGrpcReflection();

app.MapGrpcReflectionService();

現(xiàn)在我們已經(jīng)完成了所有這些前置需求,讓我們回到 Postman,再次運行應用程序。

我們可以看到我們的 greet.greeter 服務和它的 SayHello 方法。

可以通過單擊帶有 JSON 正文(將由 Postman 轉換為 protobuf)的 Invoke 按鈕來調(diào)用此端點。

在 49 毫秒內(nèi)得到了服務器響應。

將您的 gRPC 服務轉變?yōu)?REST

本節(jié)將實現(xiàn) gRPC JSON 轉碼以通過 HTTP 訪問 gRPC。

  1. 將以下 nuget 包添加到您的項目中:
Install-Package Microsoft.AspNetCore.Grpc.JsonTranscoding -Version 7.0.0

2. 導航到 Program.cs 并添加 JSONTranscoding 服務:

builder.Services.AddGrpc().AddJsonTranscoding();

下一步,我們將向您的項目添加兩個配置文件。

添加這些文件后,我們需要修改 greet.proto 并添加 import “google/api/annotations.proto” 以便我們可以注解服務方法。

  // Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply)
{
option (google.api.http) =
{
get: "/v1/greeter/{name}"
}

};

基本上,我們向我們的 RPC 方法添加了一個路由,以便它可以作為 REST 方法被調(diào)用。 讓我們再次運行應用程序并使用瀏覽器執(zhí)行端點。

就是這樣! 該 API 現(xiàn)在作為基于 REST 的 API 工作,但它仍然可以作為 gRPC 接口使用。 來自 Postman 的 gRPC 響應如下所示。

添加開放 API 規(guī)范

本節(jié)的目的是解釋我們?nèi)绾问褂?gRPC.Swagger 向我們的應用程序添加開放 API 規(guī)范。

  1. 安裝以下 nuget 包:
Install-Package Microsoft.AspNetCore.Grpc.Swagger -Version 0.3.0

2.注冊Swagger服務和中間件,如下

   builder.Services.AddGrpcSwagger();
builder.Services.AddSwaggerGen( c=>
{
c.SwaggerDoc("v1",
new Microsoft.OpenApi.Models.OpenApiInfo { Title = "gRPC using .NET 7 Demo", Version = "v1" } );
});

最后,您的 program.cs 應該如下所示:

using gRPCUsingNET7Demo.Services;

namespace gRPCUsingNET7Demo
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682

// Add services to the container.
builder.Services.AddGrpc().AddJsonTranscoding();
builder.Services.AddGrpcReflection();
builder.Services.AddGrpcSwagger();

builder.Services.AddSwaggerGen( c=>
{
c.SwaggerDoc("v1",
new Microsoft.OpenApi.Models.OpenApiInfo { Title = "gRPC using .NET 7 Demo", Version = "v1" }

});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(c
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "gRPC using .NET7 Demo");
}
);
// Configure the HTTP request pipeline.
app.MapGrpcService();
app.MapGrpcReflectionService();
app.MapGet("/", () "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
app.Run();
}
}
}

啟動應用程序后調(diào)用 Swagger 端點:
https://localhost:7211/swagger/index.html。

您可以像調(diào)用任何 Restful API 一樣嘗試調(diào)用端點。

在本節(jié)之后,我們將演示如何使用 gRPC 服務器流將 5M 記錄(大約 600MB 數(shù)據(jù))使用流式傳輸?shù)娇蛻舳恕?/p>

gRPC 服務器流

在服務器流中,gRPC 客戶端發(fā)送請求并獲取響應流。 客戶端讀取這些響應,直到所有消息都已傳遞。 gRPC 確保消息排序。

使用此示例 CSV 文件作為示例。

該 CSV 文件包含大約 500 萬條銷售記錄,因此不可能在一個調(diào)用中將它們?nèi)堪l(fā)送出去。

此外,傳統(tǒng)的基于 REST 的分頁涉及多個客戶端請求,并且需要在客戶端和服務器之間來回通信。

gRPC Server streaming 是解決這個問題的絕佳方案。

  • 客戶端將簡單地調(diào)用服務方法。
  • CSV 文件將逐行讀取,轉換為原型模型,然后使用 StreamReader 發(fā)送回客戶端。
  • 響應流將被發(fā)送到客戶端。

我們將從定義一個原型文件開始:

Protos-> sales.proto

syntax = "proto3";
import "google/protobuf/timestamp.proto";
csharp_namespace = "gRPCUsingNET7Demo";

package sales;

service SalesService {
rpc GetSalesData(Request) returns (stream SalesDataModel) {}
}

message Request{
string filters=1;

}

message SalesDataModel {
int32 OrderID = 1;
string Region = 2;
string Country = 3;
string ItemType=4;
google.protobuf.Timestamp OrderDate=5;
google.protobuf.Timestamp ShipDate=6;
int32 UnitsSold=7;
float UnitCost=8;
float UnitPrice=9;
int32 TotalRevenue=10;
int32 TotalCost=11;
int32 TotalProfit=12;
}

使用 stream 關鍵字,我們可以指定 SalesDataModel 將作為流傳遞。

我們的下一步是通過以下方式添加一個新服務——SalesDataService.cs:

using Grpc.Core;
using gRPCUsingNET7Demo;

namespace gRPCUsingNET7Demo.Services
{
public class SalesDataService : SalesService.SalesServiceBase

{
public override async Task
GetSalesData(Request request,
IServerStreamWriter responseStream, ServerCallContext context){

using (var reader = new StreamReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data", "sales_records.csv")))
{
string line; bool isFirstLine = true;
while ((line = reader.ReadLine()) != null)
{
var pieces = line.Split(',');

var _model = new SalesDataModel();

try
{
if (isFirstLine)
{
isFirstLine = false;
continue;
}

_model.Region = pieces[0];
_model.Country = pieces[1];

_model.OrderID = int.TryParse(pieces[6], out int _orderID) ? _orderID : 0;
_model.UnitPrice = float.TryParse(pieces[9], out float _unitPrice) ? _unitPrice : 0;

_model.ShipDate = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime
((DateTime.TryParse(pieces[7], out DateTime _dateShip) ? _dateShip : DateTime.MinValue).ToUniversalTime());

_model.UnitsSold = int.TryParse(pieces[8], out int _unitsSold) ? _unitsSold : 0;

_model.UnitCost = float.TryParse(pieces[10], out float _unitCost) ? _unitCost : 0;

_model.TotalRevenue = int.TryParse(pieces[11], out int _totalRevenue) ? _totalRevenue : 0;
_model.TotalCost = int.TryParse(pieces[13], out int _totalCost) ? _totalCost : 0;

await responseStream.WriteAsync(_model);

}

catch (Exception ex)
{
throw new RpcException(new Status(StatusCode.Internal, ex.ToString()));
}

}
}

}

}
}

此服務實現(xiàn) SalesServiceBase 類,該類由 .NET7 工具使用 proto 文件自動生成。

它只是重寫 GetSalesData 以逐行從文件中讀取數(shù)據(jù)并將其作為流返回。

await responseStream.WriteAsync(_model);

讓我們構建項目并運行應用程序。

應用程序按預期運行。 要從服務器獲取訂單流,我們需要創(chuàng)建一個單獨的 RPC 客戶端,這將在下一節(jié)中介紹。

使用 .NET7 創(chuàng)建 gRPC 客戶端

讓我們在您的解決方案中創(chuàng)建一個新的控制臺應用程序,并向其中添加以下包




all
runtime; build; native; contentfiles; analyzers; buildtransitive
  1. 確保添加了 Protos 文件夾并將 sales.proto 文件復制到那里。
  2. 為了為客戶端生成 gRPC 類,您需要修改 .csproj 文件。


3. 保存并構建項目(以便生成客戶端代碼)

4. 第一步是打開 Program.cs 并為您的 gRPC 服務創(chuàng)建一個通道。

var channel = GrpcChannel.ForAddress("https://localhost:7211");

5. 創(chuàng)建一個新的SalesService對象(使用gRPC工具創(chuàng)建)如下:

var client = new SalesService.SalesServiceClient(channel);

6.服務方法應按如下方式調(diào)用:

using var call = client.GetSalesData(new Request { Filters = "" });

7. 我們的代碼只是調(diào)用服務器上的 ReadAllAsync 來檢索流,然后在收到流后立即在控制臺上打印輸出。

await foreach (var each in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine(String.Format("New Order Receieved from {0}-{1},Order ID = {2}, Unit Price ={3}, Ship Date={4}", each.Country, each.Region, each.OrderID, each.UnitPrice,each.ShipDate));
Count++;
}

這就是完整實現(xiàn):

using Grpc.Core;
using Grpc.Net.Client;
using gRPCUsingNET7Demo;

namespace gRPCClient
{
internal class Program
{
static async Task Main(string[] args)
{
var channel = GrpcChannel.ForAddress("https://localhost:7211");
int Count = 0;
var watch = System.Diagnostics.Stopwatch.StartNew();
try
{
var client = new SalesService.SalesServiceClient(channel);

using var call = client.GetSalesData(new Request { Filters = "" }
, deadline: DateTime.UtcNow.AddMinutes(10)
);

await foreach (var each in call.ResponseStream.ReadAllAsync())
{

Console.WriteLine(String.Format("New Order Receieved from {0}-{1},Order ID = {2}, Unit Price ={3}, Ship Date={4}", each.Country, each.Region, each.OrderID, each.UnitPrice, each.ShipDate));
Count++;

}
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
Console.WriteLine("Service timeout.");
}

watch.Stop();

Console.WriteLine($"Stream ended: Total Records:{Count.ToString()} in {watch.Elapsed.TotalMinutes} minutes and {watch.Elapsed.TotalSeconds});
Console.Read();

}
}
}

正如您在上面的示例中看到的,服務方法調(diào)用是在deadline的幫助下完成的。 您可以使用deadline指定通話的持續(xù)時間,這樣您就可以指定通話應該持續(xù)多長時間。

using var call = client.GetSalesData(new Request { Filters = "" }
, deadline: DateTime.UtcNow.AddMinutes(10)
);

客戶端現(xiàn)在允許您查看來自 gRPC 服務的傳入消息。

結論:

本文的目的是提供有關已添加到 gRPC .NET 7 框架的性能增強的信息,包括 gRPC JSON 轉碼功能、OpenAPI 規(guī)范和服務器反射功能,以及新的性能改進。 本文還解釋了如何使用 gRPC 服務器流式處理來創(chuàng)建能夠立即處理和交付數(shù)百萬條記錄的高性能服務。


標題名稱:使用gRPC和.NET7構建高性能服務
本文鏈接:http://m.5511xx.com/article/djhcejs.html