Skip to content

Commit

Permalink
支持配置获取处理中间件,支持阿里云ACM的KMS加密配置;
Browse files Browse the repository at this point in the history
  • Loading branch information
stratosblue committed Jun 19, 2021
1 parent b414267 commit 9dc0b65
Show file tree
Hide file tree
Showing 18 changed files with 507 additions and 36 deletions.
4 changes: 3 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
- 更轻便直观的配置 (个人觉得);
- 较少的包依赖 (可以在不引用Grpc包的情况下使用Http协议接入);
- 更方便调试 (没有异步Timer...支持SourceLink);
- 支持`阿里云ACM`(暂不支持加密配置);
- 支持`阿里云ACM` (支持KMS加密配置的自动解密,不依赖阿里云SDK包);
- 支持添加配置获取处理中间件,自定义配置解密等;

## Note
- 当前仅实现了`Nacos``配置读取`功能,`不支持服务发现` (暂时没有需求...)
- 没有实现任何`failover`机制 (基于文件缓存的`failover`对于容器化运行环境不是很有必要...)

**`Nacos2.0.1 with docker``阿里云ACM`环境下开发,其它环境未测试。

** 单元测试代码暂时还没写...

------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,17 @@ private static INacosConfigurationClient CreateGrpcConfigurationClient(NacosConf
? new AutomaticHostAddressAccessor(options.ClientIPSubnet)
: new FixedHostAddressAccessor(options.SpecifyClientIP);

var clientOptions = new NacosGrpcClientOptions(clientName: $"NacosGrpcClient-{Guid.NewGuid():n}",
serverAddressAccessor: serverAddressAccessor,
hostAddressAccessor: hostAddressAccessor)
var clientOptions = new NacosGrpcConfigurationClientOptions(clientName: $"NacosGrpcConfigurationClient-{Guid.NewGuid():n}",
serverAddressAccessor: serverAddressAccessor,
hostAddressAccessor: hostAddressAccessor)
{
LoggerFactory = options.LoggerFactory,
User = options.User,
AcsProfile = options.AcsProfile,
};

clientOptions.ConfigurationClientMiddlewares.AddRange(options.ConfigurationClientMiddlewares);

return new NacosConfigurationGrpcClient(clientOptions);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.Extensions.Logging;

using Nacos;
using Nacos.Middleware;

namespace Cuture.Extensions.Configuration.Nacos
{
Expand All @@ -31,6 +32,11 @@ public class NacosConfigurationSourceOptions
/// </summary>
public string? ClientIPSubnet { get; set; }

/// <summary>
/// Nacos配置客户端的中间件列表
/// </summary>
public List<INacosConfigurationClientMiddleware> ConfigurationClientMiddlewares { get; } = new();

/// <summary>
/// 配置解析器列表(列表顺序对应解析优先级)
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ internal static INacosConfigurationClient CreateHttpConfigurationClient(NacosCon
? new RemoteServerAddressAccessor(serverUris.First().HttpUri, options.LoggerFactory?.CreateLogger<RemoteServerAddressAccessor>())
: new FixedServerAddressAccessor(options.Servers.ToArray());

var clientOptions = new NacosHttpClientOptions($"NacosHttpClient-{Guid.NewGuid():n}", serverAddressAccessor)
var clientOptions = new NacosHttpConfigurationClientOptions($"NacosHttpConfigurationClient-{Guid.NewGuid():n}", serverAddressAccessor)
{
LoggerFactory = options.LoggerFactory,
User = options.User,
AcsProfile = options.AcsProfile,
};

clientOptions.ConfigurationClientMiddlewares.AddRange(options.ConfigurationClientMiddlewares);

return new NacosConfigurationHttpClient(clientOptions);
}

Expand Down
38 changes: 25 additions & 13 deletions src/Nacos.Grpc/NacosConfigurationGrpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

using Nacos.Exceptions;
using Nacos.Grpc.Messages;
using Nacos.Middleware;

namespace Nacos.Grpc
{
Expand All @@ -19,38 +20,34 @@ public sealed class NacosConfigurationGrpcClient : NacosGrpcClient, INacosConfig
{
#region Private 字段

private readonly Func<ConfigurationGetContext, Task<NacosConfigurationDescriptor>> _getConfigurationDelegate;
private readonly Dictionary<INacosUniqueConfiguration, ConfigurationSubscribeState> _notifyCallbacks = new(new INacosUniqueConfigurationEqualityComparer());

#endregion Private 字段

#region Public 构造函数

/// <inheritdoc cref="NacosConfigurationGrpcClient"/>
public NacosConfigurationGrpcClient(NacosGrpcClientOptions clientOptions) : base(clientOptions)
public NacosConfigurationGrpcClient(NacosGrpcConfigurationClientOptions clientOptions) : base(clientOptions)
{
var middlewares = clientOptions.ConfigurationClientMiddlewares;
_getConfigurationDelegate = middlewares.BuildGetConfigurationDelegateWithAliyunKMSDecrypt(acsProfile: clientOptions.AcsProfile,
loggerFactory: clientOptions.LoggerFactory,
httpClientFactory: clientOptions.HttpClientFactory,
endpointDelegate: context => InternalGetConfigurationAsync(context.Descriptor, context.CancellationToken));
}

#endregion Public 构造函数

#region Public 方法

/// <inheritdoc/>
public async Task<NacosConfigurationDescriptor> GetConfigurationAsync(NacosConfigurationDescriptor descriptor, CancellationToken token = default)
public Task<NacosConfigurationDescriptor> GetConfigurationAsync(NacosConfigurationDescriptor descriptor, CancellationToken token = default)
{
CheckInitiated();
CheckDisposed();

var request = new ConfigQueryRequest(descriptor);
request.Headers.Add("notify", "false");

var response = await RequestAsync<ConfigQueryResponse>(request, token).ConfigureAwait(false);

if (response.ErrorCode == NacosErrorCode.ConfigurationNotFound)
{
throw new ConfigurationNotFoundException(descriptor);
}

return descriptor.WithContent(response.Content, response.Md5);
return _getConfigurationDelegate(new(this, descriptor, token));
}

/// <inheritdoc/>
Expand Down Expand Up @@ -133,6 +130,21 @@ protected override void SetupRequestProcessorBuilder(RequestProcessorBuilder bui

#region Private 方法

private async Task<NacosConfigurationDescriptor> InternalGetConfigurationAsync(NacosConfigurationDescriptor descriptor, CancellationToken token)
{
var request = new ConfigQueryRequest(descriptor);
request.Headers.Add("notify", "false");

var response = await RequestAsync<ConfigQueryResponse>(request, token).ConfigureAwait(false);

if (response.ErrorCode == NacosErrorCode.ConfigurationNotFound)
{
throw new ConfigurationNotFoundException(descriptor);
}

return descriptor.WithContent(response.Content, response.Md5);
}

private async Task<NacosResponse?> InternalSubscribeConfigurationChangeAsync(NacosConfigurationDescriptor descriptor, CancellationToken token)
{
var request = new ConfigBatchListenRequest(true).AddListenContext(descriptor);
Expand Down
40 changes: 40 additions & 0 deletions src/Nacos.Grpc/NacosGrpcConfigurationClientOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Collections.Generic;

using Nacos.Middleware;

namespace Nacos
{
/// <summary>
/// NacosGrpc配置客户端选项
/// </summary>
public class NacosGrpcConfigurationClientOptions : NacosGrpcClientOptions
{
#region Public 属性

/// <summary>
/// Nacos配置客户端的中间件列表
/// </summary>
public List<INacosConfigurationClientMiddleware> ConfigurationClientMiddlewares { get; } = new();

#endregion Public 属性

#region Public 构造函数

/// <summary>
/// <inheritdoc cref="NacosGrpcClientOptions"/>
/// </summary>
/// <param name="clientName"></param>
/// <param name="serverAddressAccessor"></param>
/// <param name="httpClientFactory"></param>
/// <param name="hostAddressAccessor"></param>
public NacosGrpcConfigurationClientOptions(string clientName,
IServerAddressAccessor serverAddressAccessor,
INacosUnderlyingHttpClientFactory? httpClientFactory = null,
IHostAddressAccessor? hostAddressAccessor = null)
: base(clientName, serverAddressAccessor, httpClientFactory, hostAddressAccessor)
{
}

#endregion Public 构造函数
}
}
45 changes: 31 additions & 14 deletions src/Nacos/Http/NacosConfigurationHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Nacos.Exceptions;
using Nacos.Http.Messages;
using Nacos.Internal;
using Nacos.Middleware;
using Nacos.Utils;

namespace Nacos.Http
Expand All @@ -16,30 +17,32 @@ namespace Nacos.Http
/// </summary>
public sealed class NacosConfigurationHttpClient : NacosHttpClient, INacosConfigurationClient
{
#region Private 字段

private readonly Func<ConfigurationGetContext, Task<NacosConfigurationDescriptor>> _getConfigurationDelegate;

#endregion Private 字段

#region Public 构造函数

/// <inheritdoc cref="NacosConfigurationHttpClient"/>
public NacosConfigurationHttpClient(NacosHttpClientOptions clientOptions) : base(clientOptions)
public NacosConfigurationHttpClient(NacosHttpConfigurationClientOptions clientOptions) : base(clientOptions)
{
var middlewares = clientOptions.ConfigurationClientMiddlewares;
_getConfigurationDelegate = middlewares.BuildGetConfigurationDelegateWithAliyunKMSDecrypt(acsProfile: clientOptions.AcsProfile,
loggerFactory: clientOptions.LoggerFactory,
httpClientFactory: clientOptions.HttpClientFactory,
endpointDelegate: context => InternalGetConfigurationAsync(context.Descriptor, context.CancellationToken));
}

#endregion Public 构造函数

#region Public 方法

/// <inheritdoc/>
public async Task<NacosConfigurationDescriptor> GetConfigurationAsync(NacosConfigurationDescriptor descriptor, CancellationToken token = default)
public Task<NacosConfigurationDescriptor> GetConfigurationAsync(NacosConfigurationDescriptor descriptor, CancellationToken token = default)
{
var request = new QueryConfigurationRequest(descriptor);
try
{
var content = await RequestAsync(request, token).ConfigureAwait(false);
return descriptor.WithContent(content);
}
catch (HttpRequestNotFoundException)
{
throw new ConfigurationNotFoundException(descriptor);
}
return _getConfigurationDelegate(new(this, descriptor, token));
}

/// <inheritdoc/>
Expand Down Expand Up @@ -71,6 +74,20 @@ protected override void Dispose(bool disposing)

#region Private 方法

private async Task<NacosConfigurationDescriptor> InternalGetConfigurationAsync(NacosConfigurationDescriptor descriptor, CancellationToken token)
{
var request = new QueryConfigurationRequest(descriptor);
try
{
var content = await RequestAsync(request, token).ConfigureAwait(false);
return descriptor.WithContent(content, HashUtil.ComputeMD5(content).ToHexString());
}
catch (HttpRequestNotFoundException)
{
throw new ConfigurationNotFoundException(descriptor);
}
}

private async Task PollingListeningConfigurationAsync(NacosConfigurationDescriptor descriptor, ConfigurationChangeNotifyCallback notifyCallback, CancellationToken token)
{
var scaler = new Scaler(0, 10, 60);
Expand All @@ -88,11 +105,11 @@ private async Task PollingListeningConfigurationAsync(NacosConfigurationDescript
if (!string.IsNullOrWhiteSpace(response))
{
//HACK 响应值是否有内容?
var newDescriptor = await GetConfigurationAsync(descriptor, RunningToken).ConfigureAwait(false);
var newDescriptor = await GetConfigurationAsync(descriptor, token).ConfigureAwait(false);

await notifyCallback(newDescriptor, token).ConfigureAwait(false);

descriptor = descriptor.WithContent(newDescriptor.Content, HashUtil.ComputeMD5(newDescriptor.Content).ToHexString());
descriptor = descriptor.WithContent(newDescriptor.Content, newDescriptor.Hash ?? HashUtil.ComputeMD5(newDescriptor.Content).ToHexString());
}

scaler.Reset();
Expand Down
2 changes: 1 addition & 1 deletion src/Nacos/Http/NacosHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public NacosHttpClient(NacosHttpClientOptions clientOptions)
? new NullRequestSigner()
: new ACMRequestSigner(clientOptions.AcsProfile.AccessKeyId, clientOptions.AcsProfile.AccessKeySecret);

_runningTokenSource = new CancellationTokenSource();
_runningTokenSource = new();
RunningToken = _runningTokenSource.Token;
}

Expand Down
4 changes: 3 additions & 1 deletion src/Nacos/Http/NacosHttpClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ public class NacosHttpClientOptions : NacosClientOptions
#region Public 构造函数

/// <inheritdoc cref="NacosHttpClientOptions"/>
public NacosHttpClientOptions(string clientName, IServerAddressAccessor serverAddressAccessor, INacosUnderlyingHttpClientFactory? httpClientFactory = null)
public NacosHttpClientOptions(string clientName,
IServerAddressAccessor serverAddressAccessor,
INacosUnderlyingHttpClientFactory? httpClientFactory = null)
: base(clientName, serverAddressAccessor, httpClientFactory)
{
}
Expand Down
33 changes: 33 additions & 0 deletions src/Nacos/Http/NacosHttpConfigurationClientOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Collections.Generic;

using Nacos.Middleware;

namespace Nacos.Http
{
/// <summary>
/// NacosHttp配置客户端选项
/// </summary>
public class NacosHttpConfigurationClientOptions : NacosHttpClientOptions
{
#region Public 属性

/// <summary>
/// Nacos配置客户端的中间件列表
/// </summary>
public List<INacosConfigurationClientMiddleware> ConfigurationClientMiddlewares { get; } = new();

#endregion Public 属性

#region Public 构造函数

/// <inheritdoc cref="NacosHttpClientOptions"/>
public NacosHttpConfigurationClientOptions(string clientName,
IServerAddressAccessor serverAddressAccessor,
INacosUnderlyingHttpClientFactory? httpClientFactory = null)
: base(clientName, serverAddressAccessor, httpClientFactory)
{
}

#endregion Public 构造函数
}
}
Loading

0 comments on commit 9dc0b65

Please sign in to comment.