Storm King
Personal blog: http://www.boydwang.com/2017/12/net-core-in-memory-cache/
These two days are looking at the. NET core in memory cache, where the usage is recorded, mainly involving MemoryCache's get/set/expire/flush.
First we create an MVC project with the dotnet command, where we will use postman to request the server,
Because we're going to use this NuGet package for Microsoft.Extensions.Caching.Memory, we need to add a reference to open the *.csproj file under the MVC project path you just built, using Vscode (or any editor). Here is my cache.csproj, find This tag, add the following code:
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0.0"/>
Note The version number may be different, I'm using. NET Core 2.0.
After that we need to register the cache service, open the Startup.cs file, find the configureservices method, add the following code:
services.AddMemoryCache();
The configureservices method should look like this:
public void ConfigureServices(IServiceCollection services){ services.AddMemoryCache(); services.AddMvc();}
Then we can use the Inmemorycache in the controller by constructing the injection method.
Open HomeController or create a new controller yourself, modify the constructor method
private IMemoryCache _cache;public HomeController(IMemoryCache cache){ this._cache = cache;}
First look at the definition of memorycache :
Constructors:MemoryCache(IOptions)Properties:Count(Gets the count of the current entries for diagnostic purposes.)Methods:Compact(Double)CreateEntry(Object)Dispose()Dispose(Boolean)Finalize()Remove(Object)TryGetValue(Object, Object)Extension Methods:Get(IMemoryCache, Object)Get(IMemoryCache, Object)GetOrCreate(IMemoryCache, Object, Func)GetOrCreateAsync(IMemoryCache, Object, Func>)Set(IMemoryCache, Object, TItem)Set(IMemoryCache, Object, TItem, MemoryCacheEntryOptions)Set(IMemoryCache, Object, TItem, IChangeToken)Set(IMemoryCache, Object, TItem, DateTimeOffset)Set(IMemoryCache, Object, TItem, TimeSpan)TryGetValue(IMemoryCache, Object, TItem)
Most of what we use is extension methods, which is a strange phenomenon, but this is not the focus of this article discussion, it will be used to
TryGetValue(Object, Object)Set<TItem>(IMemoryCache, Object, TItem, MemoryCacheEntryOptions)
Both of these methods to Get/set/expire cache entries.
First, let's add a get WEBAPI:
[HttpGet("cache/{key}")]public IActionResult GetCache(string key){ object result = new object(); _cache.TryGetValue(key, out result); return new JsonResult(result);}
It takes a key as a parameter, returns the found value if found, and returns null if it is not found
Now we can enter it on the command line.
dotnet restoredotnet run
To start the Web project, and then we can
http://localhost:5000/cache/{key}
This URL to access the cache, at which time the cache has no value
Because we don't have a set value at this point.
Next add a set method, before adding, let's take a look at the definition of memorycacheentryoptions.
Constructors:
Memorycacheentryoptions ()
Properties:
Absoluteexpiration
Absoluteexpirationrelativetonow
Expirationtokens
Postevictioncallbacks
Priority
Size
SlidingExpiration
Extension Methods:
Addexpirationtoken (Memorycacheentryoptions, Ichangetoken)
Registerpostevictioncallback (Memorycacheentryoptions, Postevictiondelegate)
Registerpostevictioncallback (Memorycacheentryoptions, Postevictiondelegate, Object)
Setabsoluteexpiration (Memorycacheentryoptions, DateTimeOffset)
Setabsoluteexpiration (Memorycacheentryoptions, TimeSpan)
SetPriority (Memorycacheentryoptions, cacheitempriority)
SetSize (Memorycacheentryoptions, Int64)
Setslidingexpiration (Memorycacheentryoptions, TimeSpan)
Here are a few concepts:
Absoluteexpiration
Represents an absolute absolute timeout, which must expire after a certain amount of time (for example, 15 minutes)
SlidingExpiration
Represents a sliding time-out (I translated it myself). ), sliding means that if you set the SlidingExpiration timeout to 5 minutes, if in 5 minutes, there is a new request to get the cached item, then this 5 minutes will be reset until more than 5 minutes without a request, only time out
CacheItemPriority
This is an enumeration that represents the priority of the cache, the default value is normal, and does not time out if set to Neverremove.
High Low NeverRemove Normal
Registerpostevictioncallback
This is a way to pass a callback that triggers a callback when the cache entry is removed (timed out).
We then add a set method and add a canceltoken to it so that we can manually control the forced emptying of the cache.
private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();[HttpPost("cache/")]public IActionResult SetCache([FromBody]CacheItem item){ var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(5)) .RegisterPostEvictionCallback(DependentEvictionCallback, null) .AddExpirationToken(new CancellationChangeToken(cancellationTokenSource.Token)); _cache.Set(item.key, item.value, cacheEntryOptions); return Ok();}
Then we can use the Postman POST request to set the cache, the address is:
http://localhost:5000/cache
Next we'll add a flush API, and we'll be able to manually empty the cache. Here we take advantage of the CancellationTokenSource added at set
[HttpGet("cache/flush")]public IActionResult Flush(){ cancellationTokenSource.Cancel(); return Ok();}
Access Address:
http://localhost:5000/cache/flush
Calling this API will find a line of output in the console.
Parent entry was evicted. Reason: TokenExpired, Key: a.
You can add the same token to multiple cache entries to achieve the purpose of purging multiple cache entries at the same time.
The pits encountered:
1.token not work problem.
When I first realized it, I added a token, that's what it says.
private CancellationTokenSource cancellationTokenSource;public HomeController(IMemoryCache cache){ this._cache = cache; cancellationTokenSource = new CancellationTokenSource();}[HttpGet("cache/flush")]public IActionResult Flush(){ cancellationTokenSource.Cancel(); return Ok();}
Then found that the call flush has not been in effect, the cache has not been cleared, very puzzled, thought my token method with a problem.
Until I changed to the following code, let's have a look.
private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();public HomeController(IMemoryCache cache){ this._cache = cache;}[HttpGet("cache/flush")]public IActionResult Flush(){ cancellationTokenSource.Cancel(); return Ok();}
Just a static problem, it produces a different result, because every time HttpRequest comes over, it starts a new thread to respond to it, so the token added in the set is not the token that flush asks for. Because a constructor method is called again, a new CancellationTokenSource object is generated, and token is called. The Cancel () method is bound to fail, thus changing to static, so that each request is the same token, so that the different tokens caused by the Cancel method does not work, empty the cache will be able to function properly.
2.RegisterPostEvictionCallback Recurring Trigger Issue
Registerpostevictioncallback triggers not only when the cache times out, but also when the cache is replaced (updated). In Postevictiondelegate there is a parameter of Evictionreason that indicates why the cache entry was removed
public delegate void PostEvictionDelegate(object key, object value, EvictionReason reason, object state);
EvictionReasonNone = 0,Removed = 1, 缓存项被Remove()方法移除Replaced = 2, 缓存项被更新Expired = 3, 缓存项超时TokenExpired = 4, 缓存由token触发超时Capacity = 5 缓存空间不足
So we need to determine in callback what reason the cache is being removed in order to avoid accidental callback triggering.