diff --git a/hystrix-examples-webapp/build.gradle b/hystrix-examples-webapp/build.gradle new file mode 100644 index 000000000..f2996bc70 --- /dev/null +++ b/hystrix-examples-webapp/build.gradle @@ -0,0 +1,10 @@ +apply plugin: 'java' +apply plugin: 'war' +apply plugin: 'eclipse-wtp' + + dependencies { + compile project(':hystrix-core') + compile project(':hystrix-examples') + compile project(':hystrix-contrib:hystrix-request-servlet') + compile project(':hystrix-contrib:hystrix-metrics-event-stream') + } diff --git a/hystrix-examples-webapp/src/main/webapp/WEB-INF/classes/log4j.properties b/hystrix-examples-webapp/src/main/webapp/WEB-INF/classes/log4j.properties new file mode 100644 index 000000000..91374f670 --- /dev/null +++ b/hystrix-examples-webapp/src/main/webapp/WEB-INF/classes/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootLogger=INFO, FILE +log4j.appender.FILE=org.apache.log4j.ConsoleAppender +log4j.appender.FILE.layout=org.apache.log4j.PatternLayout +log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p %C:%L [%C{1}] [%M]: %m%n + +log4j.appender.FILE.httpclient=ERROR diff --git a/hystrix-examples-webapp/src/main/webapp/WEB-INF/web.xml b/hystrix-examples-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..42a1c74e0 --- /dev/null +++ b/hystrix-examples-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,39 @@ + + + + + HystrixRequestContextServletFilter + HystrixRequestContextServletFilter + com.netflix.hystrix.contrib.requestservlet.HystrixRequestContextServletFilter + + + HystrixRequestContextServletFilter + /* + + + + HystrixRequestLogViaResponseHeaderServletFilter + HystrixRequestLogViaResponseHeaderServletFilter + com.netflix.hystrix.contrib.requestservlet.HystrixRequestLogViaResponseHeaderServletFilter + + + HystrixRequestLogViaResponseHeaderServletFilter + /* + + + + + HystrixMetricsStreamServlet + HystrixMetricsStreamServlet + com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet + + + + HystrixMetricsStreamServlet + /hystrix.stream + + + diff --git a/hystrix-examples-webapp/src/main/webapp/index.jsp b/hystrix-examples-webapp/src/main/webapp/index.jsp new file mode 100644 index 000000000..76efeca67 --- /dev/null +++ b/hystrix-examples-webapp/src/main/webapp/index.jsp @@ -0,0 +1,78 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +HystrixCommandDemo Execution and HystrixRequestLog [hystrix-examples-webapp] + + +
+ +

HystrixCommandDemo Execution and HystrixRequestLog
[hystrix-examples-webapp]

+
+

+ The following is the output of HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString() after simulating the execution of several commands. +

+

+ The simulation code is in com.netflix.hystrix.examples.demo.HystrixCommandDemo. +

+ <%@ page import="com.netflix.hystrix.examples.demo.HystrixCommandDemo, com.netflix.hystrix.HystrixRequestLog" %> + <% + new HystrixCommandDemo().executeSimulatedUserRequestForOrderConfirmationAndCreditCardPayment(); + %> +
+ <%= HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString() %> +
+

+ This request log is also part of the HTTP response header with key name "X-HystrixLog". +

+

+ You can view the realtime stream at ./hystrix.stream. +

+

+ To see the realtime stream change over time execute the following (with correct hostname, port etc) to keep accessing the webapp while watching the stream and you will see the metrics change: +

+
+	while true ; do curl "http://localhost:8080/hystrix-examples-webapp"; done
+	
+

+ The configuration of Hystrix for this functionality is done in web.xml as follows: +

+
+	<filter>
+		<display-name>HystrixRequestContextServletFilter</display-name>
+		<filter-name>HystrixRequestContextServletFilter</filter-name>
+		<filter-class>com.netflix.hystrix.contrib.requestservlet.HystrixRequestContextServletFilter</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>HystrixRequestContextServletFilter</filter-name>
+		<url-pattern>/*</url-pattern>
+	</filter-mapping>
+	
+	<filter>
+		<display-name>HystrixRequestLogViaResponseHeaderServletFilter</display-name>
+		<filter-name>HystrixRequestLogViaResponseHeaderServletFilter</filter-name>
+		<filter-class>com.netflix.hystrix.contrib.requestservlet.HystrixRequestLogViaResponseHeaderServletFilter</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>HystrixRequestLogViaResponseHeaderServletFilter</filter-name>
+		<url-pattern>/*</url-pattern>
+	</filter-mapping>
+
+	<servlet>
+		<description></description>
+		<display-name>HystrixMetricsStreamServlet</display-name>
+		<servlet-name>HystrixMetricsStreamServlet</servlet-name>
+		<servlet-class>com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet</servlet-class>
+	</servlet>
+
+	<servlet-mapping>
+		<servlet-name>HystrixMetricsStreamServlet</servlet-name>
+		<url-pattern>/hystrix.stream</url-pattern>
+	</servlet-mapping>
+
+ +
+ + \ No newline at end of file diff --git a/hystrix-examples/src/main/java/com/netflix/hystrix/examples/demo/HystrixCommandDemo.java b/hystrix-examples/src/main/java/com/netflix/hystrix/examples/demo/HystrixCommandDemo.java index be8be8570..c4a25f7aa 100644 --- a/hystrix-examples/src/main/java/com/netflix/hystrix/examples/demo/HystrixCommandDemo.java +++ b/hystrix-examples/src/main/java/com/netflix/hystrix/examples/demo/HystrixCommandDemo.java @@ -17,6 +17,7 @@ import java.math.BigDecimal; import java.net.HttpCookie; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -35,6 +36,10 @@ public class HystrixCommandDemo { public static void main(String args[]) { + new HystrixCommandDemo().startDemo(); + } + + public HystrixCommandDemo() { /* * Instead of using injected properties we'll set them via Archaius * so the rest of the code behaves as it would in a real system @@ -45,8 +50,6 @@ public static void main(String args[]) { ConfigurationManager.getConfigInstance().setProperty("hystrix.command.GetUserAccountCommand.execution.isolation.thread.timeoutInMilliseconds", 50); // set the rolling percentile more granular so we see data change every second rather than every 10 seconds as is the default ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.metrics.rollingPercentile.numBuckets", 60); - - new HystrixCommandDemo().startDemo(); } /* @@ -59,29 +62,18 @@ public static void main(String args[]) { public void startDemo() { startMetricsMonitor(); while (true) { - executeSimulatedUserRequestForOrderConfirmationAndCreditCardPayment(); + runSimulatedRequestOnThread(); } } - public void executeSimulatedUserRequestForOrderConfirmationAndCreditCardPayment() { + public void runSimulatedRequestOnThread() { pool.execute(new Runnable() { @Override public void run() { HystrixRequestContext context = HystrixRequestContext.initializeContext(); try { - /* fetch user object with http cookies */ - UserAccount user = new GetUserAccountCommand(new HttpCookie("mockKey", "mockValueFromHttpRequest")).execute(); - - /* fetch the payment information (asynchronously) for the user so the credit card payment can proceed */ - Future paymentInformation = new GetPaymentInformationCommand(user).queue(); - - /* fetch the order we're processing for the user */ - int orderIdFromRequestArgument = 13579; - Order previouslySavedOrder = new GetOrderCommand(orderIdFromRequestArgument).execute(); - - CreditCardCommand credit = new CreditCardCommand(previouslySavedOrder, paymentInformation.get(), new BigDecimal(123.45)); - credit.execute(); + executeSimulatedUserRequestForOrderConfirmationAndCreditCardPayment(); System.out.println("Request => " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); } catch (Exception e) { @@ -90,9 +82,25 @@ public void run() { context.shutdown(); } } + }); } + public void executeSimulatedUserRequestForOrderConfirmationAndCreditCardPayment() throws InterruptedException, ExecutionException { + /* fetch user object with http cookies */ + UserAccount user = new GetUserAccountCommand(new HttpCookie("mockKey", "mockValueFromHttpRequest")).execute(); + + /* fetch the payment information (asynchronously) for the user so the credit card payment can proceed */ + Future paymentInformation = new GetPaymentInformationCommand(user).queue(); + + /* fetch the order we're processing for the user */ + int orderIdFromRequestArgument = 13579; + Order previouslySavedOrder = new GetOrderCommand(orderIdFromRequestArgument).execute(); + + CreditCardCommand credit = new CreditCardCommand(previouslySavedOrder, paymentInformation.get(), new BigDecimal(123.45)); + credit.execute(); + } + public void startMetricsMonitor() { Thread t = new Thread(new Runnable() { diff --git a/settings.gradle b/settings.gradle index 3713694bd..ee616b25a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ rootProject.name='hystrix' include 'hystrix-core', \ 'hystrix-examples', \ +'hystrix-examples-webapp', \ 'hystrix-contrib:hystrix-request-servlet', \ 'hystrix-contrib:hystrix-servo-stream', \ 'hystrix-contrib:hystrix-servo-metrics-publisher', \