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/