Skip to content

Commit 530eb1c

Browse files
authored
Add support for per-address attributes (#1472)
1 parent 82dec0f commit 530eb1c

30 files changed

+278
-147
lines changed

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "6.0.100-rc.1.21458.32",
3+
"version": "6.0.100",
44
"rollForward": "latestFeature"
55
}
66
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#region Copyright notice and license
2+
3+
// Copyright 2019 The gRPC Authors
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
#endregion
18+
19+
#if SUPPORT_LOAD_BALANCING
20+
using System.Net;
21+
22+
namespace Grpc.Net.Client.Balancer
23+
{
24+
/// <summary>
25+
/// Represents a balancer address.
26+
/// <para>
27+
/// Note: Experimental API that can change or be removed without any prior notice.
28+
/// </para>
29+
/// </summary>
30+
public sealed class BalancerAddress
31+
{
32+
private BalancerAttributes? _attributes;
33+
34+
/// <summary>
35+
/// Initializes a new instance of the <see cref="BalancerAddress"/> class with the specified <see cref="DnsEndPoint"/>.
36+
/// </summary>
37+
/// <param name="endPoint">The end point.</param>
38+
public BalancerAddress(DnsEndPoint endPoint)
39+
{
40+
EndPoint = endPoint;
41+
}
42+
43+
/// <summary>
44+
/// Initializes a new instance of the <see cref="BalancerAddress"/> class with the specified host and port.
45+
/// </summary>
46+
/// <param name="host">The host.</param>
47+
/// <param name="port">The port.</param>
48+
public BalancerAddress(string host, int port) : this(new DnsEndPoint(host, port))
49+
{
50+
}
51+
52+
/// <summary>
53+
/// Gets the address <see cref="DnsEndPoint"/>.
54+
/// </summary>
55+
public DnsEndPoint EndPoint { get; }
56+
57+
/// <summary>
58+
/// Gets the address attributes.
59+
/// </summary>
60+
public BalancerAttributes Attributes => _attributes ??= new BalancerAttributes();
61+
62+
/// <summary>
63+
/// Returns a string that reprsents the address.
64+
/// </summary>
65+
public override string ToString()
66+
{
67+
return $"{EndPoint.Host}:{EndPoint.Port}";
68+
}
69+
}
70+
}
71+
#endif

src/Grpc.Net.Client/Balancer/ChannelState.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace Grpc.Net.Client.Balancer
3434
public sealed class ChannelState
3535
{
3636
[DebuggerStepThrough]
37-
internal ChannelState(Status status, IReadOnlyList<DnsEndPoint>? addresses, LoadBalancingConfig? loadBalancingConfig, BalancerAttributes attributes)
37+
internal ChannelState(Status status, IReadOnlyList<BalancerAddress>? addresses, LoadBalancingConfig? loadBalancingConfig, BalancerAttributes attributes)
3838
{
3939
Addresses = addresses;
4040
LoadBalancingConfig = loadBalancingConfig;
@@ -45,7 +45,7 @@ internal ChannelState(Status status, IReadOnlyList<DnsEndPoint>? addresses, Load
4545
/// <summary>
4646
/// Gets a collection of addresses. Will be <c>null</c> if <see cref="Status"/> has a non-OK value.
4747
/// </summary>
48-
public IReadOnlyList<DnsEndPoint>? Addresses { get; }
48+
public IReadOnlyList<BalancerAddress>? Addresses { get; }
4949

5050
/// <summary>
5151
/// Gets an optional load balancing config.

src/Grpc.Net.Client/Balancer/CompletionContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ namespace Grpc.Net.Client.Balancer
3232
public sealed class CompletionContext
3333
{
3434
/// <summary>
35-
/// Gets or sets the <see cref="DnsEndPoint"/> a call was made with. Required.
35+
/// Gets or sets the <see cref="BalancerAddress"/> a call was made with. Required.
3636
/// </summary>
37-
public DnsEndPoint? Address { get; set; }
37+
public BalancerAddress? Address { get; set; }
3838

3939
/// <summary>
4040
/// Gets or sets the <see cref="Exception"/> thrown when making the call.

src/Grpc.Net.Client/Balancer/DnsResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ private async Task RefreshCoreAsync(CancellationToken cancellationToken)
146146
DnsResolverLog.ReceivedDnsResults(_logger, addresses.Length, _address, addresses);
147147

148148
var resolvedPort = _address.Port == -1 ? 80 : _address.Port;
149-
var endpoints = addresses.Select(a => new DnsEndPoint(a.ToString(), resolvedPort)).ToArray();
149+
var endpoints = addresses.Select(a => new BalancerAddress(a.ToString(), resolvedPort)).ToArray();
150150
var resolverResult = ResolverResult.ForResult(endpoints, serviceConfig: null);
151151
_listener(resolverResult);
152152
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#region Copyright notice and license
2+
3+
// Copyright 2019 The gRPC Authors
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
#endregion
18+
19+
#if SUPPORT_LOAD_BALANCING
20+
using System;
21+
using System.Collections.Generic;
22+
using System.Diagnostics.CodeAnalysis;
23+
24+
namespace Grpc.Net.Client.Balancer.Internal
25+
{
26+
internal class BalancerAddressEqualityComparer : IEqualityComparer<BalancerAddress>
27+
{
28+
internal static readonly BalancerAddressEqualityComparer Instance = new BalancerAddressEqualityComparer();
29+
30+
public bool Equals(BalancerAddress? x, BalancerAddress? y)
31+
{
32+
if (ReferenceEquals(x, y))
33+
{
34+
return true;
35+
}
36+
37+
if (x == null || y == null)
38+
{
39+
return false;
40+
}
41+
42+
if (!x.EndPoint.Equals(y.EndPoint))
43+
{
44+
return false;
45+
}
46+
47+
return true;
48+
}
49+
50+
public int GetHashCode([DisallowNull] BalancerAddress obj)
51+
{
52+
throw new NotSupportedException();
53+
}
54+
}
55+
}
56+
#endif

src/Grpc.Net.Client/Balancer/Internal/BalancerHttpHandler.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,16 @@ protected override async Task<HttpResponseMessage> SendAsync(
7777
var pickContext = new PickContext { Request = request };
7878
var result = await _manager.PickAsync(pickContext, waitForReady, cancellationToken).ConfigureAwait(false);
7979
var address = result.Address!;
80+
var addressEndpoint = address.EndPoint;
8081

8182
// Update request host if required.
8283
if (!request.RequestUri.IsAbsoluteUri ||
83-
request.RequestUri.Host != address.Host ||
84-
request.RequestUri.Port != address.Port)
84+
request.RequestUri.Host != addressEndpoint.Host ||
85+
request.RequestUri.Port != addressEndpoint.Port)
8586
{
8687
var uriBuilder = new UriBuilder(request.RequestUri);
87-
uriBuilder.Host = address.Host;
88-
uriBuilder.Port = address.Port;
88+
uriBuilder.Host = addressEndpoint.Host;
89+
uriBuilder.Port = addressEndpoint.Port;
8990
request.RequestUri = uriBuilder.Uri;
9091
}
9192

src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public void UpdateState(BalancerState state)
290290

291291
public async
292292
#if !NETSTANDARD2_0
293-
ValueTask<(Subchannel Subchannel, DnsEndPoint Address, Action<CompletionContext> OnComplete)>
293+
ValueTask<(Subchannel Subchannel, BalancerAddress Address, Action<CompletionContext> OnComplete)>
294294
#else
295295
Task<(Subchannel Subchannel, DnsEndPoint Address, Action<CompleteContext> OnComplete)>
296296
#endif
@@ -316,7 +316,7 @@ public async
316316

317317
if (address != null)
318318
{
319-
ConnectionManagerLog.PickResultSuccessful(Logger, subchannel.Id, address);
319+
ConnectionManagerLog.PickResultSuccessful(Logger, subchannel.Id, address.EndPoint);
320320
return (subchannel, address, result.Complete);
321321
}
322322
else

src/Grpc.Net.Client/Balancer/Internal/ISubchannelTransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace Grpc.Net.Client.Balancer.Internal
3333
internal interface ISubchannelTransport : IDisposable
3434
{
3535
void OnRequestComplete(CompletionContext context);
36-
DnsEndPoint? CurrentEndPoint { get; }
36+
BalancerAddress? CurrentAddress { get; }
3737

3838
#if NET5_0_OR_GREATER
3939
ValueTask<Stream> GetStreamAsync(DnsEndPoint endPoint, CancellationToken cancellationToken);

src/Grpc.Net.Client/Balancer/Internal/PassiveSubchannelTransport.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,22 @@ namespace Grpc.Net.Client.Balancer.Internal
3535
internal class PassiveSubchannelTransport : ISubchannelTransport, IDisposable
3636
{
3737
private readonly Subchannel _subchannel;
38-
private DnsEndPoint? _currentEndPoint;
38+
private BalancerAddress? _currentAddress;
3939

4040
public PassiveSubchannelTransport(Subchannel subchannel)
4141
{
4242
_subchannel = subchannel;
4343
}
4444

45-
public DnsEndPoint? CurrentEndPoint => _currentEndPoint;
45+
public BalancerAddress? CurrentAddress => _currentAddress;
4646

4747
public void OnRequestComplete(CompletionContext context)
4848
{
4949
}
5050

5151
public void Disconnect()
5252
{
53-
_currentEndPoint = null;
53+
_currentAddress = null;
5454
_subchannel.UpdateConnectivityState(ConnectivityState.Idle, "Disconnected.");
5555
}
5656

@@ -63,12 +63,12 @@ public void Disconnect()
6363
TryConnectAsync(CancellationToken cancellationToken)
6464
{
6565
Debug.Assert(_subchannel._addresses.Count == 1);
66-
Debug.Assert(CurrentEndPoint == null);
66+
Debug.Assert(CurrentAddress == null);
6767

68-
var currentEndPoint = _subchannel._addresses[0];
68+
var currentAddress = _subchannel._addresses[0];
6969

7070
_subchannel.UpdateConnectivityState(ConnectivityState.Connecting, "Passively connecting.");
71-
_currentEndPoint = currentEndPoint;
71+
_currentAddress = currentAddress;
7272
_subchannel.UpdateConnectivityState(ConnectivityState.Ready, "Passively connected.");
7373

7474
#if !NETSTANDARD2_0
@@ -80,7 +80,7 @@ public void Disconnect()
8080

8181
public void Dispose()
8282
{
83-
_currentEndPoint = null;
83+
_currentAddress = null;
8484
}
8585

8686
#if NET5_0_OR_GREATER

0 commit comments

Comments
 (0)