#RefreshScope is working without /actuator/refresh being enabled - java

So I am reading about Kubernetes PropertySource in Spring Cloud and how to configure spring to reload a value when it is changed in kubernetes configmap. As far as the doc says:
refresh (default): Only configuration beans annotated with
#ConfigurationProperties or #RefreshScope are reloaded. This reload
level leverages the refresh feature of Spring Cloud Context.
The RefreshScope is a bean in the context and has a public
refreshAll() method to refresh all beans in the scope by clearing the
target cache. The /refresh endpoint exposes this functionality (over
HTTP or JMX). To refresh an individual bean by name, there is also a
refresh(String) method.
To expose the /refresh endpoint, you need to add following
configuration to your application:
management: endpoints:
web:
exposure:
include: refresh
So I'm guessing the refresh actuator endpoint needs to be enabled otherwise it won't work, right?
But I have a microservice that is configured as follows but it is working completely correct and when configmap changes, the value gets updated.
bootstrap.yaml:
spring:
cloud:
kubernetes:
reload:
enabled: true
mode: polling
strategy: refresh
config:
name: foo
application.yaml:
management:
endpoint:
health:
show-details: "ALWAYS"
probes:
enabled: true
endpoints:
web:
exposure:
include: metrics, health, caches, restart
As you can see, there is no refresh endpoint enabled. How is it working properly then?

Related

Spring Boot Actuators only exposing limited endpoints

I am trying to expose additional actuator endpoints in my Spring Boot 2.3 service. Attempting to add endpoints such as the prometheus and metrics for monitoring. But for some reason, the exposed endpoints are locked to the default loggers,health,info.
For some background, within the org, there is a parent Spring dependency which automatically brings all of the Spring essentials, as well as some generic code useful within the org. I use this dependency in many of my other projects and was able to expose these additional actuator endpoints successfully. However, in this project with multiple artifacts, I am unable to edit the default exposed actuator endpoints.
Printing the configurableEnvironment post init always shows the exposure property as follows
management.endpoints.web.exposure.include = loggers,health,info
This is after trying to override this property to an expanded list (loggers,health,info,Prometheus,metrics) using below methods:
Enabling specific endpoint via management.endpoint.metrics.enabled: true
Specifying these values in application.yaml
Passing this as a Command line arguement Dmanagement.endpoints.web.exposure.include=loggers,health,info,prometheus,metrics
Using mvn dependency:tree To exclude any transitive actuator dependencies
I don’t believe its due to the org’s parent pom, likely due to another dependency we are using. But due to the size of this project, it is quite hard to remove dependencies to test. Is there any way to track down where these properties are set. Or perhaps additional ways to force exposure of the additional endpoints I want?
——
Actuator config
management:
endpoints:
web:
exposure:
include: metrics,prometheus,info,health,logging
endpoint:
env:
enabled: true
metrics:
enabled: true
info:
enabled: true
health:
enabled: true
show-details: always
beans:
enabled: true
caches:
enabled: true
threaddump:
enabled: true
prometheus:
enabled: true
Actuator info
{"_links":{"self":{"href":"http://localhost:9050/actuator","templated":false},"health":{"href":"http://localhost:9050/actuator/health","templated":false},"health-path":{"href":"http://localhost:9050/actuator/health/{*path}","templated":true},"info":{"href":"http://localhost:9050/actuator/info","templated":false},"loggers":{"href":"http://localhost:9050/actuator/loggers","templated":false},"loggers-name":{"href":"http://localhost:9050/actuator/loggers/{name}","templated":true}}}
Your question lacks some background, like your pom.xml or build.gradle files and full application.yml config.
I will go through the basic steps, which you may have missed.
Firstly, please make sure that you've included the Prometheus dependency:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
Also, don't forget that some metrics require the AOP dependency (like custome timers, for example):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
To enable the Prometheus metrics exposure, you should specify such configuration in your application.yml file (it seems like you did it correctly, but let's list it here for the full picture):
management:
endpoints:
web.exposure.include: health, info, prometheus
To verify that the Prometheus endpoints were exposed, please use the GET request to this URL: http://localhost:8080/actuator/prometheus
If those steps don't help you resolve your issue, please add more details to your question.

How do you use Spring Boot Actuator using JMX only on a non-web spring boot app

I am trying to create a stand alone GRPC server but with Spring Boot so I get DI and other things that are provided by Spring Boot. What I am trying to do is implement the health check endpoint via JMX but when I run it with the following dependendices (note I commented out webflux because I don't want the webflux engine)
runtimeOnly 'org.springframework.boot:spring-boot-starter-actuator'
// implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
My application yaml is
spring:
main:
banner-mode: "off"
web-application-type: none
management:
endpoint:
health:
enabled: true
endpoints:
jmx:
exposure:
include: health
When I go to jconsole locally I don't see any of the spring boot mbeans though.
I tried to spring.application.admin.enabled: true and spring.jmx.enabled: true with no luck
Actually it was one of my attempts that just didn't start up correctly. The value to enable it is spring.jmx.enabled so the YAML stanza would be.
spring:
main:
banner-mode: "off"
web-application-type: none
jmx:
enabled: true
management:
endpoint:
health:
enabled: true
endpoints:
jmx:
exposure:
include: health

spring-cloud how to use Endpoints

management endpoints:
For a Spring Boot Actuator application there are some additional management endpoints:
POST to /env to update the Environment and rebind #ConfigurationProperties and log levels
http://localhost:8080/env/testprop it works and returns:
{
"testprop": "test value"
}
but when I do POST: http://localhost:8080/env/testprop
Request method 'POST' not supported
I want to update testprop, how to do it with API?
I found the following in the docs
For a Spring Boot Actuator application there are some additional management endpoints:
POST to /env to update the Environment and rebind #ConfigurationProperties and log levels
/refresh for re-loading the boot strap context and refreshing the #RefreshScope beans
/restart for closing the ApplicationContext and restarting it (disabled by default)
/pause and /resume for calling the Lifecycle methods (stop() and start() on the ApplicationContext)
Looks like you have to post agains /env instead of /end/$yourProperty
Ok, it works:
must POST with empty body
http://localhost:8080/env/?test=dasda
and response is:
{
"test": "dasda"
}

Settings in application.yml for spring.cloud.config aren't used when app is executing

I have a problem with spring cloud: my settings in application.yml for spring.cloud.config aren't used when app is executing. let me put more detail here.
I'd like to my services could get settings from a remote ConfigServer. I've created the ConfigServer as a spring boot app with annotation #EnableConfigServer.
After that i've created client app with next config file:
application:
name: mw
cloud:
config:
enabled: true
uri: http://172.17.42.1:8888
fail-fast: true
main class:
#EnableEurekaClient
#SpringBootApplication
public class MwApplication
and extra configuration into app:
#Configuration
#EnableJpaRepositories(basePackages = {"com.sample.repository"})
#EnableTransactionManagement
#EnableScheduling
public class AppConfiguration
also i have next dependencies:
spring-cloud-starter-eureka
spring-cloud-config-client
spring-boot-configuration-processor
spring-boot-starter-data-jpa
When i execute my client app, i've got this message: ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/mw/default"
The app try to get data from default uri(localhost) instead of to use uri from my setting. I've looked at app in debug mode and saw org.springframework.cloud.config.client.ConfigServiceBootstrapConfiguration was creating ConfigClientProperties with default property and my settings from application.yml weren't used.
What am i doing wrong?
thanks.
You need to add the following to your application.yml file:
spring:
cloud:
config:
enabled: true
Per comment chain, you also need to add the properties to bootstrap.yml instead of application.yml . The reason is that the former is loaded before the latter in the spring startup cycle. Here is another SO post answered by user Michael Isvy explaining why, and copied below for posterity: What is the diference between putting a property on application.yml or bootstrap.yml in spring boot?
I have just asked the Spring Cloud guys and thought I should share the info I have here.
bootstrap.yml is loaded before application.yml.
It is typically used for the following:
when using Spring Cloud Config Server, you should specify spring.application.name and spring.cloud.config.server.git.uri inside bootstrap.yml
some encryption/decryption information
Technically, bootstrap.yml is loaded by a parent Spring ApplicationContext. That parent ApplicationContext is loaded before the one that uses application.yml.

Spring Cloud Eureka with Config Server

What is the recommended configuration when running both Config Server with Eureka Server? Should Config Server be a client of Eureka? Or should Eureka be dependent on Config Server properties for its configuration? Or is both OK?
The default way to use Eureka and Config Server is to use Config First bootstrap. Essentially, you make eureka server a client of the config server but you don't make the config server a client of eureka.
As said by David Syer on these (and this) issues, the founder of spring cloud, you have to use the config server with a front end load balancer, so a single URL is already highly available.
I'm also a newbie in Spring Cloud but I agree with him since Eureka is a Service Discovery, IMHO it should function on it's problem domain only. It would make a complicated logic for Eureka servers who are asking the Config servers for it's configuration. I can't imagine how the Eureka Server would know which config server to get if the Config Server is also the Server of Eureka to get its list of defaultZone.
It would be much more simpler for me to separate the Config Server's HA.
Based on #Mideel's answer
Eureka and Config Client configuration (needs to be Bootstrap):
# bootstrap.yml
cloud:
config:
discovery:
enabled: true # This is required
service-id: configserver # Config Server's eureka registry name
enabled: true # This is default true already
Config Server configuration:
spring:
application:
name: configserver # Needs to match client configuration
Register the Config Server with the annotation #EnableEurekaClient (it should be Auto Configured to register with Eureka already though)
The Spring Cloud Config service provides configuration info for various other microservices, of which the Eureka service is one.
Each app/microservice is pointed to its configuration (from the Config service) via bootstrap.properties/.yml, which is loaded in the parent context for that application, before the app "recognizes" that it is a discovery/Eureka client per its annotated main class. This bit of documentation provides a bit more detail on that process.
Cheers,
Mark
EDIT1: I think this is a wrong answer, see the replies
If you use Spring Boot:
I'm using Spring Microservices in Action as my guide book and based on the source code example there, we make the configuration server as the Eureka Client with the #EnableEurekaClient annotation and in the config server application.yml, we need to add this property:
spring:
cloud:
config:
discovery:
enabled: true
And in the other Eureka client that uses this config server, you need to add this property to the application.yml :
spring:
cloud:
config:
enabled: true
That's it, just set up the config server normally, I think behind the scene the config libraries from spring cloud will take care of the rest using Eureka.

Categories

Resources