All Projects → max-ieremenko → ServiceModel.Grpc

max-ieremenko / ServiceModel.Grpc

Licence: Apache-2.0 license
Code-first for gRPC

Programming Languages

C#
18002 projects
powershell
5483 projects

Projects that are alternatives of or similar to ServiceModel.Grpc

Wcf
This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services.
Stars: ✭ 1,537 (+2301.56%)
Mutual labels:  wcf
Audit.net
An extensible framework to audit executing operations in .NET and .NET Core.
Stars: ✭ 1,647 (+2473.44%)
Mutual labels:  wcf
OpenRiaServices
The Open RIA Services project continues what was previously known as WCF RIA Services.
Stars: ✭ 30 (-53.12%)
Mutual labels:  wcf
Security
ASP.NET Security Providers for CloudFoundry
Stars: ✭ 27 (-57.81%)
Mutual labels:  wcf
T2TiERP-2-CSharp
T2Ti ERP 2.0 - C#
Stars: ✭ 33 (-48.44%)
Mutual labels:  wcf
WcfSoapLogger
Capture SOAP request and response in C# WCF
Stars: ✭ 26 (-59.37%)
Mutual labels:  wcf
Crema
Meta data server & client tools for game development
Stars: ✭ 61 (-4.69%)
Mutual labels:  wcf
coreipc
WCF-like service model API for communication over named pipes and TCP. .NET and node.js clients.
Stars: ✭ 22 (-65.62%)
Mutual labels:  wcf
SmartHotel360-Registration
SmartHotel360 - Registration (AKS with Windows Containers)
Stars: ✭ 28 (-56.25%)
Mutual labels:  wcf
Northwindtraders
Northwind Traders is a sample application built using ASP.NET Core and Entity Framework Core.
Stars: ✭ 4,628 (+7131.25%)
Mutual labels:  code-first
Udemy-MyEvernote-Sample-Project
ASP.NET MVC Yazılımcıların Yükselişi eğitimim için hazırladığım örnek proje.
Stars: ✭ 66 (+3.13%)
Mutual labels:  code-first
nestjs-prisma-starter
Starter template for NestJS 😻 includes GraphQL with Prisma Client, Passport-JWT authentication, Swagger Api and Docker
Stars: ✭ 1,107 (+1629.69%)
Mutual labels:  code-first
run-aspnetcore-basics retired
One Solution - One Project for web application development with Asp.Net Core & EF.Core. Only one web application project which used aspnetcore components; razor pages, middlewares, dependency injection, configuration, logging. To create websites with minimum implementation of asp.net core based on HTML5, CSS, and JavaScript. You can use this boi…
Stars: ✭ 15 (-76.56%)
Mutual labels:  code-first
uJet
Umbraco Jet (uJet) is a Code First approach to building MVC applications in Umbraco 7.
Stars: ✭ 16 (-75%)
Mutual labels:  code-first
jasyncapi
/jay-sync-api/ is a Java code-first tool for AsyncAPI specification
Stars: ✭ 29 (-54.69%)
Mutual labels:  code-first
graphql2ts
Transform .graphql to graphql-js typescript
Stars: ✭ 41 (-35.94%)
Mutual labels:  code-first
northwind-dotnet
A full-stack .NET 6 Microservices build on Minimal APIs and C# 10
Stars: ✭ 77 (+20.31%)
Mutual labels:  grpc-dotnet

ServiceModel.Grpc

ServiceModel.Grpc enables applications to communicate with gRPC services using a code-first approach (no .proto files), helps to get around limitations of gRPC protocol like "only reference types", "exact one input", "no nulls", "no value-types". Provides exception handling. Helps to migrate existing WCF solution to gRPC with minimum effort.

The library supports lightweight runtime proxy generation via Reflection.Emit and C# source code generation.

The solution is built on top of gRPC C# and grpc-dotnet.

Links

ServiceModel.Grpc at a glance

Declare a service contract

[ServiceContract]
public interface ICalculator
{
    [OperationContract]
    Task<long> Sum(long x, int y, int z, CancellationToken token = default);

    [OperationContract]
    ValueTask<(int Multiplier, IAsyncEnumerable<int> Values)> MultiplyBy(IAsyncEnumerable<int> values, int multiplier, CancellationToken token = default);
}

Client call (Reflection.Emit)

A proxy for the ICalculator service will be generated on demand via Reflection.Emit.

PS> Install-Package ServiceModel.Grpc
// create a channel
var channel = new Channel("localhost", 5000, ...);

// create a client factory
var clientFactory = new ClientFactory();

// request the factory to generate a proxy for ICalculator service
var calculator = clientFactory.CreateClient<ICalculator>(channel);

// call Sum: sum == 6
var sum = await calculator.Sum(1, 2, 3);

// call MultiplyBy: multiplier == 2, values == [] {2, 4, 6}
var (multiplier, values) = await calculator.MultiplyBy(new[] {1, 2, 3}, 2);

Client call (source code generation)

A proxy for the ICalculator service will be generated in the source code.

PS> Install-Package ServiceModel.Grpc.DesignTime
// request ServiceModel.Grpc to generate a source code for ICalculator service proxy
[ImportGrpcService(typeof(ICalculator))]
internal static partial class MyGrpcServices
{
    // generated code ...
    public static IClientFactory AddCalculatorClient(this IClientFactory clientFactory, Action<ServiceModelGrpcClientOptions> configure = null) {}
}

// create a channel
var channel = new Channel("localhost", 5000, ...);

// create a client factory
var clientFactory = new ClientFactory();

// register ICalculator proxy generated by ServiceModel.Grpc.DesignTime
clientFactory.AddCalculatorClient();

// create a new instance of the proxy
var calculator = clientFactory.CreateClient<ICalculator>(channel);

// call Sum: sum == 6
var sum = await calculator.Sum(1, 2, 3);

// call MultiplyBy: multiplier == 2, values == [] {2, 4, 6}
var (multiplier, values) = await calculator.MultiplyBy(new[] {1, 2, 3}, 2);

Implement a service

internal sealed class Calculator : ICalculator
{
    public Task<long> Sum(long x, int y, int z, CancellationToken token) => x + y + z;

    public ValueTask<(int Multiplier, IAsyncEnumerable<int> Values)> MultiplyBy(IAsyncEnumerable<int> values, int multiplier, CancellationToken token)
    {
        var multiplicationResult = DoMultiplication(values, multiplier, token);
        return new ValueTask<(int, IAsyncEnumerable<int>)>((multiplier, multiplicationResult));
    }

    private static async IAsyncEnumerable<int> DoMultiplication(IAsyncEnumerable<int> values, int multiplier, [EnumeratorCancellation] CancellationToken token)
    {
        await foreach (var value in values.WithCancellation(token))
        {
            yield return value * multiplier;
        }
    }
}

Host the service in the asp.net core application

PS> Install-Package ServiceModel.Grpc.AspNetCore
internal sealed class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // enable ServiceModel.Grpc
        services.AddServiceModelGrpc();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseEndpoints(endpoints =>
        {
            // bind Calculator service
            endpoints.MapGrpcService<Calculator>();
        });
    }
}

Integrate with Swagger, see example

UI demo

Host the service in Grpc.Core.Server

PS> Install-Package ServiceModel.Grpc.SelfHost
var server = new Grpc.Core.Server
{
    Ports = { new ServerPort("localhost", 5000, ...) }
};

// bind Calculator service
server.Services.AddServiceModelTransient(() => new Calculator());

Server filters

see example

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    // setup filter life time
    services.AddSingleton<LoggingServerFilter>();

    // attach the filter globally
    services.AddServiceModelGrpc(options =>
    {
        options.Filters.Add(1, provider => provider.GetRequiredService<LoggingServerFilter>());
    });
}

internal sealed class LoggingServerFilter : IServerFilter
{
    private readonly ILoggerFactory _loggerFactory;

    public LoggingServerFilter(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;
    }

    public async ValueTask InvokeAsync(IServerFilterContext context, Func<ValueTask> next)
    {
        // create logger with a service name
        var logger = _loggerFactory.CreateLogger(context.ServiceInstance.GetType().Name);

        // log input
        logger.LogInformation("begin {0}", context.ContractMethodInfo.Name);
        foreach (var entry in context.Request)
        {
            logger.LogInformation("input {0} = {1}", entry.Key, entry.Value);
        }

        try
        {
            // invoke all other filters in the stack and the service method
            await next().ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            // log exception
            logger.LogError("error {0}: {1}", context.ContractMethodInfo.Name, ex);
            throw;
        }

        // log output
        logger.LogInformation("end {0}", context.ContractMethodInfo.Name);
        foreach (var entry in context.Response)
        {
            logger.LogInformation("output {0} = {1}", entry.Key, entry.Value);
        }
    }
}

NuGet feed


Name Package Supported platforms Description
ServiceModel.Grpc Version netstandard2.0/2.1, net461+ main functionality, basic Grpc.Core.Api extensions and ClientFactory. ClientFactory is fully compatible with Grpc.Net.Client.
ServiceModel.Grpc.AspNetCore Version net7.0, net6.0, net5.0, .net core 3.0/3.1+ Grpc.AspNetCore.Server extensions
ServiceModel.Grpc.AspNetCore.Swashbuckle Version net7.0, net6.0, net5.0, .net core 3.0/3.1+ Swagger integration, based on Swashbuckle.AspNetCore
ServiceModel.Grpc.AspNetCore.NSwag Version net7.0, net6.0, net5.0, .net core 3.0/3.1+ Swagger integration, based on NSwag
ServiceModel.Grpc.SelfHost Version netstandard2.0/2.1, net461+ Grpc.Core extensions for self-hosted Grpc.Core.Server
ServiceModel.Grpc.DesignTime Version netstandard2.0/2.1, net461+ C# code generator
ServiceModel.Grpc.MessagePackMarshaller Version netstandard2.0, net7.0, net6.0, net5.0, .net core 3.1 marshaller factory, based on MessagePack serializer
ServiceModel.Grpc.ProtoBufMarshaller Version netstandard2.0/2.1, net7.0, net6.0, net5.0, .net core 3.1, net461+ marshaller factory, based on protobuf-net serializer

Benchmarks

ServiceModel.Grpc is a tiny layer on top of grpc-dotnet, which helps to adapt code-first to gRPC protocol. A serializer makes a picture of the performance.

Benchmark code is available here.

The following benchmarks show the performance for unary call on client and server.

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    Task<SomeObject> PingPong(SomeObject value);
}

value = new SomeObject
{
    StringScalar = "some meaningful text",
    Int32Scalar = 1,
    DateScalar = DateTime.UtcNow,
    SingleScalar = 1.1f,
    Int32Array = new int[100],
    SingleArray = new float[100],
    DoubleArray = new double[100]
};
  • ServiceModelGrpc.DataContract test uses DataContractSerializer

  • ServiceModelGrpc.Protobuf test uses protobuf-net serializer

  • ServiceModelGrpc.MessagePack test uses MessagePack serializer

  • ServiceModelGrpc.proto-emulation test uses Google protobuf serialization, the same as grpc-dotnet. This test is designed to compare numbers between ServiceModelGrpc and grpc-dotnet without the influence of a serializer.

  • grpc-dotnet is a baseline:

service TestServiceNative {
	rpc PingPong (SomeObjectProto) returns (SomeObjectProto);
}

message SomeObjectProto {
	string stringScalar = 1;
	google.protobuf.Timestamp dateScalar = 2;
	float singleScalar = 3;
	int32 int32Scalar = 4;
	repeated float singleArray = 5 [packed=true];
	repeated int32 int32Array = 6 [packed=true];
	repeated double doubleArray = 7 [packed=true];
}

Client async unary call, server is stub

BenchmarkDotNet=v0.13.2, OS=ubuntu 20.04
Intel Xeon CPU E5-2673 v4 2.30GHz, 1 CPU, 2 logical and 2 physical cores
.NET SDK=7.0.100-rc.2.22477.23
  [Host]   : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2
  ShortRun : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2

Job=ShortRun  Platform=X64  Force=True  
Server=False  IterationCount=15  LaunchCount=1  
RunStrategy=Throughput  WarmupCount=3  
Method Mean Error StdDev Op/s Ratio RatioSD Message size Gen0 Allocated Alloc Ratio
ServiceModelGrpc.DataContract 271.24 μs 7.712 μs 7.214 μs 3,686.8 16.81 1.08 6.55 KB 1.9531 51.81 KB 7.73
ServiceModelGrpc.Protobuf 28.95 μs 0.653 μs 0.579 μs 34,544.6 1.79 0.08 1.33 KB 0.3662 9.82 KB 1.47
ServiceModelGrpc.MessagePack 18.96 μs 0.899 μs 0.841 μs 52,735.3 1.17 0.08 1.52 KB 0.3662 10.02 KB 1.49
ServiceModelGrpc.proto-emulation 15.23 μs 0.627 μs 0.587 μs 65,680.3 0.95 0.06 1.32 KB 0.2441 6.76 KB 1.01
grpc-dotnet 16.20 μs 0.840 μs 0.744 μs 61,744.8 1.00 0.00 1.32 KB 0.2441 6.7 KB 1.00

Server async unary call, client is stub

BenchmarkDotNet=v0.13.2, OS=ubuntu 20.04
Intel Xeon CPU E5-2673 v4 2.30GHz, 1 CPU, 2 logical and 2 physical cores
.NET SDK=7.0.100-rc.2.22477.23
  [Host]   : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2
  ShortRun : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2

Job=ShortRun  Platform=X64  Force=True  
Server=False  IterationCount=15  LaunchCount=1  
RunStrategy=Throughput  WarmupCount=3  
Method Mean Error StdDev Op/s Ratio RatioSD Message size Gen0 Allocated Alloc Ratio
ServiceModelGrpc.DataContract 428.39 μs 22.895 μs 21.416 μs 2,334.3 5.84 0.53 6.55 KB 1.9531 60.96 KB 3.83
ServiceModelGrpc.Protobuf 96.46 μs 8.084 μs 6.750 μs 10,366.7 1.31 0.12 1.33 KB 0.7324 19.09 KB 1.20
ServiceModelGrpc.MessagePack 74.88 μs 8.302 μs 7.766 μs 13,354.7 1.02 0.10 1.52 KB 0.7324 19.26 KB 1.21
ServiceModelGrpc.proto-emulation 67.42 μs 5.998 μs 5.611 μs 14,832.5 0.92 0.11 1.32 KB 0.4883 16.05 KB 1.01
grpc-dotnet 73.74 μs 5.848 μs 5.471 μs 13,561.8 1.00 0.00 1.32 KB 0.4883 15.93 KB 1.00

Client plus server async unary call, without stubs

BenchmarkDotNet=v0.13.2, OS=ubuntu 20.04
Intel Xeon CPU E5-2673 v4 2.30GHz, 1 CPU, 2 logical and 2 physical cores
.NET SDK=7.0.100-rc.2.22477.23
  [Host]   : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2
  ShortRun : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2

Job=ShortRun  Platform=X64  Force=True  
Server=False  IterationCount=15  LaunchCount=1  
RunStrategy=Throughput  WarmupCount=3  
Method Mean Error StdDev Op/s Ratio RatioSD Message size Gen0 Allocated Alloc Ratio
ServiceModelGrpc.DataContract 782.7 μs 32.40 μs 30.31 μs 1,277.7 7.48 0.56 6.55 KB 1.9531 98.51 KB 5.11
ServiceModelGrpc.Protobuf 147.8 μs 11.29 μs 10.57 μs 6,764.2 1.41 0.15 1.33 KB 0.9766 25.52 KB 1.32
ServiceModelGrpc.MessagePack 127.1 μs 17.26 μs 16.15 μs 7,865.8 1.22 0.17 1.52 KB 0.9766 25.5 KB 1.32
ServiceModelGrpc.proto-emulation 105.5 μs 7.92 μs 7.41 μs 9,474.5 1.01 0.09 1.32 KB 0.7324 19.41 KB 1.01
grpc-dotnet 105.0 μs 6.18 μs 5.78 μs 9,524.3 1.00 0.00 1.32 KB 0.7324 19.28 KB 1.00
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].