Why does using ribbonReadTimeout don't break long request with Netflix Ribbon? - spring-boot

We are using Spring Boot 2.0.0.RELEASE with spring-cloud-starter-netflix-ribbon for our micro services. I set ribbon.readTimeout=1000 for slow requests and check it with our micro service setting breakpoint inside #GetMapping method without sending a response. In my test I have been waiting for 10 minutes and did not get any exception. It seems like there is no readTimeout at all.
Service configuration
ribbon:
ReadTimeout: 1000
my-service:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8080
ReadTimeout: 1000
ConnectTimeout: 1000
The only way a can make it work is ribbon.restclient.enabled=true. But this client is deprecated and I don't wont to use it.

Not all the ribbon properties are supported by spring-cloud-netflix while being used with a Spring RestTemplate. There are some ribbon properties that work, as described in the docs, but ReadTimeout is not one of them. So it does not work, but it's by desing (as per the response to this issue). However, if you are using Spring's RestTemplate, you can set it there directly, like so:
#LoadBalanced
#Bean
RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setReadTimeout(2000)
.build();
}

I think you need to configure Hystrix timeouts. Take a look at this part of the documentation : http://cloud.spring.io/spring-cloud-static/Edgware.RELEASE/single/spring-cloud.html#_hystrix_timeouts_and_ribbon_clients
It could be something like that :
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 1100
ribbon:
ConnectTimeout: 1000
ReadTimeout: 1000

We find this:
serviceA.ribbon.ReadTimeout=8000
work well with spring boot 2.1.0.RELEASE using spring cloud Finchley.SR2 and
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
However, we use ribbon via feign, in a client as so:
#FeignClient(value = "serviceA")
public interface ServiceAClient {
#GetMapping(value = "/test")
String getTest();
}
We then use a wiremock test to introduce a fixed delay above the read timeout to verify it is working fine.

Related

Spring-Boot-Actuator Endpoint Prometheus not shown correctly

I want to show some metrics using micrometer prometheus in combination with the spring-boot-actuator. My project is totally based on spring-boot and has the actuator feature enabled and mapped on the following url: http://localhost:9000/actuator
Other endpoints are shown correctly but the http://localhost:9000/actuator/prometheus isnĀ“t. Below you find a screenshot that I get when accessing this http-endpoint.
Can anybody help me? Why is this happening and how do i fix it?
Cause normally prometheus is configured automatically for spring-boot-actuator when you provide the suitable dependency.
you need to check many things to be sure to enable Prometheus by Actuator
First thing you should put the following dependency on your pom.xml to enable Prometheus on your project.
<!-- enable prometheus-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.10.2</version>
</dependency>
The second point you must check if the actuator exists on your
project or not if doesn't exist, you need to add the following
dependency.
<!--to enable actuator help to trace project-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
You need to add the following scripts to your application.yml to
enable the actuator and Prometheus by actuator.
.
management:
security:
enabled: false
server:
port: 9000
endpoint:
metrics:
enabled: true
prometheus:
enabled: true
health:
show-details: always
show-components: always
probes:
enabled: true
shutdown:
enabled: true
info:
env:
enabled: true
enabled: true
endpoints:
web:
exposure:
include: prometheus, metrics, info, health, shutdown, beans
using the above script the actuator will run on port 9000 and you can send a request to the following URL to access the actuator.
http://localhost:9000/actuator/prometheus
and the following URL to access Prometheus
http://localhost:9000/actuator/prometheus
Note: you must check where you are writing your script because I was confused between endpoint and endpoints
The endpoint to set the actuator config.
The endpoints to set the actuator URLs endpoint
Note: you can delete the port from application.yml and the actuator will run by current application port
best luck
This is auto-cofigured by default, here are some pointers for troubleshooting:
Check if you added micrometer-registry-prometheus (without defining the version, the version should come from the BOM)
Check if the actuator endpoint is enabled: management.endpoints.web.exposure.include=*
Check if there is a controller that maps the path of the prometheus endpoint or any of its sub-paths (/, /actuator, /actuator/prometheus)
Check if you browser tricks you curl localhost:9090/actuator/prometheus
ok i solved it with the solution:
i created a bean of type prometheusMeterRegistry manually and so spring boot didn't configure it automatically leading to no metrics provided at the prometheus endpoint
see below code snippet for further details:
// #Bean
// public PrometheusMeterRegistry prometheusMeterRegistry() {
// return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
// }
In my case I was trying to set up prometheus on old project where was MetricsAutoConfiguration excluded. So removing exclude solved the problem.
#EnableAutoConfiguration(exclude = { MetricsAutoConfiguration.class})

Expose metrics from spring application to prometheus without using spring-boot actuator

I have been trying to collect micrometer metrics in a non springboot application and expose them to prometheus.I have added the following dependency and the test method for the same.I would like to know how to proceed and expose the collected metrics to prometheus from my non spring boot application(traditional spring application).
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.2.0</version>
</dependency>
public string testmetrics(){
private PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
registry.counter("ws metric collection","tktdoc metrics");
String metricsInfo = registry.scrape();
return metricsInfo;
}
You practically have to expose an HTTP endpoint and configure Prometheus with it; the HTTP endpoint will supply the data for the scrapes.
An example showing how to add the HTTP endpoint by starting up an HTTP Server (your application may already be using one) is here.

Feign Client Prioritizing URL's in yaml over Eureka

I have a Spring Boot application which serves as a Eureka client. The application has the need to call another micro-service through REST, and I wish to make this call using Feign. The issue I am having is, my application is trying to lookup the service name in Eureka, when it is only defined in my applications yaml file.
I apologize for the hard to follow explanation, hopefully the following code snippets will help clarify.
Feign client:
#FeignClient("foo")
#Component
public interface FooServiceProxy{
#RequestMapping(value = "/balance", method = RequestMethod.POST, produces = "application/json")
ServiceResponse execute(ServiceRequest serviceRequest);
}
In my controller who calls this Feign client, the FooServiceProxy is defined using #AutoWired:
#Autowired
private FooServiceProxy fooServiceProxy;
My yaml file is as follows:
spring:
application:
name: app-name
server:
port: 8080
foo:
ribbon:
listOfServers: http://hostname:8081/balance
eureka:
client:
fetchRegistry: false
serviceUrl:
defaultZone: http://eurekasrver:8761/eureka/
My issue is, during run-time, the following error is thrown:
java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: foo
Interestingly, if I remove the #EnableEurekaClient annotation from the application, everything works. I believe I understand the problem which is that instead of looking up the server for foo in my yaml file, because the application is a Eureka client, Feign is going straight to Eureka to lookup a server ip, then failing as none can be found. Despite seeming to understand the problem, I have been unable to find a solution online or to think of one myself.
Any help will be appreciated.
Thank you!
Concerning this question, you should take in account that when eureka is on your classpath, all ribbon configuration are charged by eureka, so it'll use eureka server's list.
Spring Cloud uses #RibbonClient to configure the types used by ribbon, like server list. If you have eureka on the classpath, by default it uses the eureka server list (hence your need for the flag to disable eureka).
Commented by spencergibb https://github.com/spring-cloud/spring-cloud-netflix/issues/564
You can try either by adding the NIWSServerListClassName configuration:
`someservice.ribbon:
NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
listOfServers: server1:80`
Or try the solution proposed in this issue https://github.com/spring-cloud/spring-cloud-netflix/issues/564

How to create more than one health check endpoints with Spring Boot Actuator

What I want to do
Create two (different) endpoints using Spring Boot Actuator
My environment
Spring Boot 1.4.2
spring-boot-starter-actuator embedded in Spring Boot 1.4.2
Detail
I'm creating a Web app using Spring Boot and will need to create two separated endpoints: one for just checking application health including the app's DB connection and so on (This will be realized by the default behavior of "/health") and the other for just checking if the app is ready for accepting HTTP requests (say "/httpcheck").
To implement health check feature, I guess it's the fastest way to use Spring Boot Actuator (by default, /health is mapped to health check endpoint).
I also understand we can configure this endpoint by extending AbstractHealthIndicator (so that it will include DB health check).
But as far as I could see, I could not find a way to create more than one endpoints to do different health checks.
Do you have any ideas?
Thanks in advance.
Thanks for your answer.
Actually, I dealt with this problem by implementing a new endpoint (/httpcheck) to simply check if its HTTP stack works well or not.
HttpCheckEndpoint.java
#Component
#ConfigurationProperties(prefix = "endpoints.httpcheck") // Specifies the prefix on application.yml
public class HttpCheckEndpoint extends AbstractMvcEndpoint {
public HttpCheckEndpoint() {
super("/httpcheck", false);
}
/**
* Check if simply the app can connect to their own HTTP stack and return 200 OK.
* <ul>
* <li>Method: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS</li>
* <li>Endpoint: "/httpcheck"</li>
* </ul>
*/
#RequestMapping
#ResponseBody
public ResponseEntity<String> checkHttpConnecton() {
if (!isEnabled()) {
return new ResponseEntity<String>("", HttpStatus.NOT_FOUND);
} else {
return new ResponseEntity<String>("{\"status\": \"UP\"}", HttpStatus.OK);
}
}
}
application.yml
endpoints:
enabled: false # Default enabled/disabled on endpoints on Spring Boot Actuator
health: # Health check (already prepared in Spring Boot Actuator)
enabled: true
httpcheck: # Simple HTTP connection check (newly created by myself)
enabled: true
I've confirmed it worked well, although not sure if it's the best solution...
Solution
You can use Jolokia end points in your Spring-boot application and get it registered with o.s.b.a.e.jmx.EndpointMBeanExporter along with your Actuator Plugins.
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
<version>1.2.2</version>
</dependency>
Jolokia Configurations in application.properties
jolokia.config.debug=true
endpoints.jolokia.enabled=true

How to change the endpoint of prometheus metrics

I am trying to expose some metrics from a spring-boot service to prometheus.
Unfortunately, both spring-boot actuator and the prometheus simple-client expose their metrics through the /metrics endpoint.
How can the endpoint of the simple-client be changed?
Thanks
You might want to have a look at the Prometheus Java Simpleclient Spring Boot Metric it exposes prometheus metrics at the /prometheus endpoint.
Github Project: https://github.com/prometheus/client_java/tree/master/simpleclient_spring_boot
Maven Artifact: https://mvnrepository.com/artifact/io.prometheus/simpleclient_spring_boot
On your pom.xml:
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_spring_boot</artifactId>
<version>0.0.17</version>
</dependency>
In your springboot configuration class:
#Configuration
public class Configuration {
#Bean
public ServletRegistrationBean servletRegistrationBean() {
DefaultExports.initialize();
return new ServletRegistrationBean(new MetricsServlet(), "/prometheus");
}
#Bean
public SpringBootMetricsCollector springBootMetricsCollector(Collection<PublicMetrics> publicMetrics) {
SpringBootMetricsCollector springBootMetricsCollector = new SpringBootMetricsCollector(
publicMetrics);
springBootMetricsCollector.register();
return springBootMetricsCollector;
}
You can change spring-boot actuator's endponit and leave /metrics to Prometheus.
Add following configurations to your application.properties:
endpoints.metrics.id=springmetrics
endpoints.metrics.sensitive=false
endpoints.metrics.enabled=true
and you'll have a new endpoint /springmetics for spring actuator and /metrics for Prometheus.
For the java client you specify the endpoint when setting up the servlet, see https://github.com/RobustPerception/java_examples/blob/master/java_simple/src/main/java/io/robustperception/java_examples/JavaSimple.java#L39 for example. You can change the endpoint to whatever you like.
Have you tried to set up these properties in your application.properties file:
management.endpoints.web.path-mapping.prometheus=
management.endpoints.web.base-path=

Resources