Skip to content

introduce singleton manager and fix multiple TLS date providers#1410

Merged
mattklein123 merged 9 commits intomasterfrom
fix_date_tls
Aug 9, 2017
Merged

introduce singleton manager and fix multiple TLS date providers#1410
mattklein123 merged 9 commits intomasterfrom
fix_date_tls

Conversation

@mattklein123
Copy link
Copy Markdown
Member

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.

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.
@mattklein123
Copy link
Copy Markdown
Member Author

@lyft/network-team @htuch @dnoe

@bplotnick this should fix your issue.


/**
* @return Singleton::Manager& the server-wide singleton manager.
*/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High level question: should this subsume existing singleton state on the server? E.g. initManager(), listenerManager() etc.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification. Yeah, either an issue or maybe just some TODO to move the other ones under here later.

@ryan-lane ryan-lane closed this Aug 7, 2017
@ryan-lane ryan-lane reopened this Aug 7, 2017
@bplotnick
Copy link
Copy Markdown
Contributor

bplotnick commented Aug 7, 2017

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>,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you comment on the tradeoffs of using a string in the template vs. a concrete type as done in Registry::RegisterFactory?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, less boiler plate is always better, thanks for the clarification.

/**
* 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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will clarify.

* @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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could do this, but it would involve passing a lambda into this function. If you like that better happy to do it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be an ASSERT? I.e., is this something that could happen if not programmer error.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asserts make more sense if this is the expected use.

@mattklein123
Copy link
Copy Markdown
Member Author

@htuch updated

Copy link
Copy Markdown
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

* @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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to have callers check for validity?

#pragma once

namespace Envoy {
namespace Singleton {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mattklein123
Copy link
Copy Markdown
Member Author

@htuch updated

@mattklein123 mattklein123 merged commit 2ad6cfd into master Aug 9, 2017
@mattklein123 mattklein123 deleted the fix_date_tls branch August 9, 2017 17:02
jpsim pushed a commit that referenced this pull request Nov 28, 2022
Signed-off-by: Mike Schore <[email protected]>
Signed-off-by: JP Simard <[email protected]>
jpsim pushed a commit that referenced this pull request Nov 29, 2022
Signed-off-by: Mike Schore <[email protected]>
Signed-off-by: JP Simard <[email protected]>
mathetake pushed a commit that referenced this pull request Mar 3, 2026
**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]>
mathetake added a commit that referenced this pull request Mar 3, 2026
**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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants