搭配 ASP.NET Core 的 gRPC 服務gRPC services with ASP.NET Core

本檔說明如何使用 ASP.NET Core 開始使用 gRPC 服務。This document shows how to get started with gRPC services using ASP.NET Core.

警告

Azure App Service 或 IIS 上目前不支援ASP.NET Core gRPCASP.NET Core gRPC is not currently supported on Azure App Service or IIS. Http.Sys 的 HTTP/2 執行不支援 gRPC 所依賴的 HTTP 回應尾端標頭。The HTTP/2 implementation of Http.Sys does not support HTTP response trailing headers which gRPC relies on. 如需詳細資訊,請參閱 此 GitHub 問題For more information, see this GitHub issue.

必要條件Prerequisites

開始在 ASP.NET Core 中使用 gRPC 服務Get started with gRPC service in ASP.NET Core

檢視或下載範例程式碼 (如何下載)。View or download sample code (how to download).

如需如何建立 gRPC 專案的詳細指示,請參閱 開始使用 gRPC servicesSee Get started with gRPC services for detailed instructions on how to create a gRPC project.

將 gRPC 服務新增至 ASP.NET Core 應用程式Add gRPC services to an ASP.NET Core app

gRPC 需要 gRPC. AspNetCore 套件。gRPC requires the Grpc.AspNetCore package.

設定 gRPCConfigure gRPC

Startup.cs 中:In Startup.cs :

  • 使用方法可啟用 gRPC AddGrpcgRPC is enabled with the AddGrpc method.
  • 每個 gRPC 服務都會透過方法新增至路由管線 MapGrpcServiceEach gRPC service is added to the routing pipeline through the MapGrpcService method.
public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            // 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
            endpoints.MapGrpcService<GreeterService>();
        });
    }
}

如果您想要查看翻譯成英文以外語言的程式碼批註,請在 此 GitHub 討論問題中讓我們知道。If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

ASP.NET Core 中介軟體和功能共用路由管線,因此可以將應用程式設定為提供額外的要求處理常式。ASP.NET Core middlewares and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. 其他的要求處理常式(例如 MVC 控制器)會與已設定的 gRPC 服務平行運作。The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services.

設定 KestrelConfigure Kestrel

Kestrel gRPC 端點:Kestrel gRPC endpoints:

HTTP/2HTTP/2

gRPC 需要 HTTP/2。gRPC requires HTTP/2. ASP.NET Core 的 gRPC 會驗證HttpRequest。 HTTP/2gRPC for ASP.NET Core validates HttpRequest.Protocol is HTTP/2.

Kestrel 支援大部分新式作業系統上的 HTTP/2Kestrel supports HTTP/2 on most modern operating systems. 預設會將 Kestrel 端點設定為支援 HTTP/1.1 和 HTTP/2 連接。Kestrel endpoints are configured to support HTTP/1.1 and HTTP/2 connections by default.

TLSTLS

用於 gRPC 的 Kestrel 端點應使用 TLS 來保護。Kestrel endpoints used for gRPC should be secured with TLS. 在開發期間,會在 https://localhost:5001 ASP.NET Core 開發憑證存在時自動建立以 TLS 保護的端點。In development, an endpoint secured with TLS is automatically created at https://localhost:5001 when the ASP.NET Core development certificate is present. 不需要組態。No configuration is required. https前置詞會驗證 Kestrel 端點是否使用 TLS。An https prefix verifies the Kestrel endpoint is using TLS.

在生產環境中,必須明確設定 TLS。In production, TLS must be explicitly configured. 下列 appsettings.json 範例會提供以 TLS 保護的 HTTP/2 端點:In the following appsettings.json example, an HTTP/2 endpoint secured with TLS is provided:

{
  "Kestrel": {
    "Endpoints": {
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Protocols": "Http2",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    }
  }
}

或者,您也可以在 Program.cs 中設定 Kestrel 端點:Alternatively, Kestrel endpoints can be configured in Program.cs :

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(options =>
            {
                options.Listen(IPAddress.Any, 5001, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                    listenOptions.UseHttps("<path to .pfx file>", 
                        "<certificate password>");
                });
            });
            webBuilder.UseStartup<Startup>();
        });

通訊協定交涉Protocol negotiation

TLS 是用來保護通訊安全。TLS is used for more than securing communication. 當端點支援多個通訊協定時,會使用 TLS 應用層通訊協定協商 (ALPN) 交握來協調用戶端與伺服器之間的連接通訊協定。The TLS Application-Layer Protocol Negotiation (ALPN) handshake is used to negotiate the connection protocol between the client and the server when an endpoint supports multiple protocols. 此協商會判斷連接使用的是 HTTP/1.1 或 HTTP/2。This negotiation determines whether the connection uses HTTP/1.1 or HTTP/2.

如果 HTTP/2 端點設定為沒有 TLS,則端點的 >listenoptions 必須設定為 HttpProtocols.Http2If an HTTP/2 endpoint is configured without TLS, the endpoint's ListenOptions.Protocols must be set to HttpProtocols.Http2. 具有多個通訊協定的端點 (例如, HttpProtocols.Http1AndHttp2) 無法在沒有 TLS 的情況下使用,因為沒有任何協調。An endpoint with multiple protocols (for example, HttpProtocols.Http1AndHttp2) can't be used without TLS because there is no negotiation. 所有不安全端點的連接都會預設為 HTTP/1.1,且 gRPC 呼叫會失敗。All connections to the unsecured endpoint default to HTTP/1.1, and gRPC calls fail.

如需有關使用 Kestrel 啟用 HTTP/2 和 TLS 的詳細資訊,請參閱 Kestrel 端點設定。For more information on enabling HTTP/2 and TLS with Kestrel, see Kestrel endpoint configuration.

注意

macOS 不支援具有 TLS 的 ASP.NET Core gRPC。macOS doesn't support ASP.NET Core gRPC with TLS. 您需要額外的組態才能在 macOS 上成功執行 gRPC 服務。Additional configuration is required to successfully run gRPC services on macOS. 如需詳細資訊,請參閱無法在 macOS 上啟動 ASP.NET Core gRPC 應用程式For more information, see Unable to start ASP.NET Core gRPC app on macOS.

與 ASP.NET Core Api 整合Integration with ASP.NET Core APIs

gRPC services 具有 ASP.NET Core 功能的完整存取權,例如相依性 插入 (DI) 和 記錄gRPC services have full access to the ASP.NET Core features such as Dependency Injection (DI) and Logging. 例如,服務執行可透過此函式從 DI 容器解析記錄器服務:For example, the service implementation can resolve a logger service from the DI container via the constructor:

public class GreeterService : Greeter.GreeterBase
{
    public GreeterService(ILogger<GreeterService> logger)
    {
    }
}

根據預設,gRPC 服務執行可以使用任何存留期來解析其他 DI 服務 (單一、範圍或暫時性) 。By default, the gRPC service implementation can resolve other DI services with any lifetime (Singleton, Scoped, or Transient).

解析 gRPC 方法中的 HttpCoNtextResolve HttpContext in gRPC methods

GRPC API 可讓您存取某些 HTTP/2 訊息資料,例如方法、主機、標頭和結尾。The gRPC API provides access to some HTTP/2 message data, such as the method, host, header, and trailers. 存取是透過 ServerCallContext 傳遞給每個 gRPC 方法的引數:Access is through the ServerCallContext argument passed to each gRPC method:

public class GreeterService : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(
        HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

ServerCallContext 未提供 HttpContext 所有 ASP.NET api 的完整存取權。ServerCallContext does not provide full access to HttpContext in all ASP.NET APIs. GetHttpContext擴充方法會提供完整的存取權,以 HttpContext 代表 ASP.NET api 中的基礎 HTTP/2 訊息:The GetHttpContext extension method provides full access to the HttpContext representing the underlying HTTP/2 message in ASP.NET APIs:

public class GreeterService : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(
        HelloRequest request, ServerCallContext context)
    {
        var httpContext = context.GetHttpContext();
        var clientCertificate = httpContext.Connection.ClientCertificate;

        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name + " from " + clientCertificate.Issuer
        });
    }
}

其他資源Additional resources