From 7b8792cc1ae20c18180e3982ee9fcdbd80d0d8bd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 4 Mar 2016 13:13:56 +0000 Subject: [PATCH] Add hystrix/turbine amqp samples --- bus/src/main/resources/application.yml | 1 - hystrix-amqp/README.md | 1 + hystrix-amqp/docker-compose.yml | 5 + hystrix-amqp/pom.xml | 108 ++++++++++++++++++ .../main/java/demo/HystrixApplication.java | 41 +++++++ .../src/main/java/demo/MyService.java | 23 ++++ .../src/main/resources/application.properties | 3 + .../java/demo/HystrixApplicationTests.java | 63 ++++++++++ turbine-amqp/docker-compose.yml | 5 + turbine-amqp/pom.xml | 108 ++++++++++++++++++ .../java/demo/TurbineStreamApplication.java | 14 +++ .../src/main/resources/application.properties | 4 + .../demo/TurbineStreamApplicationTests.java | 31 +++++ .../src/test/resources/eureka.properties | 4 + .../src/test/resources/simple.properties | 2 + 15 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 hystrix-amqp/README.md create mode 100644 hystrix-amqp/docker-compose.yml create mode 100644 hystrix-amqp/pom.xml create mode 100644 hystrix-amqp/src/main/java/demo/HystrixApplication.java create mode 100644 hystrix-amqp/src/main/java/demo/MyService.java create mode 100644 hystrix-amqp/src/main/resources/application.properties create mode 100644 hystrix-amqp/src/test/java/demo/HystrixApplicationTests.java create mode 100644 turbine-amqp/docker-compose.yml create mode 100644 turbine-amqp/pom.xml create mode 100644 turbine-amqp/src/main/java/demo/TurbineStreamApplication.java create mode 100644 turbine-amqp/src/main/resources/application.properties create mode 100644 turbine-amqp/src/test/java/demo/TurbineStreamApplicationTests.java create mode 100644 turbine-amqp/src/test/resources/eureka.properties create mode 100644 turbine-amqp/src/test/resources/simple.properties diff --git a/bus/src/main/resources/application.yml b/bus/src/main/resources/application.yml index c340ca6..4476b5c 100644 --- a/bus/src/main/resources/application.yml +++ b/bus/src/main/resources/application.yml @@ -1,7 +1,6 @@ spring: application: name: bus - --- spring: profiles: other diff --git a/hystrix-amqp/README.md b/hystrix-amqp/README.md new file mode 100644 index 0000000..e146fe4 --- /dev/null +++ b/hystrix-amqp/README.md @@ -0,0 +1 @@ +This project is a sample of using just the hystrix starter diff --git a/hystrix-amqp/docker-compose.yml b/hystrix-amqp/docker-compose.yml new file mode 100644 index 0000000..1a53d6e --- /dev/null +++ b/hystrix-amqp/docker-compose.yml @@ -0,0 +1,5 @@ +rabbitmq: + image: rabbitmq:management + ports: + - "5672:5672" + - "15672:15672" diff --git a/hystrix-amqp/pom.xml b/hystrix-amqp/pom.xml new file mode 100644 index 0000000..45044f2 --- /dev/null +++ b/hystrix-amqp/pom.xml @@ -0,0 +1,108 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-sample-hystrix-amqp + Brixton.BUILD-SNAPSHOT + jar + + spring-cloud-sample-hystrix-amqp + Demo project for Spring Cloud + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.BUILD-SNAPSHOT + + + + + UTF-8 + 1.7 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-hystrix + + + org.springframework.cloud + spring-cloud-netflix-hystrix-stream + + + org.springframework.cloud + spring-cloud-starter-stream-rabbit + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + maven-deploy-plugin + + true + + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + diff --git a/hystrix-amqp/src/main/java/demo/HystrixApplication.java b/hystrix-amqp/src/main/java/demo/HystrixApplication.java new file mode 100644 index 0000000..d7a22e1 --- /dev/null +++ b/hystrix-amqp/src/main/java/demo/HystrixApplication.java @@ -0,0 +1,41 @@ +package demo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@EnableCircuitBreaker +@RestController +public class HystrixApplication { + + @Bean + public MyService myService() { + return new MyService(); + } + + @Autowired + private MyService myService; + + @RequestMapping("/") + public String ok() { + return myService.ok(); + } + + @RequestMapping("/fail") + public String fail() { + return myService.fail(); + } + + public static void main(String[] args) { + SpringApplication.run(HystrixApplication.class, args); + } +} diff --git a/hystrix-amqp/src/main/java/demo/MyService.java b/hystrix-amqp/src/main/java/demo/MyService.java new file mode 100644 index 0000000..ad995e3 --- /dev/null +++ b/hystrix-amqp/src/main/java/demo/MyService.java @@ -0,0 +1,23 @@ +package demo; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; + +/** + * @author Spencer Gibb + */ +public class MyService { + + @HystrixCommand(fallbackMethod = "fallback") + public String ok() { + return "OK"; + } + + @HystrixCommand(fallbackMethod = "fallback") + public String fail() { + throw new RuntimeException("fail now"); + } + + public String fallback() { + return "from the fallback"; + } +} diff --git a/hystrix-amqp/src/main/resources/application.properties b/hystrix-amqp/src/main/resources/application.properties new file mode 100644 index 0000000..67d89bc --- /dev/null +++ b/hystrix-amqp/src/main/resources/application.properties @@ -0,0 +1,3 @@ +# This way you get to see the exceptions when the fallback is accessed +logging.level.com.netflix.hystrix.AbstractCommand: DEBUG +logging.level.org.springframework.integration: DEBUG \ No newline at end of file diff --git a/hystrix-amqp/src/test/java/demo/HystrixApplicationTests.java b/hystrix-amqp/src/test/java/demo/HystrixApplicationTests.java new file mode 100644 index 0000000..bff821b --- /dev/null +++ b/hystrix-amqp/src/test/java/demo/HystrixApplicationTests.java @@ -0,0 +1,63 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import java.io.InputStream; +import java.net.URL; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = HystrixApplication.class) +@IntegrationTest("server.port=0") +@WebAppConfiguration +@DirtiesContext +public class HystrixApplicationTests { + + @Value("${local.server.port}") + int port; + + @Test + public void testOk() { + ResponseEntity response = new TestRestTemplate().getForEntity("http://localhost:" + port, String.class); + assertNotNull("response was null", response); + assertEquals("Bad status code", HttpStatus.OK, response.getStatusCode()); + assertEquals("Wrong response text", "OK", response.getBody()); + } + + @Test + public void testFallback() { + ResponseEntity response = new TestRestTemplate().getForEntity("http://localhost:" + port+"/fail", String.class); + assertNotNull("response was null", response); + assertEquals("Bad status code", HttpStatus.OK, response.getStatusCode()); + assertEquals("Wrong response text", "from the fallback", response.getBody()); + } + + @Test + public void hystrixStreamWorks() throws Exception { + String url = "http://localhost:" + port; + //you have to hit a Hystrix circuit breaker before the stream sends anything + ResponseEntity response = new TestRestTemplate().getForEntity(url, String.class); + assertEquals("bad response code", HttpStatus.OK, response.getStatusCode()); + + URL hystrixUrl = new URL(url + "/hystrix.stream"); + InputStream in = hystrixUrl.openStream(); + byte[] buffer = new byte[1024]; + in.read(buffer); + String contents = new String(buffer); + assertTrue(contents.contains("ping")); + in.close(); + } +} diff --git a/turbine-amqp/docker-compose.yml b/turbine-amqp/docker-compose.yml new file mode 100644 index 0000000..1a53d6e --- /dev/null +++ b/turbine-amqp/docker-compose.yml @@ -0,0 +1,5 @@ +rabbitmq: + image: rabbitmq:management + ports: + - "5672:5672" + - "15672:15672" diff --git a/turbine-amqp/pom.xml b/turbine-amqp/pom.xml new file mode 100644 index 0000000..8de956a --- /dev/null +++ b/turbine-amqp/pom.xml @@ -0,0 +1,108 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-sample-turbine-amqp + Brixton.BUILD-SNAPSHOT + jar + + spring-cloud-sample-turbine-amqp + Demo project for Spring Cloud + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.BUILD-SNAPSHOT + + + + + UTF-8 + demo.DemoApplication + 1.7 + + + + + org.springframework.cloud + spring-cloud-starter-turbine-amqp + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + maven-deploy-plugin + + true + + + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/libs-snapshot-local + + true + + + + spring-milestones + Spring Milestones + http://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + http://repo.spring.io/release + + false + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/libs-snapshot-local + + true + + + + spring-milestones + Spring Milestones + http://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + http://repo.spring.io/release + + false + + + + + diff --git a/turbine-amqp/src/main/java/demo/TurbineStreamApplication.java b/turbine-amqp/src/main/java/demo/TurbineStreamApplication.java new file mode 100644 index 0000000..748e635 --- /dev/null +++ b/turbine-amqp/src/main/java/demo/TurbineStreamApplication.java @@ -0,0 +1,14 @@ +package demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.turbine.stream.EnableTurbineStream; + +@SpringBootApplication +@EnableTurbineStream +public class TurbineStreamApplication { + + public static void main(String[] args) { + SpringApplication.run(TurbineStreamApplication.class, args); + } +} diff --git a/turbine-amqp/src/main/resources/application.properties b/turbine-amqp/src/main/resources/application.properties new file mode 100644 index 0000000..6449849 --- /dev/null +++ b/turbine-amqp/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.port: 8989 +spring.application.name: turbine +turbine.appConfig: simple +turbine.aggregator.clusterConfig: SIMPLE diff --git a/turbine-amqp/src/test/java/demo/TurbineStreamApplicationTests.java b/turbine-amqp/src/test/java/demo/TurbineStreamApplicationTests.java new file mode 100644 index 0000000..8ae41de --- /dev/null +++ b/turbine-amqp/src/test/java/demo/TurbineStreamApplicationTests.java @@ -0,0 +1,31 @@ +package demo; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = TurbineStreamApplication.class) +@DirtiesContext +public class TurbineStreamApplicationTests { + + @Autowired + DiscoveryClient discoveryClient; + + @Test + public void contextLoads() { + } + + @Test + public void discoveryClientIsEureka() { + assertTrue("discoveryClient is wrong type", discoveryClient instanceof EurekaDiscoveryClient); + } + +} diff --git a/turbine-amqp/src/test/resources/eureka.properties b/turbine-amqp/src/test/resources/eureka.properties new file mode 100644 index 0000000..a0e3d7f --- /dev/null +++ b/turbine-amqp/src/test/resources/eureka.properties @@ -0,0 +1,4 @@ +server.port: 8761 +spring.application.name: eureka +eureka.client.registerWithEureka=false +eureka.client.fetchRegistry=false \ No newline at end of file diff --git a/turbine-amqp/src/test/resources/simple.properties b/turbine-amqp/src/test/resources/simple.properties new file mode 100644 index 0000000..ec7a5fc --- /dev/null +++ b/turbine-amqp/src/test/resources/simple.properties @@ -0,0 +1,2 @@ +server.port: 8080 +spring.application.name: simple