Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C#创建gRPC流式拦截器?_C#_.net_Grpc_Interceptor_Grpc Dotnet - Fatal编程技术网

如何使用C#创建gRPC流式拦截器?

如何使用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

我已经知道如何创建一元RPC拦截器,但我不知道如何制作流式RPC拦截器。 这就是我迄今为止所做的:

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;
      }
   }