diff --git a/Grpc.Extensions.sln b/Grpc.Extensions.sln index addbb02..c481ca2 100644 --- a/Grpc.Extensions.sln +++ b/Grpc.Extensions.sln @@ -43,6 +43,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AspNetCore3.0", "AspNetCore EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MathClientHost", "examples\CodeFirst\MathClientHost\MathClientHost.csproj", "{5B3DC8DC-AC90-4BF2-9E1C-DE46F9782160}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{C876F8C2-DCEB-4F0A-8E72-FE73E4BBDF58}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + Makefile = Makefile + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..d971fb1 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,23 @@ + + + RabbitYi + Copyright (c) RabbitYi contributors. + grpc,dashboard,consul,micorservice,opentracing,polly + https://github.com/yileicn/Grpc.Extensions/ + + https://github.com/yileicn/Grpc.Extensions/ + git + + true + true + false + 1.4.9 + 一个基于GRPC的简单微服务框架 +1.服务注册和发现 +2.服务自动负载均衡 +3.服务端中件间(性能监控[日志],全局错误处理,手动熔断) +4.客户端中件间(认证,超时时间设置) +5.DashBoard(远程调用,手动熔断,日志输出控制) +6.Grpc CodeFirst + + \ No newline at end of file diff --git a/src/Grpc.Extension.Abstract/Grpc.Extension.Abstract.csproj b/src/Grpc.Extension.Abstract/Grpc.Extension.Abstract.csproj index 252af59..b294336 100644 --- a/src/Grpc.Extension.Abstract/Grpc.Extension.Abstract.csproj +++ b/src/Grpc.Extension.Abstract/Grpc.Extension.Abstract.csproj @@ -2,23 +2,7 @@ netstandard2.0 - 1.4.7 - RabbitYi - FM.Grpc.Extensions.Abstract - https://github.com/yileicn/Grpc.Extensions/ - git - https://github.com/yileicn/Grpc.Extensions/ - grpc,dashboard,consul,micorservice,opentracing,polly - 一个基于GRPC的简单微服务框架 -1.服务注册和发现 -2.服务自动负载均衡 -3.服务端中件间(性能监控[日志],全局错误处理,手动熔断) -4.客户端中件间(认证,超时时间设置) -5.DashBoard(远程调用,手动熔断,日志输出控制) -6.Grpc CodeFirst - 1.4.7.1 - 1.4.7.1 diff --git a/src/Grpc.Extension.AspNetCore/Grpc.Extension.AspNetCore.csproj b/src/Grpc.Extension.AspNetCore/Grpc.Extension.AspNetCore.csproj index eab355c..3eae292 100644 --- a/src/Grpc.Extension.AspNetCore/Grpc.Extension.AspNetCore.csproj +++ b/src/Grpc.Extension.AspNetCore/Grpc.Extension.AspNetCore.csproj @@ -2,21 +2,7 @@ netcoreapp3.0 - 1.4.8 FM.Grpc.Extensions.AspNetCore - RabbitYi - 一个基于GRPC的简单微服务框架 -1.服务注册和发现 -2.服务自动负载均衡 -3.服务端中件间(性能监控[日志],全局错误处理,手动熔断) -4.客户端中件间(认证,超时时间设置) -5.DashBoard(远程调用,手动熔断,日志输出控制) -6.Grpc CodeFirst - https://github.com/yileicn/Grpc.Extensions/ - https://github.com/yileicn/Grpc.Extensions/ - git - grpc,dashboard,consul,micorservice,opentracing,polly - Grpc.Extensions.AspNetCore diff --git a/src/Grpc.Extension.Client/Grpc.Extension.Client.csproj b/src/Grpc.Extension.Client/Grpc.Extension.Client.csproj index d2c289f..bd64335 100644 --- a/src/Grpc.Extension.Client/Grpc.Extension.Client.csproj +++ b/src/Grpc.Extension.Client/Grpc.Extension.Client.csproj @@ -3,22 +3,6 @@ netstandard2.0 FM.Grpc.Extensions.Client - RabbitYi - https://github.com/yileicn/Grpc.Extensions/ - 一个基于GRPC的简单微服务框架 -1.服务注册和发现 -2.服务自动负载均衡 -3.服务端中件间(性能监控[日志],全局错误处理,手动熔断) -4.客户端中件间(认证,超时时间设置) -5.DashBoard(远程调用,手动熔断,日志输出控制) -6.Grpc CodeFirst - - 1.4.8 - git - grpc,dashboard,consul,micorservice,opentracing,polly - https://github.com/yileicn/Grpc.Extensions/ - 1.4.8.0 - 1.4.8.0 diff --git a/src/Grpc.Extension.Client/Internal/ChannelPool.cs b/src/Grpc.Extension.Client/Internal/ChannelPool.cs index 40617e9..b8fef53 100644 --- a/src/Grpc.Extension.Client/Internal/ChannelPool.cs +++ b/src/Grpc.Extension.Client/Internal/ChannelPool.cs @@ -72,19 +72,15 @@ public async Task GetChannel(string grpcServiceName) private async Task GetEndpoint(string serviceName, string dicoveryUrl, string serviceTag) { //获取健康的endpoints - var isCache = true; - var healthEndpoints = await _memoryCache.GetOrCreateAsync(serviceName, async cacheEntry => + var healthEndpoints = await _memoryCache.GetOrCreateAtomicAsync(serviceName, cacheEntry => { - isCache = false; //cacheEntry.SetAbsoluteExpiration(TimeSpan.FromSeconds(_grpcClientOptions.ServiceAddressCacheTime)); - return await _serviceDiscovery.GetEndpoints(serviceName, dicoveryUrl, serviceTag); + return _serviceDiscovery.GetEndpoints(serviceName, dicoveryUrl, serviceTag); }); if (healthEndpoints == null || healthEndpoints.Count == 0) { throw new InternalException(GrpcErrorCode.Internal,$"get endpoints from discovery of {serviceName} is null"); } - //只有重新拉取了健康结点才需要去关闭不健康的Channel - if (isCache == false) ShutdownErrorChannel(healthEndpoints, serviceName); return _loadBalancer.SelectEndpoint(serviceName, healthEndpoints); } diff --git a/src/Grpc.Extension.Common/Common/MemoryCacheExtensions.cs b/src/Grpc.Extension.Common/Common/MemoryCacheExtensions.cs new file mode 100644 index 0000000..d09c28d --- /dev/null +++ b/src/Grpc.Extension.Common/Common/MemoryCacheExtensions.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Caching.Memory; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Extension.Common +{ + /// + /// MemoryCacheExtensions(Thread Safe) + /// + public static class MemoryCacheExtensions + { + private static readonly LazyConcurrentDictionary _semaphores = new LazyConcurrentDictionary(); + + public static async Task GetOrCreateAtomicAsync(this IMemoryCache memoryCache, object key, Func> factory) + { + if (memoryCache.TryGetValue(key, out var value)) + return (T)value; + + var semaphoreKey = (memoryCache, key).GetHashCode(); + var semaphore = GetSemaphore(semaphoreKey); + + await semaphore.WaitAsync() + .ConfigureAwait(false); + try + { + if (!memoryCache.TryGetValue(key, out value)) + { + var entry = memoryCache.CreateEntry(key); + value = await factory(entry); + entry.SetValue(value); + entry.Dispose(); + return (T)value; + } + + return (T)value; + } + finally + { + semaphore.Release(); + } + } + + private static SemaphoreSlim GetSemaphore(int semaphoreKey) + { + return _semaphores.GetOrAdd(semaphoreKey, k => new SemaphoreSlim(1)); + } + } +} diff --git a/src/Grpc.Extension.Common/Grpc.Extension.Common.csproj b/src/Grpc.Extension.Common/Grpc.Extension.Common.csproj index 3346074..44bcd45 100644 --- a/src/Grpc.Extension.Common/Grpc.Extension.Common.csproj +++ b/src/Grpc.Extension.Common/Grpc.Extension.Common.csproj @@ -1,22 +1,14 @@  - netstandard2.0 - 1.4.7 - https://github.com/yileicn/Grpc.Extensions/ - https://github.com/yileicn/Grpc.Extensions/ - git - grpc,dashboard,consul,micorservice,opentracing,polly - RabbitYi FM.Grpc.Extensions.Common - 1.4.7.1 - 1.4.7.1 + diff --git a/src/Grpc.Extension.Discovery/Grpc.Extension.Discovery.csproj b/src/Grpc.Extension.Discovery/Grpc.Extension.Discovery.csproj index 89d6ef3..7122b3f 100644 --- a/src/Grpc.Extension.Discovery/Grpc.Extension.Discovery.csproj +++ b/src/Grpc.Extension.Discovery/Grpc.Extension.Discovery.csproj @@ -2,17 +2,8 @@ netstandard2.0 - 1.4.8 FM.Grpc.Extensions.Discovery - RabbitYi - 默认使用Consul实现服务注册和服务发现 - https://github.com/yileicn/Grpc.Extensions/ - https://github.com/yileicn/Grpc.Extensions/ - git - grpc,dashboard,consul,micorservice,opentracing,polly - Grpc.Extension.Discovery - 1.4.8.0 - 1.4.8.0 + 默认使用Consul实现服务注册和服务发现 diff --git a/src/Grpc.Extension/Grpc.Extension.csproj b/src/Grpc.Extension/Grpc.Extension.csproj index 2a0ec91..7bf3e78 100644 --- a/src/Grpc.Extension/Grpc.Extension.csproj +++ b/src/Grpc.Extension/Grpc.Extension.csproj @@ -2,25 +2,7 @@ netstandard2.0 - 1.4.8 - 一个基于GRPC的简单微服务框架 -1.服务注册和发现 -2.服务自动负载均衡 -3.服务端中件间(性能监控[日志],全局错误处理,手动熔断) -4.客户端中件间(认证,超时时间设置) -5.DashBoard(远程调用,手动熔断,日志输出控制) -6.Grpc CodeFirst - RabbitYi - https://github.com/yileicn/Grpc.Extensions/ FM.Grpc.Extensions - Grpc.Extensions - - false - 1.4.8.0 - 1.4.8.0 - git - grpc,dashboard,consul,micorservice,opentracing,polly - https://github.com/yileicn/Grpc.Extensions/