#1408 In-memory session storage for CookieStickySessions load balancer to facilitate DI replacements#1405
#1408 In-memory session storage for CookieStickySessions load balancer to facilitate DI replacements#1405EliSyrota wants to merge 9 commits intoThreeMammals:developfrom
CookieStickySessions load balancer to facilitate DI replacements#1405Conversation
|
Hi @EliSyrota ! The feature branch (develop) has been rebased onto ThreeMammals:develop! |
raman-m
left a comment
There was a problem hiding this comment.
Major issues are
- No unit tests for newly added
InMemoryStickySessionStorageclass - No new unit tests in
CookieStickySessionsTests, but behavior ofCookieStickySessionsclass has changed. New parameter for the constructor should be tested. - No tests for
CookieStickySessionsCreator
I believe, current design can be enhanced a bit, to allow to developer not implementing ILoadBalancerCreator interface, but simply replace InMemoryStickySessionStorage class by custom one in DI-container for IStickySessionStorage interface.
There was a problem hiding this comment.
This new class should be covered by unit tests!
| _loadBalancer = new Mock<ILoadBalancer>(); | ||
| _defaultExpiryInMs = 0; | ||
| _stickySessions = new CookieStickySessions(_loadBalancer.Object, "sessionid", _defaultExpiryInMs, _bus); | ||
| var sessionStorage = new InMemoryStickySessionStorage(); |
There was a problem hiding this comment.
You are in unit tests! You haven't & shouldn't create concrete instance of the class!
You need to create mocked IStickySessionStorage object for the constructor on the next line.
| var sessionStorage = new InMemoryStickySessionStorage(); | |
| var sessionStorage = new Mock<IStickySessionStorage>(); | |
| // setup the mock |
| { | ||
| var loadBalancer = new RoundRobin(async () => await serviceProvider.Get()); | ||
| var bus = new InMemoryBus<StickySession>(); | ||
| var sessionStorage = new InMemoryStickySessionStorage(); |
There was a problem hiding this comment.
Is it possible to inject this default concrete class from DI-container, and/or via extra argument?
Because this method is responsible for default implementations injection, we need to forward a IStickySessionStorage object to CookieStickySessions constructor.
substitute CookieStickySessionsCreator to inject into CookieStickySessions own storage mechanism
Because this class (creator) is managed by DI-container, we have to add InMemoryStickySessionStorage class to DI-container too, and inject it via constructor. This is the simplest solution!
Finally, developer should not implement new creator inheriting the ILoadBalancerCreator interface.
P.S. See previous line 17. Consider moving of InMemoryBus<StickySession> object to DI-container too while refactoring this class.
| @@ -0,0 +1,10 @@ | |||
| namespace Ocelot.LoadBalancer.LoadBalancers; | |||
|
|
|||
| public interface IStickySessionStorage | |||
There was a problem hiding this comment.
Well... In PR you said:
- make a public interface for session storage so users can implement their own mechanism of storing user sessions such as distributed sessions storage etc.
Based on the current code I can say, the interface object is not added to DI-container.
| private readonly object _lock = new(); | ||
|
|
||
| public CookieStickySessions(ILoadBalancer loadBalancer, string key, int keyExpiryInMs, IBus<StickySession> bus) | ||
| public CookieStickySessions(ILoadBalancer loadBalancer, string key, int keyExpiryInMs, IBus<StickySession> bus, IStickySessionStorage storage) |
There was a problem hiding this comment.
substitute CookieStickySessionsCreator to inject into CookieStickySessions own storage mechanism
Because new added interface object can be injected by this creator, we need to explain to developer how to implement custom creator using ILoadBalancerCreator interface.
So, new paragraph in docs is required.
raman-m
left a comment
There was a problem hiding this comment.
Additional Development Needed❗
- Unit tests are missing
- Acceptance tests are absent
- The suggested service class has not been included in Dependency Injection❗
src/Ocelot/LoadBalancer/LoadBalancers/CookieStickySessionsCreator.cs
Outdated
Show resolved
Hide resolved
src/Ocelot/LoadBalancer/LoadBalancers/InMemoryStickySessionStorage.cs
Outdated
Show resolved
Hide resolved
908d84f to
0678e7a
Compare
Use File-scoped namespace declaration
Use File-scoped namespace declaration
Remove and Sort Usings
| private void CheckExpiry(StickySession sticky) | ||
| { | ||
| // TODO Get test coverage for this | ||
| lock (Locker) |
There was a problem hiding this comment.
In this context, and since we can have high throughput on Ocelot: using a semaphoreslim with a timeout seems more appropriate to me.
There was a problem hiding this comment.
Push commits to the feature branch! Noone will follow your suggestion.
| private readonly ConcurrentDictionary<string, StickySession> _storage; | ||
|
|
||
| public InMemoryStickySessionStorage() | ||
| => _storage = new(); |
There was a problem hiding this comment.
To avoid a bottleneck when starting the app, I recommend:
| => _storage = new(); | |
| => _storage = new(100); |
There was a problem hiding this comment.
Which bottleneck are you referring to, and why is it constant?
Raynald, are you ready to deliver this pull request?
Closes #1408
Problem to solve
The current implementation of
CookieStickySessionscontainsConcurrentDictionary<string, StickySession>where all the sessions are stored.We faced a situation when we need to have a few Ocelot instances on-premise of the customer
and we have some services that enforces us to use
CookieStickySessionsfor our Load Balancer.Having several instances of Ocelot push us to add the ability to use
CookieStickySessionsfor load balancing across these several Ocelot instances.To do so we need to have an ability to inject our own session storage implementation for
CookieStickySessions.New Feature
CookieStickySessionsCookieStickySessionsfor load balancing across these several Ocelot instancesProposed Changes
To do so, we need to:
CookieStickySessionsCookieStickySessionsCreatorto inject intoCookieStickySessionsown storage mechanism