mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 09:55:28 +08:00 
			
		
		
		
	Merge branch 'EngRajabi-feature_distributeCache'
This commit is contained in:
		@@ -2,15 +2,16 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    using System;
 | 
					    using System;
 | 
				
			||||||
    using System.Collections.Generic;
 | 
					    using System.Collections.Generic;
 | 
				
			||||||
 | 
					    using Microsoft.Extensions.Caching.Memory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class InMemoryCache<T> : IOcelotCache<T>
 | 
					    public class AspMemoryCache<T> : IOcelotCache<T>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly Dictionary<string, CacheObject<T>> _cache;
 | 
					        private readonly IMemoryCache _memoryCache;
 | 
				
			||||||
        private readonly Dictionary<string, List<string>> _regions;
 | 
					        private readonly Dictionary<string, List<string>> _regions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public InMemoryCache()
 | 
					        public AspMemoryCache(IMemoryCache memoryCache)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _cache = new Dictionary<string, CacheObject<T>>();
 | 
					            _memoryCache = memoryCache;
 | 
				
			||||||
            _regions = new Dictionary<string, List<string>>();
 | 
					            _regions = new Dictionary<string, List<string>>();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -21,10 +22,45 @@
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var expires = DateTime.UtcNow.Add(ttl);
 | 
					            _memoryCache.Set(key, value, ttl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _cache.Add(key, new CacheObject<T>(value, expires));
 | 
					            SetRegion(region, key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public T Get(string key, string region)
 | 
				
			||||||
 | 
					        {   
 | 
				
			||||||
 | 
					            if (_memoryCache.TryGetValue(key, out T value))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return default(T);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void ClearRegion(string region)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_regions.ContainsKey(region))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var keys = _regions[region];
 | 
				
			||||||
 | 
					                foreach (var key in keys)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    _memoryCache.Remove(key);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_memoryCache.TryGetValue(key, out T oldValue))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _memoryCache.Remove(key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Add(key, value, ttl, region);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void SetRegion(string region, string key)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            if (_regions.ContainsKey(region))
 | 
					            if (_regions.ContainsKey(region))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var current = _regions[region];
 | 
					                var current = _regions[region];
 | 
				
			||||||
@@ -38,44 +74,5 @@
 | 
				
			|||||||
                _regions.Add(region, new List<string> { key });
 | 
					                _regions.Add(region, new List<string> { key });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (_cache.ContainsKey(key))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                _cache.Remove(key);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Add(key, value, ttl, region);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public void ClearRegion(string region)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (_regions.ContainsKey(region))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                var keys = _regions[region];
 | 
					 | 
				
			||||||
                foreach (var key in keys)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    _cache.Remove(key);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public T Get(string key, string region)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (_cache.ContainsKey(key))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                var cached = _cache[key];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (cached.Expires > DateTime.UtcNow)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    return cached.Value;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                _cache.Remove(key);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return default(T);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -77,20 +77,6 @@
 | 
				
			|||||||
            context.DownstreamResponse = response;
 | 
					            context.DownstreamResponse = response;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private string GenerateRequestCacheKey(DownstreamContext context)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            string hashedContent = null;
 | 
					 | 
				
			||||||
            StringBuilder downStreamUrlKeyBuilder = new StringBuilder($"{context.DownstreamRequest.Method}-{context.DownstreamRequest.OriginalString}");
 | 
					 | 
				
			||||||
            if (context.DownstreamRequest.Content != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                string requestContentString = Task.Run(async () => await context.DownstreamRequest.Content?.ReadAsStringAsync()).Result;
 | 
					 | 
				
			||||||
                downStreamUrlKeyBuilder.Append(requestContentString);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            hashedContent = MD5Helper.GenerateMd5(downStreamUrlKeyBuilder.ToString());
 | 
					 | 
				
			||||||
            return hashedContent;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
 | 
					        internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (cached == null)
 | 
					            if (cached == null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,3 @@
 | 
				
			|||||||
using Ocelot.ServiceDiscovery.Providers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using Ocelot.Configuration.ChangeTracking;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Ocelot.DependencyInjection
 | 
					namespace Ocelot.DependencyInjection
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    using Microsoft.AspNetCore.Http;
 | 
					    using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@@ -13,6 +9,8 @@ namespace Ocelot.DependencyInjection
 | 
				
			|||||||
    using Ocelot.Cache;
 | 
					    using Ocelot.Cache;
 | 
				
			||||||
    using Ocelot.Claims;
 | 
					    using Ocelot.Claims;
 | 
				
			||||||
    using Ocelot.Configuration;
 | 
					    using Ocelot.Configuration;
 | 
				
			||||||
 | 
					    using Ocelot.ServiceDiscovery.Providers;
 | 
				
			||||||
 | 
					    using Ocelot.Configuration.ChangeTracking;
 | 
				
			||||||
    using Ocelot.Configuration.Creator;
 | 
					    using Ocelot.Configuration.Creator;
 | 
				
			||||||
    using Ocelot.Configuration.File;
 | 
					    using Ocelot.Configuration.File;
 | 
				
			||||||
    using Ocelot.Configuration.Parser;
 | 
					    using Ocelot.Configuration.Parser;
 | 
				
			||||||
@@ -58,8 +56,8 @@ namespace Ocelot.DependencyInjection
 | 
				
			|||||||
            Services = services;
 | 
					            Services = services;
 | 
				
			||||||
            Services.Configure<FileConfiguration>(configurationRoot);
 | 
					            Services.Configure<FileConfiguration>(configurationRoot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Services.TryAddSingleton<IOcelotCache<FileConfiguration>, InMemoryCache<FileConfiguration>>();
 | 
					            Services.TryAddSingleton<IOcelotCache<FileConfiguration>, AspMemoryCache<FileConfiguration>>();
 | 
				
			||||||
            Services.TryAddSingleton<IOcelotCache<CachedResponse>, InMemoryCache<CachedResponse>>();
 | 
					            Services.TryAddSingleton<IOcelotCache<CachedResponse>, AspMemoryCache<CachedResponse>>();
 | 
				
			||||||
            Services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
 | 
					            Services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
 | 
				
			||||||
            Services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
 | 
					            Services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
 | 
				
			||||||
            Services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
 | 
					            Services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,14 +5,15 @@
 | 
				
			|||||||
    using System;
 | 
					    using System;
 | 
				
			||||||
    using System.Threading;
 | 
					    using System.Threading;
 | 
				
			||||||
    using Xunit;
 | 
					    using Xunit;
 | 
				
			||||||
 | 
					    using Microsoft.Extensions.Caching.Memory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class InMemoryCacheTests
 | 
					    public class AspMemoryCacheTests
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly InMemoryCache<Fake> _cache;
 | 
					        private readonly AspMemoryCache<Fake> _cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public InMemoryCacheTests()
 | 
					        public AspMemoryCacheTests()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _cache = new InMemoryCache<Fake>();
 | 
					            _cache = new AspMemoryCache<Fake>(new MemoryCache(new MemoryCacheOptions()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
@@ -25,6 +26,13 @@
 | 
				
			|||||||
            fake.Value.ShouldBe(1);
 | 
					            fake.Value.ShouldBe(1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void doesnt_exist()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var result = _cache.Get("1", "region");
 | 
				
			||||||
 | 
					            result.ShouldBeNull();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void should_add_and_delete()
 | 
					        public void should_add_and_delete()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -40,11 +48,15 @@
 | 
				
			|||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void should_clear_region()
 | 
					        public void should_clear_region()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var fake = new Fake(1);
 | 
					            var fake1 = new Fake(1);
 | 
				
			||||||
            _cache.Add("1", fake, TimeSpan.FromSeconds(100), "region");
 | 
					            var fake2 = new Fake(2);
 | 
				
			||||||
 | 
					            _cache.Add("1", fake1, TimeSpan.FromSeconds(100), "region");
 | 
				
			||||||
 | 
					            _cache.Add("2", fake2, TimeSpan.FromSeconds(100), "region");
 | 
				
			||||||
            _cache.ClearRegion("region");
 | 
					            _cache.ClearRegion("region");
 | 
				
			||||||
            var result = _cache.Get("1", "region");
 | 
					            var result1 = _cache.Get("1", "region");
 | 
				
			||||||
            result.ShouldBeNull();
 | 
					            result1.ShouldBeNull();
 | 
				
			||||||
 | 
					            var result2 = _cache.Get("2", "region");
 | 
				
			||||||
 | 
					            result2.ShouldBeNull();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
@@ -3,8 +3,8 @@
 | 
				
			|||||||
    using global::CacheManager.Core;
 | 
					    using global::CacheManager.Core;
 | 
				
			||||||
    using Moq;
 | 
					    using Moq;
 | 
				
			||||||
    using Ocelot.Cache.CacheManager;
 | 
					    using Ocelot.Cache.CacheManager;
 | 
				
			||||||
    using Shouldly;
 | 
					 | 
				
			||||||
    using System;
 | 
					    using System;
 | 
				
			||||||
 | 
					    using Shouldly;
 | 
				
			||||||
    using TestStack.BDDfy;
 | 
					    using TestStack.BDDfy;
 | 
				
			||||||
    using Xunit;
 | 
					    using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user