introduce singleton manager and fix multiple TLS date providers#1410
introduce singleton manager and fix multiple TLS date providers#1410mattklein123 merged 9 commits intomasterfrom
Conversation
It is a common problem that there needs to be a single instance of something in the server. This change introduces the concept of the singleton manager which can be used for that purpose. All singletons are looked up by name and must be statically registered like existing filters. This avoids collision. This change uses the singleton manager to create a single TLS date provider for the entire server. Fixes #1362.
|
@lyft/network-team @htuch @dnoe @bplotnick this should fix your issue. |
|
|
||
| /** | ||
| * @return Singleton::Manager& the server-wide singleton manager. | ||
| */ |
There was a problem hiding this comment.
High level question: should this subsume existing singleton state on the server? E.g. initManager(), listenerManager() etc.
There was a problem hiding this comment.
It probably could/should. I basically did this because I did not want to add another top level singleton and plumb it through everywhere. I don't think it's super critical that we back-fill but could open an issue to track.
I think this will be generally useful for things that are added on or not core to the server such that everyone will use no matter what (.e.g, redis, mongo, etc.). Everyone will use the cluster manager, init manager, listener manager, etc. so those are a gray area IMO.
There was a problem hiding this comment.
Thanks for the clarification. Yeah, either an issue or maybe just some TODO to move the other ones under here later.
|
I only took a brief look through the code (and C++ is certainly not my specialty), but I pulled this branch and it looks like the CPU usage is significantly lower in my high listener count use case 👍 |
| * and must be statically registered ahead of time. This can be done like so: | ||
| * | ||
| * static constexpr char foo_singleton_name[] = "foo_singleton"; | ||
| * static Registry::RegisterFactory<Singleton::RegistrationImpl<foo_singleton_name>, |
There was a problem hiding this comment.
Can you comment on the tradeoffs of using a string in the template vs. a concrete type as done in Registry::RegisterFactory?
There was a problem hiding this comment.
I did this because it's less typing (technically it is a concrete type, it's just an instantiation of RegistrationImpl). We only need name() which is required by registry. I could probably modify Registry to support a name only registration but that seemed like overkill. If you feel otherwise I can do that.
There was a problem hiding this comment.
Sure, less boiler plate is always better, thanks for the clarification.
include/envoy/singleton/manager.h
Outdated
| /** | ||
| * This is a helper on top of get() that casts the object stored to the specified type. No type | ||
| * information is specified explicitly in code so dynamic_cast provides some level of protection | ||
| * via RTTI. |
There was a problem hiding this comment.
Not sure I follow the second sentence here (the "no type information is specified explicitly"), unless this has to do with the template string arg.
include/envoy/singleton/manager.h
Outdated
| * @param name supplies the singleton name. Must be registered via RegistrationImpl. | ||
| * @param singleton supplies the singleton. NOTE: The manager only stores a weak pointer. This | ||
| * allows a singleton to be cleaned up if it is not needed any more. All code that uses | ||
| * singletons must check for validity and create a new singleton if needed. It must also |
There was a problem hiding this comment.
Would it make sense to have the check for validity + create a utility function in the manager, to avoid repeating this pattern in lots of places?
There was a problem hiding this comment.
I could do this, but it would involve passing a lambda into this function. If you like that better happy to do it.
There was a problem hiding this comment.
It seems a bit cleaner to centralize it to me, so I'd have a slight preference to do it this way all things being equal.
| } | ||
|
|
||
| void ManagerImpl::verifyRegistration(const std::string& name) { | ||
| if (nullptr == Registry::FactoryRegistry<Registration>::getFactory(name)) { |
There was a problem hiding this comment.
Should this be an ASSERT? I.e., is this something that could happen if not programmer error.
There was a problem hiding this comment.
I think it probably needs to be more than an ASSERT since we want to verify the name is unique. I could make it a PANIC() with appropriate message. I just did exception since it's easier to test. No real preference either way (could also switch to an illegal arg exception which would be more likely to crash).
There was a problem hiding this comment.
We'd probably catch most of the core Envoy violations of this in the CI runs if it was an ASSERT, but I see the value of making it an exception or panic when Envoy is extended by other folks. So, up to you what you feel is best on this, just wanted to clarify my understanding.
| namespace Singleton { | ||
|
|
||
| InstancePtr ManagerImpl::get(const std::string& name) { | ||
| verifyRegistration(name); |
There was a problem hiding this comment.
Does it make sense to have any thread checks here? Can anyone other than the main thread access this? IF so, do we need to lock to avoid racing on get/set?
There was a problem hiding this comment.
My intention was for this to be used by the main thread only, though it doesn't really matter. I can either add appropriate asserts or add locking? Which do you prefer?
There was a problem hiding this comment.
Asserts make more sense if this is the expected use.
|
@htuch updated |
include/envoy/singleton/manager.h
Outdated
| * @param singleton supplies the singleton creation callback. This will only be called if the | ||
| * singleton does not already exist. NOTE: The manager only stores a weak pointer. This | ||
| * allows a singleton to be cleaned up if it is not needed any more. All code that uses | ||
| * singletons must check for validity and create a new singleton if needed. It must also |
There was a problem hiding this comment.
Do we still need to have callers check for validity?
| #pragma once | ||
|
|
||
| namespace Envoy { | ||
| namespace Singleton { |
There was a problem hiding this comment.
Can you cleanup the TODO in https://github.com/lyft/envoy/blob/master/source/common/common/singleton.h#L19 and and add a pointer in the comments on that class to where to go for mutable singletons.
If we didn't want cleanup on last dropped reference, and only had default constructors, we could do something simple like what is done for ConstSingleton perhaps.
|
@htuch updated |
Signed-off-by: Mike Schore <[email protected]> Signed-off-by: JP Simard <[email protected]>
Signed-off-by: Mike Schore <[email protected]> Signed-off-by: JP Simard <[email protected]>
**Description** Envoy AI Gateway currently requires an envoy gateway config map to be overriden. The better approach is to pass the configmap as helm values during envoy gateway helm install. This PR makes changes to the documentation and installation files to do the same. **Related Issues/PRs (if applicable)** Fixes: envoyproxy/ai-gateway#1191 --------- Signed-off-by: sailesh duddupudi <[email protected]>
**Description** Since #1410, the deployment created by EG for the rate limit server is in crashing loop until redis server is up and running in the rate limit e2e test setup, which caused a bit of flake in the test. This fixes it by restarting the deployment just in case. This also removes the only remaining use of t.Context in test cleanup function in e2e tests. Signed-off-by: Takeshi Yoneda <[email protected]>
It is a common problem that there needs to be a single instance of
something in the server. This change introduces the concept of the
singleton manager which can be used for that purpose. All singletons
are looked up by name and must be statically registered like existing
filters. This avoids collision.
This change uses the singleton manager to create a single TLS date provider
for the entire server.
Fixes #1362.