Multi-node of same service VS different service #550
-
|
I'm working with a microservices system and I want to add Fusion Cache for the Authorization service. I'm thinking to create a component with Fusion Cache for the authorization service that is then used by all the consumer services so that each service have their own L1 memory cache + L2 with Redis when looking for fetching Authorization information. So, unlike the typical scenarios described in the docs, I'm pushing the cache one more step toward the consumer, effectively considering the Authorization service a "slow" repository of data and using the cache to boost performance. Given I couldn't find any specific examples of this configuration in the docs, I'd like to know if this is still considered a supported multi-node scenario and how should I configure the Fusion Cache so that each separate service can read the most up-to-date cache values? I'm working on a PoC atm and I've noticed that using the same Redis var serializer = new FusionCacheSystemTextJsonSerializer();
services.AddStackExchangeRedisCache(options =>
{
options.ConfigurationOptions = redisConfiguration;
options.InstanceName = "my-fusion-cache";
});
services.AddFusionCache()
.WithDefaultEntryOptions(o =>
{
o.Duration = TimeSpan.FromSeconds(60);
o.AllowBackgroundBackplaneOperations = true;
o.AllowBackgroundDistributedCacheOperations = true;
o.IsFailSafeEnabled = true;
o.DistributedCacheSoftTimeout = TimeSpan.FromSeconds(5);
o.FailSafeThrottleDuration = TimeSpan.FromMinutes(120);
configureDefaultEntry?.Invoke(o);
})
.WithSerializer(serializer)
.WithDistributedCache(sp =>
sp.GetRequiredService<IDistributedCache>(), serializer)
.WithStackExchangeRedisBackplane(options =>
options.ConfigurationOptions = redisConfiguration);As you can see, When reading the cache from any service, I have something like this: var statusCode = await _fusionCache.GetOrSetAsync<int>(cacheKey,
async (_, ct) =>
{
factoryExecuted = true;
fullResponse = await httpClient.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, ct);
return (int)fullResponse.StatusCode;
},
options => options
.SetDuration(TimeSpan.FromMinutes(60))
.SetFactoryTimeouts(TimeSpan.FromMilliseconds(5))
.SetEagerRefresh(0.8f)
);I just need to store the response code for now in the cache. On an update request, I'm setting the expiration by simply doing something like this in the authn service. await _fusionCache.ExpireAsync(cacheKey);Just to clarify, all updates will always be propagated by the Fusion Cache instance in the authorization service. This may or may not make a difference, since the backplane should ensure the syncing happens for updates from any node, but I thought to specify that anyway. Any advice would be greatly appreciated!🙏 🙇 |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Beta Was this translation helpful? Give feedback.
-
|
the other day's afternoon came and went, so here we are 😅
From my understanding of your description: yes, totally. What is normally thought of as "the database" can be anything, really. Each app instance has its own L1 (for super fast access), and all are connected to a shared L2 and backplane (for sharing cached data and as the source of data after receiving a backplane notification).
Yup, that's how it works: when you do, for example, a And with this flow, all is taken care of.
Not really, but let me clarify. The This is not bad, mind you, it's just something that works specifically for the A similar but better solution, that will work holistically in FusionCache and for "all the things" is the use of Named Caches and Basically, by creating a Named Cache + setting the
A couple of things here.
By doing this, you are registering this
Not sure about this: 60s duration and 2h of fail-safe throttle duration? Translation of this config: "cache stuff or 60s, and if there's a transient issue during the refresh, put the old value back in the cache for 2h".
If you decide to stay with the
If instead you decide not to register and use one global
One more trick I can suggest: since the (look at the end a sample of the resulting code)
I know I said it already, but just to highlight the previous point more, since it's important: they are using the "same cache" anyway, it's just a prefix.
This is correct!
Looks good to me!
Ah, tere you have it, you already thought about it 😅
Just to be clear:
I'm not sure I 100% understood this point. Anyway, the resulting setup code I mentioned above: // CREATE THE MULTIPLEXER, SPECIFY OPTIONS, ETC
IConnectionMultiplexer conn = ... ;
// LATER...
services.AddFusionCache("AuthCache")
// CACHE KEY PREFIX
.WithCacheKeyPrefixByCacheName()
// SERIALIZER
.WithSerializer(new FusionCacheSystemTextJsonSerializer())
// L2
.WithDistributedCache(
new RedisCache(new RedisCacheOptions
{
ConnectionMultiplexerFactory = async () => conn
})
)
// BACKPLANE
.WithBackplane(
new RedisBackplane(new RedisBackplaneOptions
{
ConnectionMultiplexerFactory = async () => conn
})
);Of course you can add here all the rest like specific options, etc.
Thanks to you for using it, I hope it will help with yout project!
Ahah grazie 🤌, apprezzo molto. Hope this helps, let me know! |
Beta Was this translation helpful? Give feedback.

Hi @riccardomerlin
the other day's afternoon came and went, so here we are 😅