Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix backend reuse #3312

Merged
merged 7 commits into from Jun 6, 2018
Merged

Fix backend reuse #3312

merged 7 commits into from Jun 6, 2018

Conversation

arnested
Copy link
Contributor

@arnested arnested commented May 11, 2018

What does this PR do?

This fixes the way backends are currently cached leading t some frontend configuration being ignored when re-using same backend (reported in #2323).

Motivation

Not being able to reuse backends in different frontends is unexpected and the workaround results in defining additional, identical backends.

In a current project of mine I could potentially end up with 400 identical backends to work around this.

Fixes #2323

More

  • Added/updated tests
  • Added/updated documentation: No, this fixes a bug in internal behaviour

Additional Notes

Currently backends are cached under a key generated by entryPointName+providerName+frontend.Backend. The frontend.Backend doesn't respect the differences present in frontends.

I add Hash() method to the Frontend struct and use that instead of just the backend name.

The Hash method uses github.com/mitchellh/hashstructure which is also used in collector/collector.go (a nice feature of it is being able to ignore some fields when computing the hash).

@arnested arnested changed the title Fix/backend caching Fix backend caching May 11, 2018
@ldez ldez self-assigned this May 14, 2018
@ldez ldez added the kind/enhancement a new or improved feature. label May 16, 2018
server/server.go Outdated
@@ -925,7 +925,7 @@ func (s *Server) loadConfig(configurations types.Configurations, globalConfigura
redirectHandlers[entryPointName] = handlerToUse
}
}
if backends[entryPointName+providerName+frontend.Backend] == nil {
if backends[entryPointName+providerName+frontend.Hash()] == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this string be stored, and referenced, instead of being recalculated multiple times?

Copy link
Contributor Author

@arnested arnested May 30, 2018

Choose a reason for hiding this comment

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

Yes, that should be doable. I'll just need to make sure the frontend isn't changed between usages of a stored string.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was just thinking inside the loop. Instead of calculating .Hash() three times.
entryPointName+providerName+frontend.Hash() in your PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I hadn't checked if shady things where done to the frontend in the loop (although that would also have been a bug if it did).

Implemented in b716cb2b3c892a678d9cac77954dea11ae9439bc.

types/types.go Outdated
@@ -188,6 +189,13 @@ type Frontend struct {
Redirect *Redirect `json:"redirect,omitempty"`
}

// Hash returns the hash value of a Frontend struct.
func (f *Frontend) Hash() string {
hash, _ := hashstructure.Hash(f, nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should handle the error here. If the hash goes sideways, you are going to want to log or potentially return an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree. I think I took a shortcut because from te definition of the Hash() it is not able to produce an error with the current definition of the Frontend struct. But that's not very kind on the people doing changes in the future.

I'll create fixes for this (today or tomorrow probably).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in d44fde676f86f2d039b2b8e4798f6b25a5d98e3a.

Copy link
Contributor

@dtomcej dtomcej left a comment

Choose a reason for hiding this comment

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

LGTM
:shipit:

@arnested
Copy link
Contributor Author

arnested commented Jun 6, 2018

Thank you for the approve, @dtomcej.

GitHub has detected a conflict in server/server_test.go because the tests have been refactored into using testhelpers.

I have refactored my test method to use the new test helpers as well.

Fun story. The refactored test helpers have a bug in WithFrontend(): it will cache the frontends under the backend name (the fun part being this is the same kind of bug as I'm trying to fix in this pull request 😄).

I had to rebase on master to not make everything completely unreadable. I introduced a new commit (cc69be54446b021ed3bdbbf11d770497d7fa70ae) that fixes the bug in the test helper. Next commit (fb9ed685b943d918e6b1e78659061b0ca88282d2) is my original test case refactored to use the new test helpers. The rest of the commits are as you reviewed them.

types/types.go Show resolved Hide resolved
Copy link
Member

@ldez ldez left a comment

Choose a reason for hiding this comment

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

Thanks!

Copy link
Member

@mmatur mmatur left a comment

Choose a reason for hiding this comment

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

LGTM

@ldez ldez changed the title Fix backend caching Fix backend reuse Jun 6, 2018
@traefiker traefiker merged commit 5122724 into traefik:master Jun 6, 2018
@arnested arnested deleted the fix/backend-caching branch July 9, 2018 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement a new or improved feature. size/S
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Some frontend configuration is ignored when re-using same backend
5 participants