gRPC-Web в приложениях ASP.NET Core gRPC
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 8 этой статьи.
Автор: Джеймс Ньютон-Кинг (James Newton-King)
Узнайте, как настроить существующую службу ASP.NET Core gRPC для вызовов из приложений браузера с использованием протокола gRPC-Web. gRPC-Web позволяет приложениям JavaScript и Blazor на основе браузера вызывать службы gRPC. Вызвать службу HTTP/2 gRPC из приложения на основе браузера нельзя. Службы gRPC, размещенные в ASP.NET Core, можно настроить на поддержку gRPC-Web вместе с HTTP/2 gRPC.
См. раздел Добавление служб gRPC в приложение ASP.NET Core.
Инструкции по созданию проекта gRPC см. в статье Создание клиента и сервера .NET Core gRPC в ASP.NET Core.
Сравнение ASP.NET Core gRPC-Web с Envoy
Существует два способа добавления gRPC-Web в приложение ASP.NET Core.
- Поддержка gRPC-Web вместе с gRPC HTTP/2 в ASP.NET Core. Этот параметр использует ПО промежуточного слоя, предоставленное пакетом
Grpc.AspNetCore.Web
. - Используйте поддержку gRPC-Web в прокси-сервере Envoy, чтобы транслировать gRPC-Web в gRPC HTTP/2. Затем переведенный вызов перенаправляется в приложение ASP.NET Core.
Есть свои плюсы и минусы этого подхода. Если среда приложения уже использует Envoy в качестве прокси-сервера, имеет смысл использовать Envoy и для предоставления поддержки gRPC-Web. Если требуется простое решение для gRPC-Web, для которого требуется только ASP.NET Core, используйте Grpc.AspNetCore.Web
.
Настройка gRPC-Web в ASP.NET Core
Службы gRPC, размещенные в ASP.NET Core, можно настроить на поддержку gRPC-Web вместе с HTTP/2 gRPC. gRPC-Web не требует вносить изменения в службы. Единственное изменение заключается в настройке ПО промежуточного слоя Program.cs
.
Чтобы включить gRPC-Web со службой gRPC ASP.NET Core, выполните следующие действия.
- добавьте ссылку на пакет
Grpc.AspNetCore.Web
; - Настройте приложение для использования gRPC-Web, добавив
UseGrpcWeb
иEnableGrpcWeb
вProgram.cs
:
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb();
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is callable from browser apps using the gRPC-Web protocol");
app.Run();
Предыдущий код:
- Добавляет ПО промежуточного слоя gRPC-Web (
UseGrpcWeb
) после маршрутизации и перед конечными точками. - Указывает, что метод
endpoints.MapGrpcService<GreeterService>()
поддерживает gRPC-Web сEnableGrpcWeb
.
Можно также настроить ПО промежуточного слоя gRPC-Web, чтобы все службы поддерживали gRPC-Web по умолчанию и не нужно было использовать EnableGrpcWeb
. Укажите new GrpcWebOptions { DefaultEnabled = true }
при добавлении ПО промежуточного слоя.
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "All gRPC service are supported by default in this example, and are callable from browser apps using the gRPC-Web protocol");
app.Run();
Примечание.
Существует известная ошибка, приводящая к сбою gRPC-Web при размещении с помощью HTTP.sys в .NET Core 3.x.
Временное решение для запуска gRPC-Web на HTTP.sys доступно в разделе Экспериментальное использование gRPC-Web и UseHttpSys() (grpc/grpc-dotnet № 853).
gRPC-Web и CORS
Система безопасности браузера предотвращает запросы веб-страницы к другому домену, отличному от того, который обслуживает веб-страницу. Это ограничение применяется к вызовам gRPC-Web с приложениями браузера. Например, приложение браузера, обслуживаемое https://www.contoso.com
, блокирует вызов служб gRPC-Web, размещенных на https://services.contoso.com
. Можно использовать общий доступ к ресурсам независимо от источника (CORS), чтобы ослабить это ограничение.
Чтобы разрешить приложению браузера вызывать gRPC-Web независимо от источника, настройте CORS в ASP.NET Core. Используйте встроенную поддержку CORS и предоставьте заголовки, относящиеся к gRPC, с помощью WithExposedHeaders.
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));
var app = builder.Build();
app.UseGrpcWeb();
app.UseCors();
app.MapGrpcService<GreeterService>().EnableGrpcWeb()
.RequireCors("AllowAll");
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS enabled, and is callable from browser apps using the gRPC-Web protocol");
app.Run();
Предыдущий код:
- Вызывает
AddCors
для добавления служб CORS и настройки политики CORS, которая предоставляет заголовки, относящиеся к gRPC. - Вызывает
UseCors
для добавления ПО промежуточного слоя CORS после настройки маршрутизации и перед настройкой конечных точек. - Указывает, что метод
endpoints.MapGrpcService<GreeterService>()
поддерживает CORS сRequireCors
.
gRPC-Web и потоковая передача
Традиционный протокол gRPC на основе HTTP/2 поддерживает клиентскую, серверную и двунаправленную потоковую передачу. gRPC-Web имеет ограниченную поддержку потоковой передачи:
- Клиенты браузера с gRPC-Web не поддерживают вызов методов потоковой передачи клиента и двунаправленной потоковой передачи.
- Клиенты .NET с gRPC-Web не поддерживают вызов на клиенте методов потоковой передачи и двунаправленной потоковой передачи по протоколу HTTP/1.1.
- Службы gRPC в ASP.NET Core, размещенные в Службе приложений Azure и IIS, не поддерживают двунаправленную потоковую передачу.
При использовании gRPC-Web мы рекомендуем применять только унарные методы и методы серверной потоковой передачи.
Протокол HTTP
Шаблон службы ASP.NET Core gRPC, включенный в пакет SDK для .NET, создает приложение, настроенное только для HTTP/2. Это хорошая настройка по умолчанию, если приложение поддерживает только традиционный протокол gRPC на основе HTTP/2. Однако gRPC-Web работает как с HTTP/1.1, так и с HTTP/2. Некоторые платформы, например UWP или Unity, не могут использовать HTTP/2. Чтобы обеспечить поддержку всех клиентских приложений, настройте сервер для включения HTTP/1.1 и HTTP/2.
Обновите протокол умолчанию в файле appsettings.json
:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
Как вариант, вы можете настроить конечные точки Kestrel в коде запуска.
Чтобы включить HTTP/1.1 и HTTP/2 на одном порте, требуется TLS для согласования протокола. Дополнительные сведения см. в разделе Согласование протокола ASP.NET Core.
Вызов gRPC-Web из браузера
Приложения браузера могут использовать gRPC-Web для вызова служб gRPC. При вызове служб gRPC с помощью gRPC-Web из браузера существует ряд требований и ограничений.
- Сервер должен содержать конфигурацию для поддержки gRPC-Web.
- Потоковая передача клиента и вызовы двунаправленной потоковой передачи не поддерживаются. Потоковая передача сервера поддерживается.
- Для вызова служб gRPC в другом домене требуется настроить CORS на сервере.
Клиент gRPC-Web JavaScript
Существуют клиенты gRPC-Web для JavaScript. Инструкции по использованию gRPC-Web из JavaScript см. в статье, посвященной написанию кода клиента JavaScript с gRPC-Web.
Настройка gRPC-Web с помощью клиента .NET gRPC
Клиент .NET gRPC можно настроить для выполнения вызовов gRPC-Web. Это полезно для приложений Blazor WebAssembly, которые размещаются в браузере и имеют те же ограничения HTTP, что и код JavaScript. Вызов gRPC-Web с помощью клиента .NET выполняется так же, как и для HTTP/2 gRPC. Единственным изменением является то, как создается канал.
Чтобы использовать gRPC-Web:
- добавьте ссылку на пакет
Grpc.Net.Client.Web
; - убедитесь, что используется ссылка на пакет
Grpc.Net.Client
версии 2.29.0 или более поздней; - Настройте канал на использование
GrpcWebHandler
:
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Предыдущий код:
- Настраивает канал для использования gRPC-Web.
- Создает клиент и выполняет вызов с помощью канала.
GrpcWebHandler
имеет следующие параметры конфигурации.
InnerHandler
: базовый HttpMessageHandler объект, который делает HTTP-запрос gRPC, напримерHttpClientHandler
.GrpcWebMode
: тип перечисления, указывающий, являетсяapplication/grpc-web
ли HTTP-запросContent-Type
gRPC илиapplication/grpc-web-text
.GrpcWebMode.GrpcWeb
настраивает отправку содержимого без кодирования. Значение по умолчанию.GrpcWebMode.GrpcWebText
настраивает содержимое в кодировке Base64. Требуется для вызовов потоковой передачи сервера в браузерах.
HttpVersion
: протоколVersion
HTTP, используемый для установки HttpRequestMessage.Version в базовом HTTP-запросе gRPC. gRPC-Web не требует определенной версии и не переопределяет значение по умолчанию, если не указано иное.
Внимание
Созданные клиенты gRPC имеют синхронные и асинхронные методы для вызова унарных методов. Например, SayHello
является синхронным, а SayHelloAsync
— асинхронным. Асинхронные методы всегда требуются в Blazor WebAssembly. Вызов синхронного метода в приложении Blazor WebAssembly приведет к тому, что приложение перестанет отвечать на запросы.
Использование фабрики клиента gRPC с gRPC-Web
Создайте клиент .NET, совместимый с gRPC-Web, с помощью фабрики клиентов gRPC:
- Добавьте ссылки на пакеты в файл проекта для следующих пакетов:
- Зарегистрируйте клиент gRPC с внедрением зависимостей (DI) с помощью универсального метода расширения
AddGrpcClient
. В приложении Blazor WebAssembly службы регистрируются с внедрением зависимостей вProgram.cs
. - Настройте
GrpcWebHandler
с помощью метода расширения ConfigurePrimaryHttpMessageHandler.
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
Дополнительные сведения см. в статье Интеграция фабрики клиента gRPC в .NET.
Дополнительные ресурсы
Узнайте, как настроить существующую службу ASP.NET Core gRPC для вызовов из приложений браузера с использованием протокола gRPC-Web. gRPC-Web позволяет приложениям JavaScript и Blazor на основе браузера вызывать службы gRPC. Вызвать службу HTTP/2 gRPC из приложения на основе браузера нельзя. Службы gRPC, размещенные в ASP.NET Core, можно настроить на поддержку gRPC-Web вместе с HTTP/2 gRPC.
См. раздел Добавление служб gRPC в приложение ASP.NET Core.
Инструкции по созданию проекта gRPC см. в статье Создание клиента и сервера .NET Core gRPC в ASP.NET Core.
Сравнение ASP.NET Core gRPC-Web с Envoy
Существует два способа добавления gRPC-Web в приложение ASP.NET Core.
- Поддержка gRPC-Web вместе с gRPC HTTP/2 в ASP.NET Core. Этот параметр использует ПО промежуточного слоя, предоставленное пакетом
Grpc.AspNetCore.Web
. - Используйте поддержку gRPC-Web в прокси-сервере Envoy, чтобы транслировать gRPC-Web в gRPC HTTP/2. Затем переведенный вызов перенаправляется в приложение ASP.NET Core.
Есть свои плюсы и минусы этого подхода. Если среда приложения уже использует Envoy в качестве прокси-сервера, имеет смысл использовать Envoy и для предоставления поддержки gRPC-Web. Если требуется простое решение для gRPC-Web, для которого требуется только ASP.NET Core, используйте Grpc.AspNetCore.Web
.
Настройка gRPC-Web в ASP.NET Core
Службы gRPC, размещенные в ASP.NET Core, можно настроить на поддержку gRPC-Web вместе с HTTP/2 gRPC. gRPC-Web не требует вносить изменения в службы. Единственное изменение заключается в настройке middelware в Program.cs
.
Чтобы включить gRPC-Web со службой gRPC ASP.NET Core, выполните следующие действия.
- добавьте ссылку на пакет
Grpc.AspNetCore.Web
; - Настройте приложение для использования gRPC-Web, добавив
UseGrpcWeb
иEnableGrpcWeb
вProgram.cs
:
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb();
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is callable from browser apps using the gRPC-Web protocol");
app.Run();
Предыдущий код:
- Добавляет ПО промежуточного слоя gRPC-Web (
UseGrpcWeb
) после маршрутизации и перед конечными точками. - Указывает, что метод
endpoints.MapGrpcService<GreeterService>()
поддерживает gRPC-Web сEnableGrpcWeb
.
Можно также настроить ПО промежуточного слоя gRPC-Web, чтобы все службы поддерживали gRPC-Web по умолчанию и не нужно было использовать EnableGrpcWeb
. Укажите new GrpcWebOptions { DefaultEnabled = true }
при добавлении ПО промежуточного слоя.
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "All gRPC service are supported by default in this example, and are callable from browser apps using the gRPC-Web protocol");
app.Run();
Примечание.
Существует известная ошибка, приводящая к сбою gRPC-Web при размещении с помощью HTTP.sys в .NET Core 3.x.
Временное решение для запуска gRPC-Web на HTTP.sys доступно в разделе Экспериментальное использование gRPC-Web и UseHttpSys() (grpc/grpc-dotnet № 853).
gRPC-Web и CORS
Система безопасности браузера предотвращает запросы веб-страницы к другому домену, отличному от того, который обслуживает веб-страницу. Это ограничение применяется к вызовам gRPC-Web с приложениями браузера. Например, приложение браузера, обслуживаемое https://www.contoso.com
, блокирует вызов служб gRPC-Web, размещенных на https://services.contoso.com
. Можно использовать общий доступ к ресурсам независимо от источника (CORS), чтобы ослабить это ограничение.
Чтобы разрешить приложению браузера вызывать gRPC-Web независимо от источника, настройте CORS в ASP.NET Core. Используйте встроенную поддержку CORS и предоставьте заголовки, относящиеся к gRPC, с помощью WithExposedHeaders.
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));
var app = builder.Build();
app.UseGrpcWeb();
app.UseCors();
app.MapGrpcService<GreeterService>().EnableGrpcWeb()
.RequireCors("AllowAll");
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS enabled, and is callable from browser apps using the gRPC-Web protocol");
app.Run();
Предыдущий код:
- Вызывает
AddCors
для добавления служб CORS и настройки политики CORS, которая предоставляет заголовки, относящиеся к gRPC. - Вызывает
UseCors
для добавления ПО промежуточного слоя CORS после настройки маршрутизации и перед настройкой конечных точек. - Указывает, что метод
endpoints.MapGrpcService<GreeterService>()
поддерживает CORS сRequireCors
.
gRPC-Web и потоковая передача
Традиционный протокол gRPC на основе HTTP/2 поддерживает клиентскую, серверную и двунаправленную потоковую передачу. gRPC-Web имеет ограниченную поддержку потоковой передачи:
- Клиенты браузера с gRPC-Web не поддерживают вызов методов потоковой передачи клиента и двунаправленной потоковой передачи.
- Клиенты .NET с gRPC-Web не поддерживают вызов на клиенте методов потоковой передачи и двунаправленной потоковой передачи по протоколу HTTP/1.1.
- Службы gRPC в ASP.NET Core, размещенные в Службе приложений Azure и IIS, не поддерживают двунаправленную потоковую передачу.
При использовании gRPC-Web мы рекомендуем применять только унарные методы и методы серверной потоковой передачи.
Протокол HTTP
Шаблон службы ASP.NET Core gRPC, включенный в пакет SDK для .NET, создает приложение, настроенное только для HTTP/2. Это хорошая настройка по умолчанию, если приложение поддерживает только традиционный протокол gRPC на основе HTTP/2. Однако gRPC-Web работает как с HTTP/1.1, так и с HTTP/2. Некоторые платформы, например UWP или Unity, не могут использовать HTTP/2. Чтобы обеспечить поддержку всех клиентских приложений, настройте сервер для включения HTTP/1.1 и HTTP/2.
Обновите протокол умолчанию в файле appsettings.json
:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
Как вариант, вы можете настроить конечные точки Kestrel в коде запуска.
Чтобы включить HTTP/1.1 и HTTP/2 на одном порте, требуется TLS для согласования протокола. Дополнительные сведения см. в разделе Согласование протокола ASP.NET Core.
Вызов gRPC-Web из браузера
Приложения браузера могут использовать gRPC-Web для вызова служб gRPC. При вызове служб gRPC с помощью gRPC-Web из браузера существует ряд требований и ограничений.
- Сервер должен содержать конфигурацию для поддержки gRPC-Web.
- Потоковая передача клиента и вызовы двунаправленной потоковой передачи не поддерживаются. Потоковая передача сервера поддерживается.
- Для вызова служб gRPC в другом домене требуется настроить CORS на сервере.
Клиент gRPC-Web JavaScript
Существуют клиенты gRPC-Web для JavaScript. Инструкции по использованию gRPC-Web из JavaScript см. в статье, посвященной написанию кода клиента JavaScript с gRPC-Web.
Настройка gRPC-Web с помощью клиента .NET gRPC
Клиент .NET gRPC можно настроить для выполнения вызовов gRPC-Web. Это полезно для приложений Blazor WebAssembly, которые размещаются в браузере и имеют те же ограничения HTTP, что и код JavaScript. Вызов gRPC-Web с помощью клиента .NET выполняется так же, как и для HTTP/2 gRPC. Единственным изменением является то, как создается канал.
Чтобы использовать gRPC-Web:
- добавьте ссылку на пакет
Grpc.Net.Client.Web
; - убедитесь, что используется ссылка на пакет
Grpc.Net.Client
версии 2.29.0 или более поздней; - Настройте канал на использование
GrpcWebHandler
:
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Предыдущий код:
- Настраивает канал для использования gRPC-Web.
- Создает клиент и выполняет вызов с помощью канала.
GrpcWebHandler
имеет следующие параметры конфигурации.
InnerHandler
: базовый HttpMessageHandler объект, который делает HTTP-запрос gRPC, напримерHttpClientHandler
.GrpcWebMode
: тип перечисления, указывающий, являетсяapplication/grpc-web
ли HTTP-запросContent-Type
gRPC илиapplication/grpc-web-text
.GrpcWebMode.GrpcWeb
настраивает отправку содержимого без кодирования. Значение по умолчанию.GrpcWebMode.GrpcWebText
настраивает содержимое в кодировке Base64. Требуется для вызовов потоковой передачи сервера в браузерах.
HttpVersion
: протоколVersion
HTTP, используемый для установки HttpRequestMessage.Version в базовом HTTP-запросе gRPC. gRPC-Web не требует определенной версии и не переопределяет значение по умолчанию, если не указано иное.
Внимание
Созданные клиенты gRPC имеют синхронные и асинхронные методы для вызова унарных методов. Например, SayHello
является синхронным, а SayHelloAsync
— асинхронным. Асинхронные методы всегда требуются в Blazor WebAssembly. Вызов синхронного метода в приложении Blazor WebAssembly приведет к тому, что приложение перестанет отвечать на запросы.
Использование фабрики клиента gRPC с gRPC-Web
Создайте клиент .NET, совместимый с gRPC-Web, с помощью фабрики клиентов gRPC:
- Добавьте ссылки на пакеты в файл проекта для следующих пакетов:
- Зарегистрируйте клиент gRPC с внедрением зависимостей (DI) с помощью универсального метода расширения
AddGrpcClient
. В приложении Blazor WebAssembly службы регистрируются с внедрением зависимостей вProgram.cs
. - Настройте
GrpcWebHandler
с помощью метода расширения ConfigurePrimaryHttpMessageHandler.
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
Дополнительные сведения см. в статье Интеграция фабрики клиента gRPC в .NET.
Дополнительные ресурсы
Узнайте, как настроить существующую службу ASP.NET Core gRPC для вызовов из приложений браузера с использованием протокола gRPC-Web. gRPC-Web позволяет приложениям JavaScript и Blazor на основе браузера вызывать службы gRPC. Вызвать службу HTTP/2 gRPC из приложения на основе браузера нельзя. Службы gRPC, размещенные в ASP.NET Core, можно настроить на поддержку gRPC-Web вместе с HTTP/2 gRPC.
См. раздел Добавление служб gRPC в приложение ASP.NET Core.
Инструкции по созданию проекта gRPC см. в статье Создание клиента и сервера .NET Core gRPC в ASP.NET Core.
Сравнение ASP.NET Core gRPC-Web с Envoy
Существует два способа добавления gRPC-Web в приложение ASP.NET Core.
- Поддержка gRPC-Web вместе с gRPC HTTP/2 в ASP.NET Core. Этот параметр использует ПО промежуточного слоя, предоставленное пакетом
Grpc.AspNetCore.Web
. - Используйте поддержку gRPC-Web в прокси-сервере Envoy, чтобы транслировать gRPC-Web в gRPC HTTP/2. Затем переведенный вызов перенаправляется в приложение ASP.NET Core.
Есть свои плюсы и минусы этого подхода. Если среда приложения уже использует Envoy в качестве прокси-сервера, имеет смысл использовать Envoy и для предоставления поддержки gRPC-Web. Если требуется простое решение для gRPC-Web, для которого требуется только ASP.NET Core, используйте Grpc.AspNetCore.Web
.
Настройка gRPC-Web в ASP.NET Core
Службы gRPC, размещенные в ASP.NET Core, можно настроить на поддержку gRPC-Web вместе с HTTP/2 gRPC. gRPC-Web не требует вносить изменения в службы. Единственного изменения потребует конфигурация запуска.
Чтобы включить gRPC-Web со службой gRPC ASP.NET Core, выполните следующие действия.
- добавьте ссылку на пакет
Grpc.AspNetCore.Web
; - Настройте приложение для использования gRPC-Web, добавив
UseGrpcWeb
иEnableGrpcWeb
вStartup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb(); // Must be added between UseRouting and UseEndpoints
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
});
}
Предыдущий код:
- Добавляет ПО промежуточного слоя gRPC-Web (
UseGrpcWeb
) после маршрутизации и перед конечными точками. - Указывает, что метод
endpoints.MapGrpcService<GreeterService>()
поддерживает gRPC-Web сEnableGrpcWeb
.
Можно также настроить ПО промежуточного слоя gRPC-Web, чтобы все службы поддерживали gRPC-Web по умолчанию и не нужно было использовать EnableGrpcWeb
. Укажите new GrpcWebOptions { DefaultEnabled = true }
при добавлении ПО промежуточного слоя.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
}
Примечание.
Существует известная ошибка, приводящая к сбою gRPC-Web при размещении с помощью HTTP.sys в .NET Core 3.x.
Временное решение для запуска gRPC-Web на HTTP.sys доступно в разделе Экспериментальное использование gRPC-Web и UseHttpSys() (grpc/grpc-dotnet № 853).
gRPC-Web и CORS
Система безопасности браузера предотвращает запросы веб-страницы к другому домену, отличному от того, который обслуживает веб-страницу. Это ограничение применяется к вызовам gRPC-Web с приложениями браузера. Например, приложение браузера, обслуживаемое https://www.contoso.com
, блокирует вызов служб gRPC-Web, размещенных на https://services.contoso.com
. Можно использовать общий доступ к ресурсам независимо от источника (CORS), чтобы ослабить это ограничение.
Чтобы разрешить приложению браузера вызывать gRPC-Web независимо от источника, настройте CORS в ASP.NET Core. Используйте встроенную поддержку CORS и предоставьте заголовки, относящиеся к gRPC, с помощью WithExposedHeaders.
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb()
.RequireCors("AllowAll");
});
}
Предыдущий код:
- Вызывает
AddCors
для добавления служб CORS и настройки политики CORS, которая предоставляет заголовки, относящиеся к gRPC. - Вызывает
UseCors
для добавления ПО промежуточного слоя CORS после настройки маршрутизации и перед настройкой конечных точек. - Указывает, что метод
endpoints.MapGrpcService<GreeterService>()
поддерживает CORS сRequireCors
.
gRPC-Web и потоковая передача
Традиционный протокол gRPC на основе HTTP/2 поддерживает клиентскую, серверную и двунаправленную потоковую передачу. gRPC-Web имеет ограниченную поддержку потоковой передачи:
- Клиенты браузера с gRPC-Web не поддерживают вызов методов потоковой передачи клиента и двунаправленной потоковой передачи.
- Клиенты .NET с gRPC-Web не поддерживают вызов на клиенте методов потоковой передачи и двунаправленной потоковой передачи по протоколу HTTP/1.1.
- Службы gRPC в ASP.NET Core, размещенные в Службе приложений Azure и IIS, не поддерживают двунаправленную потоковую передачу.
При использовании gRPC-Web мы рекомендуем применять только унарные методы и методы серверной потоковой передачи.
Протокол HTTP
Шаблон службы ASP.NET Core gRPC, включенный в пакет SDK для .NET, создает приложение, настроенное только для HTTP/2. Это хорошая настройка по умолчанию, если приложение поддерживает только традиционный протокол gRPC на основе HTTP/2. Однако gRPC-Web работает как с HTTP/1.1, так и с HTTP/2. Некоторые платформы, например UWP или Unity, не могут использовать HTTP/2. Чтобы обеспечить поддержку всех клиентских приложений, настройте сервер для включения HTTP/1.1 и HTTP/2.
Обновите протокол умолчанию в файле appsettings.json
:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
Как вариант, вы можете настроить конечные точки Kestrel в коде запуска.
Чтобы включить HTTP/1.1 и HTTP/2 на одном порте, требуется TLS для согласования протокола. Дополнительные сведения см. в разделе Согласование протокола ASP.NET Core.
Вызов gRPC-Web из браузера
Приложения браузера могут использовать gRPC-Web для вызова служб gRPC. При вызове служб gRPC с помощью gRPC-Web из браузера существует ряд требований и ограничений.
- Сервер должен содержать конфигурацию для поддержки gRPC-Web.
- Потоковая передача клиента и вызовы двунаправленной потоковой передачи не поддерживаются. Потоковая передача сервера поддерживается.
- Для вызова служб gRPC в другом домене требуется настроить CORS на сервере.
Клиент gRPC-Web JavaScript
Существуют клиенты gRPC-Web для JavaScript. Инструкции по использованию gRPC-Web из JavaScript см. в статье, посвященной написанию кода клиента JavaScript с gRPC-Web.
Настройка gRPC-Web с помощью клиента .NET gRPC
Клиент .NET gRPC можно настроить для выполнения вызовов gRPC-Web. Это полезно для приложений Blazor WebAssembly, которые размещаются в браузере и имеют те же ограничения HTTP, что и код JavaScript. Вызов gRPC-Web с помощью клиента .NET выполняется так же, как и для HTTP/2 gRPC. Единственным изменением является то, как создается канал.
Чтобы использовать gRPC-Web:
- добавьте ссылку на пакет
Grpc.Net.Client.Web
; - убедитесь, что используется ссылка на пакет
Grpc.Net.Client
версии 2.29.0 или более поздней; - Настройте канал на использование
GrpcWebHandler
:
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
Предыдущий код:
- Настраивает канал для использования gRPC-Web.
- Создает клиент и выполняет вызов с помощью канала.
GrpcWebHandler
имеет следующие параметры конфигурации.
InnerHandler
: базовый HttpMessageHandler объект, который делает HTTP-запрос gRPC, напримерHttpClientHandler
.GrpcWebMode
: тип перечисления, указывающий, являетсяapplication/grpc-web
ли HTTP-запросContent-Type
gRPC илиapplication/grpc-web-text
.GrpcWebMode.GrpcWeb
настраивает отправку содержимого без кодирования. Значение по умолчанию.GrpcWebMode.GrpcWebText
настраивает содержимое в кодировке Base64. Требуется для вызовов потоковой передачи сервера в браузерах.
HttpVersion
: протоколVersion
HTTP, используемый для установки HttpRequestMessage.Version в базовом HTTP-запросе gRPC. gRPC-Web не требует определенной версии и не переопределяет значение по умолчанию, если не указано иное.
Внимание
Созданные клиенты gRPC имеют синхронные и асинхронные методы для вызова унарных методов. Например, SayHello
является синхронным, а SayHelloAsync
— асинхронным. Асинхронные методы всегда требуются в Blazor WebAssembly. Вызов синхронного метода в приложении Blazor WebAssembly приведет к тому, что приложение перестанет отвечать на запросы.
Использование фабрики клиента gRPC с gRPC-Web
Создайте клиент .NET, совместимый с gRPC-Web, с помощью фабрики клиентов gRPC:
- Добавьте ссылки на пакеты в файл проекта для следующих пакетов:
- Зарегистрируйте клиент gRPC с внедрением зависимостей (DI) с помощью универсального метода расширения
AddGrpcClient
. В приложении Blazor WebAssembly службы регистрируются с внедрением зависимостей вProgram.cs
. - Настройте
GrpcWebHandler
с помощью метода расширения ConfigurePrimaryHttpMessageHandler.
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
Дополнительные сведения см. в статье Интеграция фабрики клиента gRPC в .NET.
Дополнительные ресурсы
ASP.NET Core