Commit e2e09c46 by Dave Syer

Default turbine.amqp.port to server.port and allow Actuator endpoints

This change adds an ApplicationListener that sets some high priority properties in the Environment to allow server.port and management.port to keep their usual meaning, but have server.port apply only to turbine. Actuator endpoints can be enabled with management.port (different to server.port otherwise there will be a conflict between Netty and Tomcat). Fixes gh-143, fixes gh-140
parent 0e4eb9ef
...@@ -393,7 +393,7 @@ To run the Hystrix Dashboard annotate your Spring Boot main class with `@EnableH ...@@ -393,7 +393,7 @@ To run the Hystrix Dashboard annotate your Spring Boot main class with `@EnableH
Looking at an individual instances Hystrix data is not very useful in terms of the overall health of the system. https://github.com/Netflix/Turbine[Turbine] is an application that aggregates all of the relevant `/hystrix.stream` endpoints into a combined `/turbine.stream` for use in the Hystrix Dashboard. Individual instances are located via Eureka. Running Turbine is as simple as annotating your main class with the `@EnableTurbine` annotation. Looking at an individual instances Hystrix data is not very useful in terms of the overall health of the system. https://github.com/Netflix/Turbine[Turbine] is an application that aggregates all of the relevant `/hystrix.stream` endpoints into a combined `/turbine.stream` for use in the Hystrix Dashboard. Individual instances are located via Eureka. Running Turbine is as simple as annotating your main class with the `@EnableTurbine` annotation.
`turbine.appConfig` is a list of eureka serviceId's that turbine will use to lookup instances. `turbine.aggregator.clusterConfig` is used to group instances together. This comes from the eureka `InstanceInfo`. The clusterName is a SPEL expression evaluated against the InstanceInfo. The default clusterNameExpression is `appName`. The turbine stream is then used in the Hystrix dashboard using a url that looks like: http://my.turbine.sever:8080/turbine.stream?cluster=CUSTOMERS Configuration key `turbine.appConfig` is a list of eureka serviceId's that turbine will use to lookup instances. And `turbine.aggregator.clusterConfig` is used to group instances together (from the eureka `InstanceInfo`). The clusterName is a SPEL expression evaluated against the InstanceInfo. The default `clusterNameExpression` is `appName`. The turbine stream is then used in the Hystrix dashboard using a url that looks like: http://my.turbine.sever:8080/turbine.stream?cluster=CUSTOMERS
The `cluster` parameter must match an entry in `turbine.aggregator.clusterConfig`. The `cluster` parameter must match an entry in `turbine.aggregator.clusterConfig`.
...@@ -406,7 +406,17 @@ turbine: ...@@ -406,7 +406,17 @@ turbine:
appConfig: customers appConfig: customers
---- ----
The clusterName can be customized by a SPEL expression in `turbine.clusterNameExpression`. For example, `turbine.clusterNameExpression=aSGName` would get the clustername from the AWS ASG name. The `clusterName` can be customized by a SPEL expression in `turbine.clusterNameExpression`. For example, `turbine.clusterNameExpression=aSGName` would get the cluster name from the AWS ASG name.
Spring Cloud provides a `spring-cloud-starter-turbine` that has all the dependencies you need to get a Turbine server running. Just create a Spring Boot application and annotate it with `@EnableTurbine`.
=== Turbine AMQP
In some environments (e.g. in a PaaS setting), the classic Turbine model of pulling metrics from all the distributed Hystrix commands doesn't work. In that case you might want to have your Hystrix commands push metrics to Turbine, and Spring Cloud enables that with AMQP messaging. All you need to do on the client is add a dependency to `spring-cloud-netflix-hystrix-amqp` and make sure there is a Rabbit brooker available (see Spring Boot documentation for details on how to configure the client credentials, but it should work out of the box for a local broker or in Cloud Foundry).
On the server side Just create a Spring Boot application and annotate it with `@EnableTurbineAmqp` and by default it will come up on port 8989 (point your Hystrix dashboard to that port, any path). You can customize the port using either `server.port` or `turbine.amqp.port`. If you have `spring-boot-starter-web` and `spring-boot-starter-actuator` on the classpath as well, then you can open up the Actuator endpoints on a separate port (with Tomcat by default) by providing a `management.port` which is different.
Spring Cloud provides a `spring-cloud-starter-turbine-amqp` that has all the dependencies you need to get a Turbine AMQP server running. You need Java 8 to run the app because it is Netty-based.
[[spring-cloud-feign]] [[spring-cloud-feign]]
== Declarative REST Client: Feign == Declarative REST Client: Feign
......
...@@ -15,8 +15,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties ...@@ -15,8 +15,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.SmartLifecycle; import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.SocketUtils; import org.springframework.util.SocketUtils;
import rx.Observable; import rx.Observable;
import rx.subjects.PublishSubject; import rx.subjects.PublishSubject;
...@@ -36,6 +36,7 @@ public class TurbineAmqpConfiguration implements SmartLifecycle { ...@@ -36,6 +36,7 @@ public class TurbineAmqpConfiguration implements SmartLifecycle {
@Autowired @Autowired
private TurbineAmqpProperties turbine; private TurbineAmqpProperties turbine;
private int turbinePort; private int turbinePort;
@Bean @Bean
......
...@@ -2,6 +2,7 @@ package org.springframework.cloud.netflix.turbine.amqp; ...@@ -2,6 +2,7 @@ package org.springframework.cloud.netflix.turbine.amqp;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
...@@ -11,6 +12,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; ...@@ -11,6 +12,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@Data @Data
public class TurbineAmqpProperties { public class TurbineAmqpProperties {
@Value("${server.port:8989}")
private int port = 8989; private int port = 8989;
} }
package org.springframework.cloud.netflix.turbine.amqp;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.MapPropertySource;
public class TurbinePortSpringApplicationRunListener implements
ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
Integer serverPort = event.getEnvironment().getProperty("server.port",
Integer.class);
Integer managementPort = event.getEnvironment().getProperty("management.port",
Integer.class);
Integer turbinePort = event.getEnvironment().getProperty("turbine.amqp.port",
Integer.class);
if (serverPort == null && managementPort == null) {
return;
}
if (serverPort != -1) {
Map<String, Object> ports = new HashMap<String, Object>();
ports.put("server.port", -1);
if (serverPort != null && turbinePort==null) {
ports.put("turbine.amqp.port", serverPort);
}
event.getEnvironment().getPropertySources()
.addFirst(new MapPropertySource("ports", ports));
}
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.turbine.amqp.TurbineAmqpAutoConfiguration org.springframework.cloud.netflix.turbine.amqp.TurbineAmqpAutoConfiguration
org.springframework.context.ApplicationListener=\
org.springframework.cloud.netflix.turbine.amqp.TurbinePortSpringApplicationRunListener
\ No newline at end of file
...@@ -17,6 +17,7 @@ import org.springframework.test.context.web.WebAppConfiguration; ...@@ -17,6 +17,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest({ "server.port=0", "turbine.amqp.port=0", "spring.jmx.enabled=true" }) @IntegrationTest({ "server.port=0", "turbine.amqp.port=0", "spring.jmx.enabled=true" })
public class TurbineAmqpTests { public class TurbineAmqpTests {
@EnableAutoConfiguration @EnableAutoConfiguration
@EnableTurbineAmqp @EnableTurbineAmqp
public static class Application { public static class Application {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment