-
Notifications
You must be signed in to change notification settings - Fork 18
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
Implement a custom HystrixPropertiesStrategy plugin #36
Implement a custom HystrixPropertiesStrategy plugin #36
Conversation
Add a custom HystrixPropertiesStrategy implementation where getCommandPropertiesCacheKey is overridden to return null so that HystrixPropertiesFactory will always generate a new HystrixCommandProperties for each new HystrixCommand instantiation.
Should fix #31 |
Apparently you can only register a strategy once inside a single Java process and subsequent attempts will cause exceptions to be thrown. Instead of registering in Global, which, depending on libs/other singletons/w/e, may already be too late, use the hystrix.plugin.HystrixPropertiesStrategy.implementation system property and name our class.
Might be a good idea to try to make sure CachelessHystrixPropertiesStrategy is used in Global during onStart if the system property is not set
* Resist the temptation to do a HystrixPlugins.getInstance().getPropertiesStrategy first to do | ||
* checking, as that actually also sets the strategy if it isn't already set. | ||
*/ | ||
def setHystrixPropertiesStrategy(app: Application): Unit = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure if this is a good idea, or we should just make end-users responsible for always sending the hystrix.plugin.HystrixPropertiesStrategy.implementation
system property. Suggestions on other alternatives are welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As Octoparts should mostly run out-of-the-box, I'd suggest to not use this hystrix.plugin.HystrixPropertiesStrategy.implementation
env variable, and use this new one in any case.
I woud like to clarify :
|
|
Also of note is this Hystrix issue: Netflix/Hystrix#34 Looks like they don't want people to be changing properties at runtime. |
* generate a new [[HystrixCommandProperties]] for each new [[com.netflix.hystrix.HystrixCommand]] instantiation | ||
*/ | ||
class CachelessHystrixPropertiesStrategy extends HystrixPropertiesStrategy { | ||
override def getCommandPropertiesCacheKey(commandKey: HystrixCommandKey, builder: HystrixCommandProperties.Setter): String = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could build the cache key with commandKey + (a hash of) builder, this should avoid the forewarned performance issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so maintain our own Map as a cache. Sounds like a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reflecting on this now, I guess can get the hashCode of builder
, combine it with the commandKey.name
in a string and return that.
HystrixPropertiesFactory
will be responsible for caching the properties using the returned string anyways.
The disadvantage is that theoretically, the cache could grow out of hand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the least invasive solution so far 👍
On Oct 3, 2014 7:21 PM, "Lloyd" [email protected] wrote:
In app/com/m3/octoparts/hystrix/CachelessHystrixPropertiesStrategy.scala:
@@ -0,0 +1,13 @@
+package com.m3.octoparts.hystrix
+
+import com.netflix.hystrix.{ HystrixCommandKey, HystrixCommandProperties }
+import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy
+
+/**
- * Custom [[HystrixPropertiesStrategy]] implementation where getCommandPropertiesCacheKey is overridden
- * to return null so that [[com.netflix.hystrix.strategy.properties.HystrixPropertiesFactory]] will always
- * generate a new [[HystrixCommandProperties]] for each new [[com.netflix.hystrix.HystrixCommand]] instantiation
- */
+class CachelessHystrixPropertiesStrategy extends HystrixPropertiesStrategy {- override def getCommandPropertiesCacheKey(commandKey: HystrixCommandKey, builder: HystrixCommandProperties.Setter): String = null
Reflecting on this now, I guess can get the hashCode of builder, combine
it with the commandKey.name in a string and return that.`HystrixPropertiesFactory will be responsible for caching the properties
using the returned string anyways.The disadvantage is that theoretically, the cache could grow out of hand.
@mauhiz https://github.com/mauhiz @cb372 https://github.com/cb372
what do you think?—
Reply to this email directly or view it on GitHub
https://github.com/m3dev/octoparts/pull/36/files#r18388802.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, builder is not a case class and hashCode
for the builder is not overridden to be based on the values of the builder, meaning we get new hashCodes for every single newly instantiated builder..
I suppose one way is to manually write a function that grabs values from the builder's accessors (there are at least 20 now), but I don't want to go down that route without exploring other solutions (maybe even just continue returning null)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, as of cf0507a, I've changed it to return a string that is a combination of the CommandKey name and the builder JSON string value. Human-readable too now as a bonus.
Interesting. I think that PR relates to not allowing injecting different property strategies (via a HystrixCommand) depending on code path, not properties themselves ("property strategy" is not the same as "property"). Since then, the project has changed so that once you set a property strategy, you can no longer change it Regarding CircuitBreakers, we currently don't allow customisation of circuit breaker settings, so it doesn't directly affect us (yet), and a quick look through the code shows that CircuitBreakers are cached in I think with Octoparts being essentially something that adds runtime definition support of Hystrix-backed operations, our use-case is slightly different and maybe we might have to ignore some of the recommendations they give. The alternative is we say you can't change Hystrix-related stuff once it's been defined (or at least without restarting the service), which is doesn't seem very friendly. |
@@ -14,4 +14,4 @@ before_script: | |||
- psql -c "CREATE USER octoparts_app WITH PASSWORD '';" -U postgres | |||
- psql -c "GRANT ALL PRIVILEGES ON DATABASE octoparts_test to octoparts_app;" -U postgres | |||
|
|||
script: "sbt coveralls" | |||
script: "sbt coveralls test" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't coveralls already run tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it was the way we were using it, but the coveralls
task is troublesome in that if the compilation fails (like this), the exit status is 0 if the report is uploaded to coveralls properly and the whole build is marked as successful 😆
There may be a more elegant solution to adding test
after coveralls
but I'm not too sure.
…rties-strategy Implement a custom HystrixPropertiesStrategy plugin
Add a custom HystrixPropertiesStrategy implementation where getCommandPropertiesCacheKey is overridden to return null so that HystrixPropertiesFactory will always generate a new HystrixCommandProperties for each new HystrixCommand instantiation.