You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Dapr + .NET Aspire搭建gRPC服务间调用遇阻求助

Aspire + Dapr gRPC服务调用失败问题求助

我已按照Aspire官方Dapr HTTP客户端示例完成配置,但gRPC场景下服务间调用无法正常运行。已通过.proto文件完成服务端与客户端的代码生成,不过客户端发起请求时触发内部服务器错误,报错信息如下:

RpcException: Status(StatusCode="Internal", Detail: "failed to invoke, id: service2, err: rpc error: code = Internal desc = error invoking app channel: rpc error: code = InvalidArgument desc = missing HTTP extension field")

InvocationException: An exception occurred while invoking method: 'SayHello' on app-id: 'service2'
Dapr.Client.DarpClientGrpc.InvokeMethodGrpcAsync<TRequest, TResponse>(string appId, string methodName, TRequest data, CancellationToken cancellationToken)

推测问题原因可能是默认协议为HTTP,需要指定gRPC端点调用,或者需要创建拦截器发送路由所需的额外元数据。

请问是否有经官方验证、可在Aspire环境下稳定运行的gRPC + Dapr调用方案?目前相关文档不完善,现有示例的类似配置在使用protobuf生成的gRPC客户端时往往无法正常工作,这个方案也能帮助其他遇到同样问题的开发者。


当前配置代码示例

AppHost 配置

using CommunityToolkit.Aspire.Hosting.Dapr;
using System.Security.Cryptography;

var builder = DistributedApplication.CreateBuilder(args);

var stateStore = builder.AddDaprStateStore("statestore");
var pubSub = builder.AddDaprPubSub("pubsub");

var bytes = new byte[50];
RandomNumberGenerator.Fill(bytes);
var daprApiKey = string.Join("", bytes.Select(b => b.ToString("x2")));

builder.AddProject<Projects.TestService1>("service1")
    .WithDaprSidecar(b => b.WithOptions(new DaprSidecarOptions(){Config = $"../{nameof(Projects.TestService1)}/resources/dapr/config.yaml",}).WithAnnotation(new EnvironmentCallbackAnnotation("APP_API_TOKEN", () => daprApiKey)))
    .WithReference(stateStore)
    .WithEnvironment("APP_API_TOKEN", daprApiKey)
    .WithReference(pubSub);

builder.AddProject<Projects.TestService2>("service2")
    .WithDaprSidecar(b => b.WithOptions(new DaprSidecarOptions(){Config = $"../{nameof(Projects.TestService2)}/resources/dapr/config.yaml",}).WithAnnotation(new EnvironmentCallbackAnnotation("APP_API_TOKEN", () => daprApiKey)))
    .WithReference(stateStore)
    .WithEnvironment("APP_API_TOKEN", daprApiKey)
    .WithReference(pubSub);
 // ...
}

Service 1 (调用方) 代码

using Dapr.Client;
using Grpc.Core;
using Grpc.Net.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TestService1.Clients;
using TestService2;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddOpenApi();
builder.Services.AddDaprClient();

// Adds Dapr authentication. By default, the token will be read from the APP_API_TOKEN environment variable.
builder.Services.AddAuthentication().AddDapr();

builder.Services.AddAuthorization(options =>
{
    // Adds Dapr authorization. The authentication scheme is "Dapr."
    options.AddDapr();
});

var invoker = DaprClient.CreateInvocationInvoker(appId: "service2", daprApiToken:Environment.GetEnvironmentVariable("APP_API_TOKEN"));
var greetClient = new Greeter.GreeterClient(invoker);

builder.Services.AddSingleton<Greeter.GreeterClient>(greetClient);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();

app.MapGet("/weatherforecast", async (DaprClient client, [FromQuery] int pageSize = 10) =>
    {
        return await new WeatherClient(client).GetWeatherForecastAsync(pageSize);
    })
    .WithName("GetWeatherForecast");

app.MapGet("/greet", async (DaprClient client, [FromQuery] string name) =>
    {
        return await client.InvokeMethodGrpcAsync<HelloRequest, HelloReply>("service2", "SayHello", new HelloRequest { Name = name });
        //return await client.SayHelloAsync(new HelloRequest() { Name = name });
    })
    .WithName("GetGreet");

app.Run();

public record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
//...

Service 1 项目文件

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net9.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Dapr.AspNetCore" Version="1.15.2" />
        <PackageReference Include="Dapr.Client" Version="1.15.2" />
        <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2"/>
        <PackageReference Include="Grpc.Tools" Version="2.36.1">
            <PrivateAssets>all</PrivateAssets>
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
    </ItemGroup>

    <ItemGroup>
        <Protobuf Include="../TestService2/resources/protos/greet.proto" GrpcServices="Server,Client" />
    </ItemGroup>
</Project>

Service 2 (被调用方) 代码

using Grpc.Net.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using System.Reflection;
using TestService2.Controllers.GRPC;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddOpenApi();
builder.Services.AddDaprClient();
builder.Services.AddGrpc();
builder.Services.AddControllers();

// Adds Dapr authentication. By default, the token will be read from the APP_API_TOKEN environment variable.
builder.Services.AddAuthentication().AddDapr();

builder.Services.AddAuthorization(options =>
{
    // Adds Dapr authorization. Authentication scheme is "Dapr"
    options.AddDapr();
});


var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseAuthentication();
app.UseAuthorization();

//app.UseHttpsRedirection();

//app.UseRouting();

app.MapGrpcService<GreeterService>();

app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client.");

app.MapControllers();

app.Run();

Service 2 项目文件

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net9.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Dapr.AspNetCore" Version="1.15.2" />
        <PackageReference Include="Grpc.AspNetCore.Server" Version="2.70.0" />
        <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2"/>
        <PackageReference Include="Grpc.Tools" Version="2.36.1">
            <PrivateAssets>all</PrivateAssets>
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
    </ItemGroup>

    <ItemGroup>
        <Protobuf Include="resources/protos/greet.proto" GrpcServices="Server,Client" />
    </ItemGroup>

</Project>

补充说明:浏览器请求Service 2,再由Service 2请求Service 1。已成功搭建Aspire环境下基于HTTP协议的Dapr Sidecar服务间调用,但gRPC场景始终失败。


内容的提问来源于stack exchange,提问作者Brevyn Kurt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:27:32