Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use grpc-dotnet instead of grpc #9149

Merged
merged 10 commits into from Mar 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG_PENDING.md
@@ -1,3 +1,6 @@
### Improvements

- [language/dotnet] - Updated Pulumi dotnet packages to use grpc-dotnet instead of grpc.
[#9149](https://github.com/pulumi/pulumi/pull/9149)

### Bug Fixes
28 changes: 24 additions & 4 deletions sdk/dotnet/Pulumi/Deployment/GrpcEngine.cs
@@ -1,22 +1,42 @@
// Copyright 2016-2020, Pulumi Corporation

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
using Pulumirpc;

namespace Pulumi
{
internal class GrpcEngine : IEngine
{
private readonly Engine.EngineClient _engine;
// Using a static dictionary to keep track of and re-use gRPC channels
// According to the docs (https://docs.microsoft.com/en-us/aspnet/core/grpc/performance?view=aspnetcore-6.0#reuse-grpc-channels), creating GrpcChannels is expensive so we keep track of a bunch of them here
private static ConcurrentDictionary<string, GrpcChannel> _engineChannels = new ConcurrentDictionary<string, GrpcChannel>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: readonly


public GrpcEngine(string engine)
public GrpcEngine(string engineAddress)
{
// maxRpcMessageSize raises the gRPC Max Message size from `4194304` (4mb) to `419430400` (400mb)
var maxRpcMessageSize = 400 * 1024 * 1024;
var grpcChannelOptions = new List<ChannelOption> { new ChannelOption(ChannelOptions.MaxReceiveMessageLength, maxRpcMessageSize)};
this._engine = new Engine.EngineClient(new Channel(engine, ChannelCredentials.Insecure, grpcChannelOptions));
if (!_engineChannels.ContainsKey(engineAddress))
{
// Allow for insecure HTTP/2 transport (only needed for netcoreapp3.x)
// https://docs.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-6.0#call-insecure-grpc-services-with-net-core-client
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
// Inititialize the engine channel once for this address
_engineChannels[engineAddress] = GrpcChannel.ForAddress(new Uri($"http://{engineAddress}"), new GrpcChannelOptions
{
MaxReceiveMessageSize = maxRpcMessageSize,
MaxSendMessageSize = maxRpcMessageSize,
Credentials = Grpc.Core.ChannelCredentials.Insecure,
});
}

this._engine = new Engine.EngineClient(_engineChannels[engineAddress]);
Comment on lines +25 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use GetOrAdd?

var engineChannel = _engineChannels.GetOrAdd(engineAddress, address =>
{
    // maxRpcMessageSize raises the gRPC Max Message size from `4194304` (4mb) to `419430400` (400mb)
    var maxRpcMessageSize = 400 * 1024 * 1024;

    // Allow for insecure HTTP/2 transport (only needed for netcoreapp3.x)
    // https://docs.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-6.0#call-insecure-grpc-services-with-net-core-client
    AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
    // Inititialize the engine channel once for this address
    return GrpcChannel.ForAddress(new Uri($"http://{address}"), new GrpcChannelOptions
    {
        MaxReceiveMessageSize = maxRpcMessageSize,
        MaxSendMessageSize = maxRpcMessageSize,
        Credentials = Grpc.Core.ChannelCredentials.Insecure,
    });
});

_engine = new Engine.EngineClient(engineChannel);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be another way of implementing it. GetOrAdd does exactly the same as the above: checks if it exists and return it or if the key does not exist, adds to the dictionary. Do you want me to update the code with GetOrAdd instead?

}

public async Task LogAsync(LogRequest request)
Expand Down
30 changes: 24 additions & 6 deletions sdk/dotnet/Pulumi/Deployment/GrpcMonitor.cs
@@ -1,22 +1,40 @@
// Copyright 2016-2020, Pulumi Corporation

using System.Collections.Generic;
using System;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
using Pulumirpc;
using Grpc.Core;
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace Pulumi
{
internal class GrpcMonitor : IMonitor
{
private readonly ResourceMonitor.ResourceMonitorClient _client;

public GrpcMonitor(string monitor)
// Using a static dictionary to keep track of and re-use gRPC channels
// According to the docs (https://docs.microsoft.com/en-us/aspnet/core/grpc/performance?view=aspnetcore-6.0#reuse-grpc-channels), creating GrpcChannels is expensive so we keep track of a bunch of them here
private static ConcurrentDictionary<string, GrpcChannel> _monitorChannels = new ConcurrentDictionary<string, GrpcChannel>();
public GrpcMonitor(string monitorAddress)
{
// maxRpcMessageSize raises the gRPC Max Message size from `4194304` (4mb) to `419430400` (400mb)
var maxRpcMessageSize = 400 * 1024 * 1024;
var grpcChannelOptions = new List<ChannelOption> { new ChannelOption(ChannelOptions.MaxReceiveMessageLength, maxRpcMessageSize)};
this._client = new ResourceMonitor.ResourceMonitorClient(new Channel(monitor, ChannelCredentials.Insecure, grpcChannelOptions));
if (!_monitorChannels.ContainsKey(monitorAddress))
{
// Allow for insecure HTTP/2 transport (only needed for netcoreapp3.x)
// https://docs.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-6.0#call-insecure-grpc-services-with-net-core-client
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
// Inititialize the monitor channel once for this monitor address
_monitorChannels[monitorAddress] = GrpcChannel.ForAddress(new Uri($"http://{monitorAddress}"), new GrpcChannelOptions
{
MaxReceiveMessageSize = maxRpcMessageSize,
MaxSendMessageSize = maxRpcMessageSize,
Credentials = ChannelCredentials.Insecure
});
}

this._client = new ResourceMonitor.ResourceMonitorClient(_monitorChannels[monitorAddress]);
}

public async Task<SupportsFeatureResponse> SupportsFeatureAsync(SupportsFeatureRequest request)
Expand Down
4 changes: 2 additions & 2 deletions sdk/dotnet/Pulumi/Pulumi.csproj
Expand Up @@ -31,8 +31,8 @@

<ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
<PackageReference Include="Grpc" Version="2.37.0" />
<PackageReference Include="Grpc.Tools" Version="2.37.0">
<PackageReference Include="Grpc.Net.Client" Version="2.43.0" />
<PackageReference Include="Grpc.Tools" Version="2.44.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down