// 引入proto文件
// 公共messages.proto
syntax = "proto3";
option csharp_namespace = "GrpcProject";
package grpc.serviceing;
// 请求体
message ServerRequest{
string name = 1;
double height = 2;
int32 age = 3;
bool flag = 4;
float x = 5;
float y = 6;
float z= 7;
repeated string departments = 8;
}
message ServerFileRequest{
bytes fileBytes = 1;
}
// 响应体
message ServerResponse{
bool result = 1;
}
// 服务dollar.proto文件
syntax = "proto3";
import "google/protobuf/empty.proto";
import "Protos/messages.proto";
option csharp_namespace = "GrpcProject";
package grpc.serviceing;
service DollarRpc{
rpc ServerOne (ServerRequest) returns (ServerResponse);
rpc ServerTwo (ServerRequest) returns (google.protobuf.Empty);
}
服务端接口实现:
public class DollarService : DollarRpc.DollarRpcBase
{
public override async Task ServerOne(ServerRequest request, ServerCallContext context)
{
await Console.Out.WriteLineAsync("-------------------------ServerOne------------------------------\r\n");
await Task.Delay(TimeSpan.FromSeconds(8), context.CancellationToken);
foreach (var prop in request.GetType().GetProperties())
{
await Console.Out.WriteLineAsync($"property name:{prop.Name};value:{prop.GetValue(request)}");
}
return GetResponse();
}
public override async Task ServerTwo(ServerRequest request, ServerCallContext context)
{
await Console.Out.WriteLineAsync("-------------------------ServerTwo------------------------------\r\n");
await Task.Delay(TimeSpan.FromSeconds(8), context.CancellationToken);
foreach (var prop in request.GetType().GetProperties())
{
await Console.Out.WriteLineAsync($"property name:{prop.Name};value:{prop.GetValue(request)}");
}
return new();
}
private ServerResponse GetResponse() => new() { Result = true };
}
客户端实现重点:
// program.cs
builder.Services.AddGrpcClient(options =>
{
options.Address = new Uri("https://localhost:7188");
}).EnableCallContextPropagation();
//拦截器过滤截止时间
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class GrpcFilterAttribute : Attribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
CancellationTokenSource tokenSource = new();
GrpcServerCallContextFeature callContext = new(DateTime.UtcNow.AddSeconds(5), tokenSource.Token);
context.HttpContext.Features.Set(callContext);
}
}
public class GrpcServerCallContextFeature : ServerCallContext, IServerCallContextFeature
{
///
/// 构造
///
///
///
public GrpcServerCallContextFeature(DateTime deadline, CancellationToken cancellationToken)
{
DeadlineCore = deadline;
CancellationTokenCore = cancellationToken;
AuthContextCore = new AuthContext(null, new Dictionary>());
}
public ServerCallContext ServerCallContext => this;
protected override string MethodCore { get; }
protected override string HostCore { get; }
protected override string PeerCore { get; }
protected override DateTime DeadlineCore { get; }
protected override Metadata RequestHeadersCore { get; }
protected override CancellationToken CancellationTokenCore { get; }
protected override Metadata ResponseTrailersCore { get; }
protected override Status StatusCore { get; set; }
protected override WriteOptions? WriteOptionsCore { get; set; }
protected override AuthContext AuthContextCore { get; }
protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions? options)
{
return base.CreatePropagationToken(options);
}
protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders)
{
throw new NotImplementedException();
}
}
//调用
// 在相应的类上打上标记 [GrpcFilter]
[Route("api/[controller]")]
[ApiController]
[GrpcFilter] // 设定截止时间过滤
public class GrpcTestController : ControllerBase
{
private readonly DollarRpc.DollarRpcClient _dollarRpcClient;
public GrpcTestController(DollarRpc.DollarRpcClient dollarRpcClient) => _dollarRpcClient = dollarRpcClient;
[HttpGet("one")]
public async Task GetOneResult()
{
ServerRequest request = new ServerRequest()
{
Departments = {
"one","two","three","four","five"
},
Age = 10,
Flag = true,
Height = 10,
Name = "zhangsan",
X = 10F,
Y = 11F,
Z = 12F
};
try
{
var response = await _dollarRpcClient.ServerOneAsync(request);
if (response.Result)
{
return "Success";
}
return "Fail";
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.DeadlineExceeded)
{
return "dealine timeout.";
}
catch (RpcException ex)
{
return ($"NoResult:{ex.Message}");
}
}
[HttpGet("two")]
public async Task GetTwoResult()
{
ServerRequest request = new ServerRequest()
{
Departments = {
"one","two","three","four","five"
},
Age = 10,
Flag = true,
Height = 10,
Name = "zhangsan",
X = 10F,
Y = 11F,
Z = 12F
};
try
{
var response = await _dollarRpcClient.ServerTwoAsync(request);
return "Success";
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.DeadlineExceeded)
{
return "dealine timeout.";
}
catch (RpcException ex)
{
return ($"NoResult:{ex.Message}");
}
}
}
服务端One:
客户端One:
swagger:
另一个Two效果类似。同时服务端任务取消错误,也在截图上有显示。
链接:https://pan.baidu.com/s/1vleChFc3F6ILs-5ad8xQCA
提取码:mud0