├── README.md
├── src
├── main
│ ├── webapp
│ │ ├── index.jsp
│ │ └── WEB-INF
│ │ │ ├── spring-servlet.xml
│ │ │ └── web.xml
│ ├── resources
│ │ ├── logback.xml
│ │ └── applicationContext.xml
│ └── java
│ │ └── com
│ │ └── xianlinbox
│ │ └── hystrix
│ │ ├── model
│ │ ├── Contact.java
│ │ ├── Customer.java
│ │ └── Address.java
│ │ ├── filter
│ │ └── HystrixRequestContextServletFilter.java
│ │ ├── dao
│ │ ├── AddressDao.java
│ │ ├── ContactDao.java
│ │ ├── ContactHystrixCommand.java
│ │ ├── AddressHystrixCommand.java
│ │ └── HystrixCommandAdvice.java
│ │ ├── controller
│ │ └── CustomerController.java
│ │ └── service
│ │ └── CustomerService.java
└── test
│ └── java
│ ├── com
│ └── xianlinbox
│ │ └── hystrix
│ │ └── service
│ │ └── CustomerServiceTest.java
│ └── demo
│ ├── SemaphoreEchoCommand.java
│ ├── ThreadEchoCommand.java
│ ├── DemoTest.java
│ ├── CommandCollapserGetValueForKey.java
│ ├── CollapseEchoHystrixCommand.java
│ └── HystrixCommandTest.java
└── .gitignore
/README.md:
--------------------------------------------------------------------------------
1 | ###A Demo with Spring MVC 4 and Hystrix
2 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse
2 | .classpath
3 | .project
4 | .settings/
5 |
6 | # Intellij
7 | *.ipr
8 | .idea/
9 | *.iml
10 | *.iws
11 |
12 | # Mac
13 | .DS_Store
14 |
15 | # Maven
16 | log/
17 | target/
18 | build/
19 | out/
20 |
21 | # Gradle
22 | .gradle/
23 | activemq-data/*
24 |
25 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/model/Contact.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.model;
2 |
3 | public class Contact {
4 | private String phone;
5 | private String mobile;
6 | private String email;
7 |
8 | public String getPhone() {
9 | return phone;
10 | }
11 |
12 | public void setPhone(String phone) {
13 | this.phone = phone;
14 | }
15 |
16 | public String getMobile() {
17 | return mobile;
18 | }
19 |
20 | public void setMobile(String mobile) {
21 | this.mobile = mobile;
22 | }
23 |
24 | public String getEmail() {
25 | return email;
26 | }
27 |
28 | public void setEmail(String email) {
29 | this.email = email;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/java/com/xianlinbox/hystrix/service/CustomerServiceTest.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.service;
2 |
3 | import com.xianlinbox.hystrix.model.Customer;
4 | import org.junit.Before;
5 | import org.junit.Test;
6 |
7 | import static org.hamcrest.CoreMatchers.equalTo;
8 | import static org.junit.Assert.assertThat;
9 |
10 | public class CustomerServiceTest {
11 | private CustomerService service;
12 |
13 | @Before
14 | public void setUp() throws Exception {
15 | service = new CustomerService();
16 | }
17 |
18 | @Test
19 | public void testGetCustomer() throws Exception {
20 | Customer customer = service.getCustomer("1234");
21 | assertThat(customer.getId(), equalTo("1234"));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/model/Customer.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.model;
2 |
3 | public class Customer {
4 | private String id;
5 | private String name;
6 | private Contact contact;
7 | private Address address;
8 |
9 | public Customer(String id, String name) {
10 | this.id = id;
11 | this.name = name;
12 | }
13 |
14 | public void setContact(Contact contact) {
15 | this.contact = contact;
16 | }
17 |
18 | public void setAddress(Address address) {
19 | this.address = address;
20 | }
21 |
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public Contact getContact() {
27 | return contact;
28 | }
29 |
30 | public Address getAddress() {
31 | return address;
32 | }
33 |
34 | public String getId() {
35 | return id;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/filter/HystrixRequestContextServletFilter.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.filter;
2 |
3 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
4 |
5 | import javax.servlet.*;
6 | import java.io.IOException;
7 |
8 | public class HystrixRequestContextServletFilter implements Filter {
9 | @Override
10 | public void init(FilterConfig filterConfig) throws ServletException {
11 | }
12 |
13 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
14 | throws IOException, ServletException {
15 | HystrixRequestContext context = HystrixRequestContext.initializeContext();
16 | try {
17 | chain.doFilter(request, response);
18 | } finally {
19 | context.shutdown();
20 | }
21 | }
22 |
23 | @Override
24 | public void destroy() {
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/model/Address.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.model;
2 |
3 | public class Address {
4 | private String country;
5 | private String province;
6 | private String city;
7 | private String detail;
8 |
9 | public String getCountry() {
10 | return country;
11 | }
12 |
13 | public void setCountry(String country) {
14 | this.country = country;
15 | }
16 |
17 | public String getProvince() {
18 | return province;
19 | }
20 |
21 | public void setProvince(String province) {
22 | this.province = province;
23 | }
24 |
25 | public String getCity() {
26 | return city;
27 | }
28 |
29 | public void setCity(String city) {
30 | this.city = city;
31 | }
32 |
33 | public String getDetail() {
34 | return detail;
35 | }
36 |
37 | public void setDetail(String detail) {
38 | this.detail = detail;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/dao/AddressDao.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.dao;
2 |
3 | import com.xianlinbox.hystrix.model.Address;
4 | import org.apache.http.client.fluent.Request;
5 | import org.codehaus.jackson.map.ObjectMapper;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.io.IOException;
10 |
11 | public class AddressDao {
12 | private Logger logger = LoggerFactory.getLogger(AddressDao.class);
13 |
14 | public Address getAddress(String customerId) throws IOException {
15 | logger.info("Get address for customer {}", customerId);
16 | String response = Request.Get("http://localhost:9090/customer/" + customerId + "/address")
17 | .connectTimeout(1000)
18 | .socketTimeout(1000)
19 | .execute()
20 | .returnContent()
21 | .asString();
22 |
23 | return new ObjectMapper().readValue(response, Address.class);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/dao/ContactDao.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.dao;
2 |
3 | import com.xianlinbox.hystrix.model.Contact;
4 | import org.apache.http.client.fluent.Request;
5 | import org.codehaus.jackson.map.ObjectMapper;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.io.IOException;
10 |
11 | public class ContactDao {
12 | private Logger logger = LoggerFactory.getLogger(ContactDao.class);
13 |
14 | public Contact getContact(String customerId) throws IOException {
15 | logger.info("Get contact for customer {}", customerId);
16 | String response = Request.Get("http://localhost:9090/customer/" + customerId + "/contact")
17 | .connectTimeout(1000)
18 | .socketTimeout(1000)
19 | .execute()
20 | .returnContent()
21 | .asString();
22 |
23 | return new ObjectMapper().readValue(response, Contact.class);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/controller/CustomerController.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.controller;
2 |
3 | import com.xianlinbox.hystrix.model.Customer;
4 | import com.xianlinbox.hystrix.service.CustomerService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RequestMethod;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | public class CustomerController {
13 |
14 | @Autowired
15 | private CustomerService customerService;
16 |
17 | @RequestMapping(value = "/customers/{customerId}", method = RequestMethod.GET)
18 | public Customer getCustomer(@PathVariable String customerId) {
19 | // return new CustomerService().getCustomer(customerId);
20 | return customerService.getCustomerThroughDao(customerId);
21 | }
22 |
23 | public void setCustomerService(CustomerService customerService) {
24 | this.customerService = customerService;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/demo/SemaphoreEchoCommand.java:
--------------------------------------------------------------------------------
1 | package demo;
2 |
3 | import com.netflix.hystrix.HystrixCommand;
4 | import com.netflix.hystrix.HystrixCommandGroupKey;
5 | import com.netflix.hystrix.HystrixCommandKey;
6 | import com.netflix.hystrix.HystrixCommandProperties;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | public class SemaphoreEchoCommand extends HystrixCommand {
11 | private Logger logger = LoggerFactory.getLogger(ThreadEchoCommand.class);
12 |
13 | private String input;
14 |
15 | protected SemaphoreEchoCommand(String input) {
16 | super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("Semaphore Echo"))
17 | .andCommandKey(HystrixCommandKey.Factory.asKey("Echo"))
18 | .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
19 | .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
20 | .withExecutionIsolationSemaphoreMaxConcurrentRequests(2)));
21 | this.input = input;
22 | }
23 |
24 | @Override
25 | protected String run() throws Exception {
26 | logger.info("Run command with input: {}", input);
27 | Thread.currentThread().sleep(100);
28 | return "Echo: " + input;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/dao/ContactHystrixCommand.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.dao;
2 |
3 | import com.netflix.hystrix.HystrixCommand;
4 | import com.netflix.hystrix.HystrixCommandGroupKey;
5 | import com.xianlinbox.hystrix.model.Contact;
6 | import org.apache.http.client.fluent.Request;
7 | import org.codehaus.jackson.map.ObjectMapper;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | public class ContactHystrixCommand extends HystrixCommand {
12 | private Logger logger = LoggerFactory.getLogger(ContactHystrixCommand.class);
13 | private String customerId;
14 |
15 | public ContactHystrixCommand(String customerId) {
16 | super(HystrixCommandGroupKey.Factory.asKey("Contact"));
17 | this.customerId = customerId;
18 | }
19 |
20 | @Override
21 | public Contact run() throws Exception {
22 | logger.info("Get contact for customer {}", customerId);
23 | String response = Request.Get("http://localhost:9090/customer/" + customerId + "/contact")
24 | .connectTimeout(1000)
25 | .socketTimeout(1000)
26 | .execute()
27 | .returnContent()
28 | .asString();
29 |
30 | return new ObjectMapper().readValue(response, Contact.class);
31 | }
32 |
33 | @Override
34 | protected Contact getFallback() {
35 | logger.info("Met error, using fallback value: {}", customerId);
36 | return null;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/dao/AddressHystrixCommand.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.dao;
2 |
3 | import com.netflix.hystrix.HystrixCommand;
4 | import com.netflix.hystrix.HystrixCommandGroupKey;
5 | import com.xianlinbox.hystrix.model.Address;
6 | import org.apache.http.client.fluent.Request;
7 | import org.codehaus.jackson.map.ObjectMapper;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | public class AddressHystrixCommand extends HystrixCommand {
12 | private Logger logger = LoggerFactory.getLogger(AddressHystrixCommand.class);
13 | private String customerId;
14 |
15 | public AddressHystrixCommand(String customerId) {
16 | super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("Address")));
17 | this.customerId = customerId;
18 | }
19 |
20 | @Override
21 | public Address run() throws Exception {
22 | logger.info("Get address for customer {}", customerId);
23 | String response = Request.Get("http://localhost:9090/customer/" + customerId + "/address")
24 | .connectTimeout(1000)
25 | .socketTimeout(1000)
26 | .execute()
27 | .returnContent()
28 | .asString();
29 |
30 | return new ObjectMapper().readValue(response, Address.class);
31 | }
32 |
33 | @Override
34 | protected Address getFallback() {
35 | logger.info("Met error, using fallback value: {}", customerId);
36 | return null;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/xianlinbox/hystrix/dao/HystrixCommandAdvice.java:
--------------------------------------------------------------------------------
1 | package com.xianlinbox.hystrix.dao;
2 |
3 | import com.netflix.hystrix.HystrixCommand;
4 | import com.netflix.hystrix.HystrixCommandGroupKey;
5 | import com.netflix.hystrix.HystrixCommandKey;
6 | import org.aspectj.lang.ProceedingJoinPoint;
7 |
8 | public class HystrixCommandAdvice {
9 | private String groupName;
10 | private String commandName;
11 |
12 | public Object runCommand(final ProceedingJoinPoint pjp) {
13 | return wrapWithHystrixCommnad(pjp).execute();
14 | }
15 |
16 | private HystrixCommand