如何使用C#创建gRPC流式拦截器?
我已经知道如何创建一元RPC拦截器,但我不知道如何制作流式RPC拦截器。 这就是我迄今为止所做的:如何使用C#创建gRPC流式拦截器?,c#,.net,grpc,interceptor,grpc-dotnet,C#,.net,Grpc,Interceptor,Grpc Dotnet,我已经知道如何创建一元RPC拦截器,但我不知道如何制作流式RPC拦截器。 这就是我迄今为止所做的: public override async Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>( IAsyncStreamReader<TRequest> requestStream, ServerCallContext context, Client
public override async Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>(
IAsyncStreamReader<TRequest> requestStream, ServerCallContext context,
ClientStreamingServerMethod<TRequest, TResponse> continuation)
{
Console.WriteLine("ClientStreaming");
var response = await base.ClientStreamingServerHandler(requestStream, context, continuation);
return response;
}
public覆盖异步任务ClientStreamingServerHandler(
IAsyncStreamReader请求流,ServerCallContext上下文,
ClientStreamingServer方法(续)
{
Console.WriteLine(“客户端流媒体”);
var response=await base.ClientStreamingServerHandler(requestStream、context、continuation);
返回响应;
}
这段代码在每次启动客户端流时都会截取控制台日志,我就是不知道如何在控制台中记录每个传入的客户端消息
Jesse我有一个与您最近类似的场景,下面是我如何用拦截器解决它的。我们需要通过GRPCAPI测量消息吞吐量/消息大小。一元呼叫非常直截了当,但在流媒体方面遇到了问题。下面是我拦截流所做的工作(在我的例子中,服务器应该与您的场景类似) 第一段代码是您已经拥有的拦截器方法(这是服务器流)
公共覆盖AsyncServerStreamingCall AsyncServerStreamingCall(TRequest请求,
ClientInterceptorContext上下文,
AsyncServerStreamingCallContinuation(续)
{
//将传出消息大小添加到度量中
mCollector.Add(mInterceptorName,context.Method.ServiceName,context.Method.Name,networkmetricscolectionservice.DIRECTION.OUT,请求为IMessage);
//此调用返回服务器流以及服务器流读取器
//返回给客户端使用。
var prelimResponse=base.AsyncServerStreamingCall(请求、上下文、继续);
//将结果消息大小添加到度量中
mCollector.Add(mInterceptorName,context.Method.ServiceName,context.Method.Name,networkmetricscolectionservice.DIRECTION.IN,prelimResponse作为IMessage);
//用我们的实现包装响应流对象,该实现将记录大小,然后
//将其代理给客户端。
var response=新的AsyncServerStreamingCall(新的AsyncStreamReaderRapper(prelimResponse.ResponseStream),
mInterceptorName,
context.Method.ServiceName,
context.Method.Name,mCollector),
prelimResponse.ResponseHeaderAsync,
prelimResponse.GetStatus,
prelimResponse.GetTrailers,
预响应(处理);
//将包装好的流返回给客户端
返回响应;
}
AsyncServerStreamReaderRapper实现接收对象,测量并记录其大小,然后将其传递给客户端。这个包装器是必需的,因为流读取器只能有一个使用者,如果我有多个读取器,就会生成一个错误,这是有道理的
/// <summary>
/// Wrapper class around the gRPC AsyncStreamReader class that allows retrieval of the object
/// before handing off to the client for the purpose of throughput measurements and metrics
/// collection
/// </summary>
/// <typeparam name="T">type of object contained within the stream</typeparam>
public class AsyncStreamReaderWrapper<T> : IAsyncStreamReader<T>
{
private IAsyncStreamReader<T> mInnerImplementation = null;
private NetworkMetricsCollectionService mCollector = null;
private string mId = string.Empty;
private string mService = string.Empty;
private string mMethod = string.Empty;
public T Current => mInnerImplementation.Current;
/// <summary>
/// Advances the reader to the next element in the sequence, returning the result asynchronously.
/// </summary>
/// <param name="cancellationToken">Cancellation token that can be used to cancel the
/// operation.</param>
/// <returns>Task containing the result of the operation: true if the reader was successfully
/// advanced to the next element; false if the reader has passed the end of the sequence.</returns>
public async Task<bool> MoveNext(CancellationToken cancellationToken)
{
bool result = await mInnerImplementation.MoveNext(cancellationToken);
if (result)
{
mCollector.Add(mId,mService, mMethod, NetworkMetricsCollectionService.DIRECTION.IN, Current as IMessage);
}
return result;
}
/// <summary>
/// Parameterized Constructor
/// </summary>
/// <param name="aInnerStream">inner stream reader to wrap</param>
/// <param name="aService">service name for metrics reporting</param>
/// <param name="aMethod">method name for metrics reporting</param>
/// <param name="aCollector">metrics collector</param>
public AsyncStreamReaderWrapper(IAsyncStreamReader<T> aInnerStream, string aId, string aService, string aMethod, NetworkMetricsCollectionService aCollector)
{
mInnerImplementation = aInnerStream;
mId = aId;
mService = aService;
mMethod = aMethod;
mCollector = aCollector;
}
}
//
///gRPC AsyncStreamReader类周围的包装器类,该类允许检索对象
///在交付给客户进行吞吐量测量和度量之前
///收藏
///
///流中包含的对象的类型
公共类AsyncStreamReaderRapper:IAsyncStreamReader
{
私有IAsyncStreamReader MinneImplementation=null;
专用网络MetricsCollectionService mCollector=null;
私有字符串mId=string.Empty;
私有字符串mService=string.Empty;
私有字符串mMethod=string.Empty;
公共T Current=>mInnerImplementation.Current;
///
///使读取器前进到序列中的下一个元素,异步返回结果。
///
///可用于取消的取消令牌
///手术。
///包含操作结果的任务:如果读卡器成功运行,则为true
///前进到下一个元素;如果读取器已通过序列末尾,则为false。
公共异步任务MoveNext(CancellationToken CancellationToken)
{
bool result=wait mInnerImplementation.MoveNext(cancellationToken);
如果(结果)
{
mCollector.Add(mId、MSService、mMethod、NetworkMetricsCollectionService.DIRECTION.IN,当前为IMessage);
}
返回结果;
}
///
///参数化构造函数
///
///要包装的内部流读取器
///度量报告的服务名称
///度量报告的方法名称
///度量收集器
公共AsyncStreamReaderRapper(IAsyncStreamReader ainerStream、字符串辅助、字符串服务、字符串方法、NetworkMetricsCollectionService acCollector)
{
mInnerImplementation=AinerStream;
mId=援助;
mService=aService;
方法=方法;
mCollector=收集器;
}
}
我知道这不是您正在寻找的确切场景,但我相信您的实现将是类似的,但是使用StreamWriter而不是StreamReader
/// <summary>
/// Wrapper class around the gRPC AsyncStreamReader class that allows retrieval of the object
/// before handing off to the client for the purpose of throughput measurements and metrics
/// collection
/// </summary>
/// <typeparam name="T">type of object contained within the stream</typeparam>
public class AsyncStreamReaderWrapper<T> : IAsyncStreamReader<T>
{
private IAsyncStreamReader<T> mInnerImplementation = null;
private NetworkMetricsCollectionService mCollector = null;
private string mId = string.Empty;
private string mService = string.Empty;
private string mMethod = string.Empty;
public T Current => mInnerImplementation.Current;
/// <summary>
/// Advances the reader to the next element in the sequence, returning the result asynchronously.
/// </summary>
/// <param name="cancellationToken">Cancellation token that can be used to cancel the
/// operation.</param>
/// <returns>Task containing the result of the operation: true if the reader was successfully
/// advanced to the next element; false if the reader has passed the end of the sequence.</returns>
public async Task<bool> MoveNext(CancellationToken cancellationToken)
{
bool result = await mInnerImplementation.MoveNext(cancellationToken);
if (result)
{
mCollector.Add(mId,mService, mMethod, NetworkMetricsCollectionService.DIRECTION.IN, Current as IMessage);
}
return result;
}
/// <summary>
/// Parameterized Constructor
/// </summary>
/// <param name="aInnerStream">inner stream reader to wrap</param>
/// <param name="aService">service name for metrics reporting</param>
/// <param name="aMethod">method name for metrics reporting</param>
/// <param name="aCollector">metrics collector</param>
public AsyncStreamReaderWrapper(IAsyncStreamReader<T> aInnerStream, string aId, string aService, string aMethod, NetworkMetricsCollectionService aCollector)
{
mInnerImplementation = aInnerStream;
mId = aId;
mService = aService;
mMethod = aMethod;
mCollector = aCollector;
}
}