Spring cloud bus not updating config property for all instances - spring-boot

I am using spring cloud bus with kafka to update the config property for multiple instances at once.
I have a cloud-config server running on localhost:8888,
Find the below property for cloud config server :
server.port=8888
spring.application.name=clientServer
spring.cloud.config.server.default-label=master
spring.cloud.config.server.git.uri=https://github.com/kumawatanupriya/demo-cloud-config.git
management.endpoints.web.exposure.include=*
management.endpoint.env.post.enabled=true
spring.cloud.config.enabled=false
spring.cloud.bus.enabled=true
spring.cloud.stream.kafka.binder.brokers=localhost:9092
spring.cloud.stream.kafka.binder.zkNodes=localhost:2181
Find the below dependencies used for cloud config server :
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka'
implementation 'org.springframework.cloud:spring-cloud-config-server'
implementation 'org.springframework.cloud:spring-cloud-config-monitor'
I am running 3 instances of cloud-config-client on localhost:8080, 7011, 7012.
Find the below property for cloud config client :
spring.config.import=configserver:http://localhost:8888
management.endpoints.web.exposure.include=*
management.endpoint.env.post.enabled=true
spring.cloud.bus.enabled=true
spring.cloud.bus.refresh.enabled=true
spring.cloud.bus.env.enabled=true
endpoints.spring.cloud.bus.refresh.enabled=true
endpoints.spring.cloud.bus.env.enabled=true
spring.cloud.bus.trace.enabled=true
spring.cloud.stream.kafka.binder.autoAddPartitions=true
spring.cloud.stream.kafka.binder.brokers=localhost:9092
spring.cloud.stream.kafka.binder.zkNodes=localhost:2181
spring.profiles.active=test
Find the below dependencies used for config client :
implementation 'org.springframework.boot:spring-boot-starter-web'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka'
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.cloud:spring-cloud-stream'
implementation "org.springframework.cloud:spring-cloud-stream-binder-kafka"
I have a git repo with config file including property inventory.initial.mode.
When i update this property in github and hit this bus refresh endpoint localhost:8080/actuator/busrefresh. it only changes the value for one instances localhost:8080, it doesn't change it for 7011, 7012.
I tried hitting config-server refresh enpoint as well localhost:8888/actuator/busrefresh, but it also didn't update the value.
I added the monitor as well in config-server still it's not updating.
please help me identify the issue.
What am I doing wrong??

Related

Fail to disable AWS SQS configuration Spring Cloud AQS Messaging 2.2.0

I have a Spring profile dbmigration that should not need the AWS SQS bean or configuration. However, I am not being able to disable this configuration when I run with this profile.
Those are the only dependencies I have in my project:
val awsSdkVersion = "1.12.131"
[...]
// SQS Dependencies
implementation("org.springframework.cloud:spring-cloud-aws-messaging:2.2.6.RELEASE")
implementation("com.amazonaws:aws-java-sdk-core:$awsSdkVersion")
implementation("com.amazonaws:aws-java-sdk-sts:$awsSdkVersion")
Here are some guides I tried to follow:
https://davidagood.com/disable-spring-cloud-aws/
Spring boot cannot start with aws starter dependency
Turning off Spring Boot AWS Autoconfiguration
Also, I think is important to know that my configuration files are:
application.yml
application-dbmigration.yml
And I tried to change the library to: org.springframework.cloud:spring-cloud-starter-aws-messaging:2.2.6.RELEASE, also no success
Even tried to update to another version of this library:
val awsSdkVersion = "1.12.131"
val springCloudAwsVersion = "2.3.1"
[...]
implementation("io.awspring.cloud:spring-cloud-aws-messaging:${springCloudAwsVersion}")
implementation("io.awspring.cloud:spring-cloud-aws-autoconfigure:${springCloudAwsVersion}")
implementation("com.amazonaws:aws-java-sdk-core:$awsSdkVersion")
implementation("com.amazonaws:aws-java-sdk-sts:$awsSdkVersion")
No success.
I would prefer to do it through the configurations and application settings, instead of having to add #Profile("!dbmigration") in every Bean or Component related to SQS on my code.

Spring Cloud Embedded Config Server with native repository

I have a working spring boot application and I am trying to remove some properties from application.yaml file and read them from an embedded config server in the same app. At the moment, I am trying to read properties from file system through "native" profile type, and I am planning to later replace this with S3. Also, I am trying to read the configuration directly from backend repository as explained here https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#_embedding_the_config_server , rather than connecting through an endpoint.
If you want to read the configuration for an application directly from
the backend repository (instead of from the config server), you
basically want an embedded config server with no endpoints. You can
switch off the endpoints entirely by not using the #EnableConfigServer
annotation (set spring.cloud.config.server.bootstrap=true).
I have introduced following changes to my existing application to achieve this.
Added following dependencies to pom.xml
spring-cloud-starter-config
spring-cloud-config-server
spring-cloud-config-client
application-dev.yaml
spring:
could:
bootstrap:
enabled: true
bootstrap.yaml
spring:
profiles:
active: composite
cloud:
config:
server:
composite:
- type: native
search-locations: file:C:\\Users\\chamila\\config-test\\config
# bootstrap: true
The required properties are saved in a different application-dev.yaml file at the above file path. I have not used #EnableConfigServer annotation from my app class, as I want connect directly without the endpoint.
However, still my program is failing to read the properties from the config-server. I tried setting spring.cloud.config.server.bootstrap=true and spring.cloud.bootstrap.enabled=true from both application-dev.yaml and bootstrap.yaml, but it didn't work?
Any idea what I am missing? I note that I never specified how to connect to the config-server in my application-dev.yaml file also. Is that an issue?
Any help is highly appreciated.
I created a sample project of an embedded Configuration Server which uses a custom repository:
https://github.com/taxone/embedded-config-server
The initial problem was that the custom EnvironmentRepository was not available via bootstrap, as described in this issue.
I followed https://cloud.spring.io/spring-cloud-config/reference/html/#_embedding_the_config_server and achieved the expected result.
Add spring-cloud-starter-bootstrap to your dependencies as suggested in https://github.com/taxone/embedded-config-server.
Make sure that composite profile is active when you start the app.
Verify that your native configuration is added by finding a log message from NativeEnvironmentRepository during startup.
(Optional) Remove spring.cloud.bootstrap.enabled from application-dev.yaml.
(Optional) Remove spring-cloud-config-client dependency as it is included in both spring-cloud-starter-config and
spring-cloud-config-server.
(Further steps) Use #RefreshScope on a spring bean to achieve dynamic properties. Requires POST actuator/refresh.

How to override a property defined in profile-specific application-{profile}.yml for a single application?

I have a spring-cloud-config server set up to serve YML files from a git repository. The server is using Spring Cloud 2020.0.3. There are several spring-cloud-config clients consuming config files from the server. The client applications consuming the config are using Spring Boot 2.4.6 and the new config parsing implementation.
The config repository contains an application-db.yml file and myapp.yml file. The application-db.yml file has several common properties set that all applications will use for the db profile. myapp.yml has properties for a specific application. Prior to using Spring Boot 2.4.6, I was able to override properties from application-db.yml in myapp.yml. In effect, the application-db.yml properties were the default values that individual applications could override.
For example application-db.yml might have (property key is not relevant):
spring:
datasource:
hikari:
maximum-pool-size: 5
to set the connection pool size to 5 for most applications and myapp.yml could set
spring:
datasource:
hikari:
maximum-pool-size: 10
for a one-off connection pool size of 10.
In Spring Cloud 2020.0.3 (Spring Cloud Config 3.0.4) and Spring Boot 2.4.6, the behavior is that the property in application-db.yml cannot be overridden in myapp.yml and the connection pool size property always has value 5.
I have tried setting the following properties in the application.yml and still have the same results.
spring:
cloud:
config:
allowOverride: true
overrideNone: true
overrideSystemProperties: false
According to Config file processing in Spring Boot 2.4 overriding property values is allowed in the config processing, but it is dependent on document order.
Is the overriding behavior still supported by Spring Boot using Spring Cloud Config? If so, does it depend on the order the cloud config server serves the documents? Is there a way to control the order?
edit note: I originally posted about overriding properties in the application.yml file. After more investigation, that does allowing overriding. It is in the profile specific files like application-db.yml that I cannot override values. I'm starting to think this might be a bug.
The overriding behavior you are looking for is supported in the latest release documented here and should be the default behavior without needing to add additional properties to enable override. You will need to include the application name with the spring.application.name property for the config server to recognize the overriding file.The overriding file also needs to have the same name you give in the client application (in this case,for example, my config repo has files application.properties and myapp.properties.
Client application.properties
spring.application.name=myapp
spring.config.import=optional:configserver:http://localhost:8888
...
Server application.properties
spring.application.name=configserver
spring.cloud.config.server.git.uri=https://github.com/...
server.port=8888
...
Within config repo
application.properties
spring:
datasource:
hikari:
maximum-pool-size: 5
myapp.properties
spring:
datasource:
hikari:
maximum-pool-size: 10
If the client application cannot fetch the overriding file (in this case the myapp file) from the config server application, it will fall back to its local application.properties file. However, the application will probably fail if all of the properties your application needs are not present there as well, so it's a good practice to copy all properties from your overriding file to the client application.properties file in case fetch fails.
If this didn't fix your problem I would check out this section on property overrides.

Spring Cloud Client Config with placeholders

I have a Spring Boot application.yml with this config for Cloud Config:
spring:
cloud:
config:
uri: http://localhost:8080/config
name: ${cluster.name}
profile: ${cluster.idx}
I read cluster.name and cluster.idx from a custom PropertySouce that loads a JSON file. But Spring Boot is not capable of resolve the placeholder yet.
13:04:37,370 ERROR [main] org.springframework.boot.SpringApplication(SpringApplication.java:839) : Application startup failed
java.lang.IllegalArgumentException: Could not resolve placeholder 'cluster.idx' in string value "${cluster.idx}"
How do I tell Spring Boot to load my PropertySource before trying to resolve the placeholders? Thanks in advance.
I'm using Sp Boot 1.4.3 and Sp Cloud Config 1.2.2.
You won't be able to use the property sources as they are not yet available, and will not be at the time that this file is read. You have a couple of options, though. First, you can place these properties into the bootstrap.properties (or bootstrap.yml if you prefer). I suspect that you are trying to do something that's profile driven though and should use the appropriate properties for the profile. In this case, you can create bootstrap-{profile}.yml. So, if you are running with -Dspring.profiles.active=dev, you would have a bootstrap-dev.yml file that would contain the values for this profile.
The second and simpler approach would be to pass these to the VM as arguments. -Dcluster.name=foo -Dcluster.idx=bar

Spring Boot application log level

I want to change the log level of a Spring Boot application that is running.
Is it possible to change the log level at runtime? Right now I have the logger configuration in my jar itself.
Changing the log level while the application is running is part of the underlying logger implementation.
You did not specify the logger implementation you are using so I will assume you are using the default logback provided via the spring-boot-starter-logging or spring-boot-starter-web dependencies.
Comment out any logger related configurations from application.properties
e.g.
#logging.path=logs
#logging.level.org.springframework.web= INFO
#logging.level.=INFO
Add logback.xml in the root of your classpath with tag
See http://logback.qos.ch/manual/jmxConfig.html
Start the application and open JConsole and go to MBeans tab.
Select the package ch.qos.logback.classic.JMxConfigurator.Under default locate the setLoggerLevel operation
e.g. org.springframework.web, DEBUG
The change will be effective immediately.
For other logger libraries see the spring boot user guide
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html
And library specific information e.g. for log4j
http://www.sureshpw.com/2012/04/dynamic-logging-with-log4j.html
A different approach is to repeat the about steps without JMX and use configuration watcher
Logback Automatically reloading configuration file upon modification
Log4j configureAndWatch(java.lang.String, long)
If you want to change the logging level of an already running Spring Boot application you can take a look at spring-cloud-config. Refer to:
http://cloud.spring.io/spring-cloud-config/:
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments.
You can centrally manage the properties in config server and in your current application - applications.properties file (check bootstrap.properties) create an entry for
spring.application.name=application name
Using #RefreshScope annotation in your client application you will be able to refresh your application runtime and see the updated logging level property.
With the release of Spring Boot 1.5, if you have actuator in your Boot application you can do this through an out of the box REST API.
1.5 actuator provides an endpoint called 'loggers' which you can GET to view the configuration, and POST to make runtime changes.
Ex.
curl -i -X POST -H 'Content-Type: application/json' -d '{"configuredLevel": "DEBUG"}' http://localhost:8080/loggers/org.springframwork

Resources