【问题标题】:GRPC service instantiated per call每次调用都会实例化 GRPC 服务
【发布时间】:2020-11-17 16:05:11
【问题描述】:

我在 .NET core 3.1 下创建了一个 GRPC 服务主机(使用来自 https://github.com/grpc/grpc-dotnet 的 Grpc.AspNetCore v2.30)。通过在“ProxyService”构造函数中放置断点,我可以看到每次调用都会实例化该类 - 每次来自客户端的 GRPC 调用时,都会触发断点。如何将其配置为始终使用相同的 ProxyService 实例?

这些是程序和启动类:

    class Program
    {
        const int _port = 23456;

        static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
            Console.WriteLine("started - press any key to quit...");
            Console.ReadKey();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureKestrel(options =>
                    {
                        options.ConfigureEndpointDefaults(o =>
                        {
                            o.Protocols = HttpProtocols.Http2;
                            
                        });
                        options.ListenAnyIP(_port);
                    });
                    webBuilder.UseStartup<Startup>();
                });
    }

    public class ProxyService : StreamingApi.Protos.StreamingApi.StreamingApiBase
    {
        public ProxyService()
        {
    // gets here with every client call
        }

        public override Task<UpdateResponse> Update(UpdateRequest request, ServerCallContext context)
        {
            return Task.FromResult(new UpdateResponse());
        }
    }

   class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddGrpc();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGrpcService<ProxyService>();
            });
        }
    }

【问题讨论】:

  • 你为什么要这样做?理想情况下,您的构造函数应该包含零成本逻辑,例如依赖关系链接。其他一切都应该在 Update 方法中或在您的服务启动之前发生。
  • 作为起点 - 我想测量处理的调用数量并每 1 秒将它们打印到控制台,因此我无法添加线程以保持不变并在循环中执行此操作。这个可以配置吗?
  • 这是共享资源。您应该定义将保存聚合值并且是静态的依赖接口。

标签: c# .net-core grpc


【解决方案1】:

首先,让我猜猜你为什么要这样做:

  • 您在 ProxyService 内部有一些繁重的逻辑,例如某种初始化;
  • 您有一些静态变量要在调用之间共享;

要解决第一种情况,您应该使用任一方法本身:

    public ProxyService(IFooBar foobar)
    {
        this.foobar = foobar;
    }
    public override Task<UpdateResponse> Update(UpdateRequest request, ServerCallContext context)
    {
        await this.foobar.InitializeAsync();
        return Task.FromResult(new UpdateResponse());
    }

或系统中的其他触发器,例如“服务启动时”:

    public interface IFooBarInitilizer :IHostedService
    {
    }
    public class FooBarInitilizer : IFooBarInitilizer 
    {
        public async Task StartAsync(CancellationToken token){ await this.foobar.InitializeAsync(); }
    }

    //in your Configure
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
        services.AddSingleton<IFooBarInitializer, FooBarInitializer>();
        services.AddHostedService(x=> x.GetService<IFooBarInitializer>());
    }

第二种情况更简单,因为你可以通过接口依赖指定你的共享资源:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
        services.AddSingleton<IFooBarResource, FooBarResource>();
    }

    
public class ProxyService : StreamingApi.Protos.StreamingApi.StreamingApiBase
{
    public ProxyService(IFooBarResource myStaticResource)
    {
        this.myStaticResource = myStaticResource;
    }

    public override Task<UpdateResponse> Update(UpdateRequest request, ServerCallContext context)
    {
        var somethingGood = this.myStaticResource.GetMeSomethingGood();
        return Task.FromResult(new UpdateResponse());
    }
}

【讨论】:

  • 谢谢 - 看起来像我正在寻找的解决方案。仅用于知识 - 是否有服务配置允许其他方法进行服务实例化,而不是像 WCF 中的每次调用?
  • 我没怎么使用 grpc,但是你可以通过在 IServiceCollection 中指定生命周期依赖来做到这一点(每次调用、每次会话、每次数据库调用、当前日期时间中的偶数计数等) .由于在所有现代 IDE 中集成了自动完成功能,这将容易得多。阅读有关 IoC 和 DI 的更多信息,以轻松管理业务实体的生命周期。
  • 谢谢 - 我实际上是指您没有注册的 ProxyService 本身
  • 是的,我明白了,但遗憾的是没有找到任何快速参考,所以这可能意味着你应该通过 DI 来做,至少它会比一些属性驱动的技术更直接。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 2019-07-02
  • 1970-01-01
  • 2020-01-22
  • 1970-01-01
相关资源
最近更新 更多