I am using #HystrixCommand in a #Component in a Spring Boot application configured using Spring Cloud Config and the Hystrix command is not picking the configuration.
If I use the Actuator env endpoint, I see my Hystrix configuration.
"hystrix.command.default.circuitBreaker.enabled": true,
"hystrix.command.default.circuitBreaker.requestVolumeThreshold": 20,
"hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds": 20000,
"hystrix.command.default.execution.isolation.strategy": "THREAD",
"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": 10000,
"hystrix.command.default.execution.timeout.enabled": true,
"hystrix.command.default.metrics.rollingStats.numBuckets": 200,
"hystrix.command.default.metrics.rollingStats.timeInMilliseconds": 10000,
If I use the archaius endpoint I see nothing.
{}
I can see the configuration using following in my fallback. It confirms I am only getting configuration from the #HystrixCommand.
HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(commandKey);
HystrixReporter.reportMetric(HystrixCommandMetrics.getInstance(commandKey), text -> logger.debug(text));
I can use the #HystrixCommand to configure the Hystric command but want dynamic run-time configuration.
Here is a snippet from my build.gradle.
springBootVersion = '1.5.4.RELEASE'
...
ext {
springCloudVersion = 'Dalston.SR1'
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.cloud:spring-cloud-starter-feign')
compile('org.springframework.cloud:spring-cloud-starter-hystrix')
compile('org.springframework.integration:spring-integration-jms')
I keep seeing this comment so it should "just" work:
External Configuration: a bridge from the Spring Environment to Archaius
Here is the application.yml supplied by Spring Cloud Config server.
hystrix:
command:
default:
circuitBreaker:
enabled: true
requestVolumeThreshold: 20
sleepWindowInMilliseconds: 20000
execution:
isolation:
strategy: THREAD
thread:
timeoutInMilliseconds: 10000
timeout:
enabled: true
metrics:
rollingStats:
numBuckets: 200
timeInMilliseconds: 10000
threadpool:
default:
coreSize: 10
maximumSize: 10
maxQueueSize: -1
metrics:
polling-interval-ms: 5000
Related
I have a Spring Boot 2, Java 8 application using Resilience4j (version 1.3) CircuitBreaker (CB). The default CB properties in my application yaml look like this -
resilience4j.circuitbreaker:
configs:
default:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10000
failureRateThreshold: 50
eventConsumerBufferSize: 10
recordExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.util.concurrent.TimeoutException
- java.io.IOException
ignoreExceptions:
- org.springframework.web.client.HttpClientErrorException
I was hoping every CB I create would end up with these default values but it does not appear to be the case.
// Case 1: Does not load defaults from yaml
#Bean
CircuitBreaker xCircuitBreaker(CircuitBreakerRegistry circuitBreakerRegistry) {
return circuitBreakerRegistry.circuitBreaker("xCircuitBreaker");
}
// Case 2: Does not load defaults from yaml
#Bean
CircuitBreaker yCircuitBreaker() {
return CircuitBreaker.ofDefaults("yCircuitBreaker");
}
// Case 3: Works
#Bean
public CircuitBreaker zCircuitBreaker(CircuitBreakerRegistry circuitBreakerRegistry,
#Value("${resilience4j.circuitbreaker.configs.default.slidingWindowSize}") Integer slidingWindowSize,
#Value("${resilience4j.circuitbreaker.configs.default.permittedNumberOfCallsInHalfOpenState}") Integer permittedNumberOfCallsInHalfOpenState,
#Value("${resilience4j.circuitbreaker.configs.default.minimumNumberOfCalls}") Integer minimumNumberOfCalls,
#Value("${resilience4j.circuitbreaker.configs.default.failureRateThreshold}") Integer failureRateThreshold,
#Value("${resilience4j.circuitbreaker.configs.default.waitDurationInOpenState}") Integer waitDurationInOpenState,
#Value("${resilience4j.circuitbreaker.configs.default.automaticTransitionFromOpenToHalfOpenEnabled}") Boolean automaticTransitionFromOpenToHalfOpenEnabled) {
CircuitBreakerConfig cfg = CircuitBreakerConfig.custom()
.slidingWindowSize(slidingWindowSize)
.minimumNumberOfCalls(minimumNumberOfCalls)
.permittedNumberOfCallsInHalfOpenState(permittedNumberOfCallsInHalfOpenState)
.failureRateThreshold(failureRateThreshold)
.waitDurationInOpenState(Duration.ofMillis(waitDurationInOpenState))
.automaticTransitionFromOpenToHalfOpenEnabled(automaticTransitionFromOpenToHalfOpenEnabled)
.recordException(recordFailurePredicate())
.recordExceptions(HttpServerErrorException.class)
.ignoreExceptions(HttpClientErrorException.class)
.build();
return circuitBreakerRegistry.circuitBreaker("zCircuitBreaker", cfg);
}
I am hoping I don't have to resort to case 3. Is there something I am doing incorrectly in Case 1 and 2? For the purposes of this testing, I am using an InMemoryCircuitBreakerRegistry. I appreciate your help.
Thank you
Please use the Spring Boot starter from Resilience4j and don't create a CircuitBreaker manually via a bean. Everything is done automatically for you on-the-fly.
I had a grails 3 app including spring security, which I recently upgraded to grails 4.
My application.yml includes the following:
environments:
test:
grails:
plugin:
springsecurity:
active: false
security:
ignored: '/**'
basic:
enabled: false
spring:
security:
enabled: false
Why doesn't this work in Grails 4? What's a good alternative solution?
Grails 4 seems to be ignoring this configuration. When I run integration tests, I am getting a 403 error with a message:
Could not verify the provided CSRF token because your session was not found.
It seems like spring security enabled, and it's using SecurityFilterAutoConfiguration, which is normally excluded for my app.
Update
I am using the following dependencies:
compile('org.grails.plugins:spring-security-core:3.2.3') {
exclude group: 'org.springframework.security'
}
compile ('org.springframework.security:spring-security-core:4.2.13.RELEASE') {
force = true
}
compile 'org.springframework.security:spring-security-web:4.2.13.RELEASE'
compile 'org.springframework.security:spring-security-config:4.2.13.RELEASE'
Update 2:
In my debugger, I found that the spring security core plugin actually is being disabled. The following code from the plugin class is executed:
SpringSecurityUtils.resetSecurityConfig()
def conf = SpringSecurityUtils.securityConfig
boolean printStatusMessages = (conf.printStatusMessages instanceof Boolean) ? conf.printStatusMessages : true
if (!conf || !conf.active) {
if (printStatusMessages) {
// <-- the code in this block is executed; active flag is false
String message = '\n\nSpring Security is disabled, not loading\n\n'
log.info message
println message
}
return
}
...however, I am still getting the CSRF filter error, so Spring Security must be configuring itself somehow regardless.
Update 3:
The CSRF filter is being set up by ManagementWebSecurityConfigurerAdapter, using the default configuration.
I tried adding the following to resources.groovy:
if (grailsApplication.config.disableSecurity == true && !Environment.isWarDeployed()) {
webSecurityConfigurerAdapter(new WebSecurityConfigurerAdapter(true) {})
}
This did not fix the issue. Although my anonymous WSCA bean is being constructed, the MWSCA default bean is still being used by spring.
Try this in
grails-app/conf/application.groovy
environments {
development {
}
test {
grails.plugin.springsecurity.active = false
}
production {
}
}
My Team migrated our Microservices from Spring Boot 1 to Version 2 and since the Actuator changed, our Health Endpoint Metrics exported via prometheus jmx exporter do not work anymore.
The usual /actuator/health is working as expected, but the prometheus-jmx-exporter won't pick it up although several things tried:
I changed the Metainformation in the exporter-config.yaml to reflect the name change in Spring Boot 2
I added the io.micrometer:micrometer-registry-prometheus to our build.gradle to see if this is the issue
I exposed web and jmx endpoints acording to the Spring Boot 2 Documentation
So now I run out of ideas and would appreciate any hints oyu might be able to give me
old prometheus-jmx-exporter exporter-config.yaml:
---
lowercaseOutputName: true
lowercaseOutputLabelNames: true
whitelistObjectNames: ["org.springframework.boot:type=Endpoint,name=healthEndpoint"]
rules:
- pattern: 'org.springframework.boot<type=Endpoint, name=healthEndpoint><(.*, )?(.*)>(.*):'
name: health_endpoint_$1$3
attrNameSnakeCase: true
new prometheus-jmx-exporter exporter-config.yaml:
---
lowercaseOutputName: true
lowercaseOutputLabelNames: true
whitelistObjectNames: ["org.springframework.boot:type=Endpoint,name=Health"]
rules:
- pattern: 'org.springframework.boot<type=Endpoint, name=Health>'
name: health_endpoint_$1$3
attrNameSnakeCase: true
current application properties about actuator endpoints:
management.endpoints.web.exposure.include=info, health, refresh, metrics, prometheus
management.endpoints.jmx.exposure.include=health, metrics, prometheus
in Spring Boot 1 with the old exporter-config.yaml I get results like this:
# HELP health_endpoint_hystrix_status Invoke the underlying endpoint (org.springframework.boot<type=Endpoint, name=healthEndpoint><hystrix, status>status)
# TYPE health_endpoint_hystrix_status untyped
health_endpoint_hystrix_status 1.0
# HELP health_endpoint_status Invoke the underlying endpoint (org.springframework.boot<type=Endpoint, name=healthEndpoint><status>status)
# TYPE health_endpoint_status untyped
health_endpoint_status 1.0
But with all the changes and in Spring Boot 2 I get nothing out of this.
You can cofigure your own health value and add it to the Prometheus Metrics endpoint:
#Configuration
public class HealthMetricsConfiguration {
#Bean
public MeterRegistryCustomizer prometheusHealthCheck(HealthEndpoint healthEndpoint) {
return registry -> registry.gauge("health", healthEndpoint, HealthMetricsConfiguration::healthToCode);
}
public static int healthToCode(HealthEndpoint ep) {
Status status = ep.health().getStatus();
return status.equals(Status.UP) ? 1 : 0;
}
}
I'm using Spring Boot health indicator from an actuator. So far example response looks like:
{
"status":"DOWN",
"details": {
"diskSpace": {
"status":"UP",
"details": {
"total":499963170816,
"free":250067189760,
"threshold":10485760
}
}
}
}
Because I need to make /actuator/health endpoint public, I need to hide details for health indicators, so I expect to get something like this:
{
"status":"DOWN",
"details": {
"diskSpace": {
"status":"UP"
}
}
}
For disk space it's not a big problem but e.g. for database I don't want to share exception message and details in case of it's outage. Also (as I mentioned at the beginning) it must be public so I don't want to make this endpoint 'when-authorized'. And at the end - it would be great if it's possible to do that without writing my own custom endpoint.
Is it possible at all?
This isn't possible at the time of writing (in Spring Boot 2.1 and earlier) without writing your own custom endpoint. I've opened an issue to consider it as an enhancement for a future version of Spring Boot.
There is a way to achieve this in Spring Boot 2.X
management:
health:
db:
enabled: false
diskspace:
enabled: false
mongo:
enabled: false
refresh:
enabled: false
More information can be found here https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#_auto_configured_healthindicators
I am using spring cloud stream Kafka sync producer in a spring boot micro service. every time we deploy the service the very first call to kafka takes more than 20 seconds to publish the message to Topic. but all the subsequent calls takes hardly 3 to 4 miliseconds. This issue also happens randomly and is intermittent but mostly happens when we restart the service.
we are using kafka version 0.9.0.1 and gradle dependencies as below
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-stream-kafka')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.SR3"
}
}
here is the application. yml
spring:
cloud:
stream:
bindings:
output:
content-type: application/json
destination: SOPOrderReceiveTopic
kafka:
binder:
brokers: "localhost:9092,localhost:9093"
headers: eventType
requiredAcks: -1
zkNodes: "localhost:2181"
bindings:
output:
producer:
configuration:
max:
block:
ms: 20000
reconnect:
backoff:
ms: 5000
request:
timeout:
ms: 30000
retries: 3
retry:
backoff:
ms: 10000
timeout:
ms: 30000
sync: true
I am using org.springframework.cloud.stream.messaging.Source as output channel and this is the method used to publish message
public void publish(Message event) {
try {
boolean result = source.output().send(event, orderEventConfig.getTimeoutMs());
logger.log(LoggingEventType.INFORMATION, "MESSAGE SENT TO KAFKA : " + result);
} catch (Exception publishingExceptionMessage) {
logger.log(LoggingEventType.ERROR, "publish event to kafka failed!", publishingExceptionMessage);
throw new PublishEventException("publish event to kafka failed for eventPayload: " + event.getPayload(),
ThreadVariables.getTenantId());
}
}
I am aware that sync producer is slower is terms of performance as it guarantees the order and durability of message but why only the first request takes so long? is this issue a known issue ? is it fixed in the latest kafka version. can somebody suggest. thanks
It looks like there is an issue with the version for spring cloud stream downloaded using below dependency ,
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.SR3"
}
Try upgrading the spring cloud stream and check. It should fix the latency in the first publishing call on kafka server after springboot service startup.
dependencies {
compile('org.springframework.cloud:spring-cloud-stream-binder-kafka')
}
ext { springCloudVersion = 'Dalston.RELEASE' }
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}