2. MILAN 18/19.11.2015 - GIULIO SANTOLI
RECOMMENDATIONS
SERVICE (9002)
MEMBERSHIP
SERVICE (9001)
Scenario 1: Naive Implementation
3. MILAN 18/19.11.2015 - GIULIO SANTOLI
1. Go to the Spring Initializer site (https://start.spring.io)
2. Select Gradle Project with Spring Boot 1.2.7
3. Specify in Project Metadata:
Group: com.microservices
Artifact: membership
4. Add the following starters: Web, Eureka Discovery, Hystrix, Actuator
5. Generate the Project (membership.zip) and extract it.
6. Open the file build.gradle with your Java editor (IntelliJ)
Membership Service
4. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class MembershipApplication {
public static void main(String[] args) {
SpringApplication.run(MembershipApplication.class, args);
}
@RequestMapping("/")
public String home() {
return "Hello world";
}
}
MembershipApplication.java
Add this
method
5. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:membership> gradlew bootRun
. ____ _ __ _ _
/ / ___'_ __ _ _(_)_ __ __ _
( ( )___ | '_ | '_| | '_ / _` |
/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |___, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.2.7.RELEASE)
2015-11-12 13:41:17.084 INFO 5452 --- [ main] com.microservices.MembershipApplication : Starting MembershipApplication on win81
with PID 5452 (C:Bluemixworkshopmembershipbuildclassesmain started by Giulio in C:Bluemixworkshopmembership)
2015-11-12 13:41:17.212 INFO 5452 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.cont
ext.embedded.AnnotationConfigEmbeddedWebApplicationContext@12f41634: startup date [Thu Nov 12 13:41:17 CET 2015]; root of con text hierarchy
2015-11-12 13:41:18.661 INFO 5452 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'bea
nNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireC
andidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$Whitelabel ErrorViewConfig
uration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path res ource [org/spri
ngframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=;
abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org .springframewo
rk.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; ini tMethodName=nul
l; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfigu ration$WebMvcAu
toConfigurationAdapter.class]]
2015-11-12 13:41:20.332 INFO 5452 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (h
ttp)
2015-11-12 13:41:20.896 INFO 5452 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat
2015-11-12 13:41:20.907 INFO 5452 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8
.0.28
2015-11-12 13:41:21.433 INFO 5452 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicat
ionContext
2015-11-12 13:41:21.435 INFO 5452 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initializati
on completed in 4229 ms
2015-11-12 13:41:23.400 INFO 5452 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to
[/]
2015-11-12 13:41:23.427 INFO 5452 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter
' to: [/*]
2015-11-12 13:41:23.428 INFO 5452 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter'
to: [/*]
2015-11-12 13:41:24.132 INFO 5452 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.sprin
gframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@12f41634: startup date [Thu Nov 12 13:41:17 CE T 2015]; root o
f context hierarchy
2015-11-12 13:41:24.284 INFO 5452 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.Str
ing com.microservices.MembershipApplication.home()
7. MILAN 18/19.11.2015 - GIULIO SANTOLI
buildscript {
...
}
...
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-eureka')
compile('org.springframework.cloud:spring-cloud-starter-hystrix')
compile('org.springframework.boot:spring-boot-starter-web')
compile('com.google.guava:guava:12.0')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
...
build.gradle
Add this
line
8. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
@RestController
@RequestMapping("/api/member")
class MembershipController {
final private Random rand = new Random();
final private Map<String, Member> memberStore = ImmutableMap.of(
"Alfa", new Member("Alfa", 10), "Beta", new Member("Beta", 30));
@RequestMapping(method = RequestMethod.POST)
public Member register(@RequestBody Member member) {
memberStore.put(member.getUser(), member);
return member;
}
@RequestMapping("/{user}")
Member login(@PathVariable String user) {
delay();
return memberStore.get(user);
}
private void delay() {
try { Thread.sleep((int)((Math.abs(2 + rand.nextGaussian()*15))*100)); }
catch (InterruptedException e) { throw new RuntimeException(e); }
}
}
MembershipApplication.java
Add this
class in
the file
9. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
class Member {
private String user;
private Integer age;
public Member() {}
public Member(String name, Integer age) { this.user = name; this.age = age; }
public final String getUser() { return user; }
public final void setUser(String name) { this.user = name; }
public final Integer getAge() { return age; }
public final void setAge(Integer age) { this.age = age;}
}
MembershipApplication.java
Add this
class in
the file
server:
port: ${PORT:9001}
application.yml
Create this
file in
"resources"
11. MILAN 18/19.11.2015 - GIULIO SANTOLI
1. Go to the Spring Initializer site (https://start.spring.io)
2. Select Gradle Project with Spring Boot 1.2.7
3. Specify in Project Metadata:
Group: com.microservices
Artifact: recommendations
4. Add the following starters: Web, Hystrix, Eureka Discovery, Actuator
5. Generate the Project (recommendations.zip) and extract it.
6. Open the file build.gradle with your Java editor (IntelliJ)
Recommendations Service
12. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RecommendationsApplication {
public static void main(String[] args) {
SpringApplication.run(RecommendationsApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
RecommendationsApplication.java
Add this
method
13. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
class Member {
private String user;
private Integer age;
public Member() {}
public Member(String name, Integer age) { this.user = name; this.age = age; }
public final String getUser() { return user; }
public final void setUser(String name) { this.user = name; }
public final Integer getAge() { return age; }
public final void setAge(Integer age) { this.age = age;}
}
class Movie {
public String title;
public Movie() {}
public Movie(String title) { this.title = title; }
public final String getTitle() { return this.title; }
public void setTitle(String title) { this.title = title; }
}
class UserNotFoundException extends Exception {
private static final long serialVersionUID = 7806250577893330972L;}
RecommendationsApplication.java
Add these
classes in
the file
14. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
@RestController
@RequestMapping("/api/recommendations")
class RecommendationController {
@Autowired
RestTemplate restTemplate;
Set<Movie> kidRecommendations = Sets.newHashSet(new Movie("Big Hero 6"), new Movie("Frozen"));
Set<Movie> adultRecommendations = Sets.newHashSet(new Movie("The Martian"),
new Movie("The Hobbit"));
@RequestMapping("/{user}")
public Set<Movie> findRecommendationsForUser(@PathVariable String user) throws
UserNotFoundException {
Member member = restTemplate.getForObject("http://localhost:9001/api/member/{user}",
Member.class, user);
if(member == null) throw new UserNotFoundException();
return member.getAge() < 17 ? kidRecommendations : adultRecommendations;
}
}
RecommendationsApplication.java
Add this
class in
the file
15. MILAN 18/19.11.2015 - GIULIO SANTOLI
server:
port: ${PORT:9002}
application.yml
Create this
file in
"resources"
17. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: localhost
Server Port: 9001
Document Path: /api/member/Alfa
Document Length: 24 bytes
Concurrency Level: 100
Time taken for tests: 14.427 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 172000 bytes
HTML transferred: 24000 bytes
Requests per second: 69.31 [#/sec] (mean)
Time per request: 1442.710 [ms] (mean)
Time per request: 14.427 [ms] (mean, across all concurrent requests)
Transfer rate: 11.64 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.9 0 25
Processing: 13 1226 884.6 1038 4835
Waiting: 11 1225 884.8 1037 4834
Total: 13 1226 884.6 1038 4835
Percentage of the requests served within a certain time (ms)
50% 1038
66% 1500
75% 1768
80% 1934
90% 2515
95% 2930
98% 3453
99% 3814
100% 4835 (longest request)
C:> ab -c 100 -n 1000 http://localhost:9001/api/member/Alfa
18. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: localhost
Server Port: 9002
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 100
Time taken for tests: 19.096 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 230000 bytes
HTML transferred: 43000 bytes
Requests per second: 52.37 [#/sec] (mean)
Time per request: 1909.590 [ms] (mean)
Time per request: 19.096 [ms] (mean, across all concurrent requests)
Transfer rate: 11.76 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.1 0 25
Processing: 23 1623 1012.4 1422 5302
Waiting: 23 1619 1013.9 1421 5302
Total: 23 1624 1012.4 1423 5302
Percentage of the requests served within a certain time (ms)
50% 1423
66% 1878
75% 2194
80% 2402
90% 3033
95% 3627
98% 4234
99% 4815
100% 5302 (longest request)
C:> ab -c 100 -n 1000 http://localhost:9002/api/recommendations/Alfa
19. MILAN 18/19.11.2015 - GIULIO SANTOLI
RECOMMENDATIONS
SERVICE (9002)
MEMBERSHIP
SERVICE (9001)
Scenario 2: Service Discovery
EUREKA
SERVER
(DISCOVERY)
EUREKA
SERVER
(9000)
EUREKA
CLIENT
EUREKA
CLIENT
20. MILAN 18/19.11.2015 - GIULIO SANTOLI
1. Go to the Spring Initializer site (https://start.spring.io)
2. Select Gradle Project with Spring Boot 1.2.7
3. Specify in Project Metadata:
Group: com.microservices
Artifact: eurekaserver
4. Add the following starters: Eureka Server
5. Generate the Project (eurekaserver.zip) and extract it.
6. Open the file build.gradle with your Java editor (IntelliJ)
Netflix Eureka Service
21. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaserverApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaserverApplication.class, args);
}
}
EurekaserverApplication.java
Add this
annotation
22. MILAN 18/19.11.2015 - GIULIO SANTOLI
server:
port: ${PORT:9000}
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
application.yml
Create this
file in
"resources"
27. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import ...
@EnableEurekaClient
public class RecommendationsApplication {
public static void main(String[] args) { ... }
/* @Bean
public RestTemplate restTemplate() { return new RestTemplate();}
*/
}
class RecommendationController {
...
@RequestMapping("/{user}")
public Set<Movie> findRecommendationsForUser(@PathVariable String user) {
Member member = restTemplate.getForObject("http://membership/api/member/{user}",
Member.class, user);
...
}
}
RecommendationsApplication.java
Remove
this method
Add this
annotation
Replace the
hostname
30. MILAN 18/19.11.2015 - GIULIO SANTOLI
MEMBERSHIP
SERVICE (9001)
RECOMMENDATIONS
SERVICE (9002)
MEMBERSHIP
SERVICE (9003)
Scenario 3: Load Balancing
EUREKA
SERVER
(DISCOVERY)
EUREKA
SERVER
(9000)
EUREKA
CLIENT
EUREKA
CLIENT
RIBBON
32. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: localhost
Server Port: 9002
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 100
Time taken for tests: 19.096 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 230000 bytes
HTML transferred: 43000 bytes
Requests per second: 52.37 [#/sec] (mean)
Time per request: 1909.590 [ms] (mean)
Time per request: 19.096 [ms] (mean, across all concurrent requests)
Transfer rate: 11.76 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.1 0 25
Processing: 23 1623 1012.4 1422 5302
Waiting: 23 1619 1013.9 1421 5302
Total: 23 1624 1012.4 1423 5302
Percentage of the requests served within a certain time (ms)
50% 1423
66% 1878
75% 2194
80% 2402
90% 3033
95% 3627
98% 4234
99% 4815
100% 5302 (longest request)
C:> ab -c 100 -n 1000 http://localhost:9002/api/recommendations/Alfa
33. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: localhost
Server Port: 9002
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 100
Time taken for tests: 16.302 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 236000 bytes
HTML transferred: 43000 bytes
Requests per second: 61.34 [#/sec] (mean)
Time per request: 1630.229 [ms] (mean)
Time per request: 16.302 [ms] (mean, across all concurrent requests)
Transfer rate: 14.14 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.5 0 3
Processing: 28 1380 909.4 1227 4661
Waiting: 26 1379 909.7 1225 4661
Total: 29 1381 909.4 1227 4661
Percentage of the requests served within a certain time (ms)
50% 1227
66% 1617
75% 1917
80% 2138
90% 2740
95% 3078
98% 3700
99% 3967
100% 4661 (longest request)
C:> ab -c 100 -n 1000 http://localhost:9002/api/recommendations/Alfa
34. MILAN 18/19.11.2015 - GIULIO SANTOLI
Scenario 4: Circuit Breaker
MEMBERSHIP
SERVICE (9001)
RECOMMENDATIONS
SERVICE (9002)
EUREKA
SERVER
(DISCOVERY)
EUREKA
SERVER
(9000)
EUREKA
CLIENT
EUREKA
CLIENT
RIBBON +
HYSTRIX
35. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
class RecommendationController {
...
Set<Movie> familyRecommendations = Sets.newHashSet(new Movie("Iron Man"),
new Movie("Spiderman"));
@RequestMapping("/{user}")
@HystrixCommand(fallbackMethod = "recommendationsFallback“,
ignoreExceptions = UserNotFoundException.class,
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "5000")})
public Set<Movie> findRecommendationsForUser(@PathVariable String user)
throws UserNotFoundException {
}
public Set<Movie> recommendationsFallback(String user) {
return familyRecommendations;
}
}
...
RecommendationsApplication.java
Add this
Set
Add this
annotation
Add this
method
37. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: localhost
Server Port: 9002
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 100
Time taken for tests: 19.096 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 230000 bytes
HTML transferred: 43000 bytes
Requests per second: 52.37 [#/sec] (mean)
Time per request: 1909.590 [ms] (mean)
Time per request: 19.096 [ms] (mean, across all concurrent requests)
Transfer rate: 11.76 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.1 0 25
Processing: 23 1623 1012.4 1422 5302
Waiting: 23 1619 1013.9 1421 5302
Total: 23 1624 1012.4 1423 5302
Percentage of the requests served within a certain time (ms)
50% 1423
66% 1878
75% 2194
80% 2402
90% 3033
95% 3627
98% 4234
99% 4815
100% 5302 (longest request)
C:> ab -c 100 -n 1000 http://localhost:9002/api/recommendations/Alfa
38. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: localhost
Server Port: 9002
Document Path: /api/recommendations/Alfa
Document Length: 44 bytes
Concurrency Level: 100
Time taken for tests: 8.962 seconds
Complete requests: 3000
Failed requests: 52(Connect: 0, Receive: 0, Length: 52, Exceptions: 0)
Total transferred: 710948 bytes
HTML transferred: 131948 bytes
Requests per second: 334.73 [#/sec] (mean)
Time per request: 298.749 [ms] (mean)
Time per request: 2.987 [ms] (mean, across all concurrent requests)
Transfer rate: 77.47 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 3.1 0 111
Processing: 1 245 314.7 167 3295
Waiting: 1 165 251.0 132 3283
Total: 1 246 314.8 168 3297
Percentage of the requests served within a certain time (ms)
50% 168
66% 258
75% 297
80% 330
90% 378
95% 690
98% 1359
99% 1634
100% 3297 (longest request)
C:> ab -c 100 -n 3000 http://localhost:9002/api/recommendations/Alfa
39. MILAN 18/19.11.2015 - GIULIO SANTOLI
Scenario 5: Hystrix Dashboard
MEMBERSHIP
SERVICE (9001)
RECOMMENDATIONS
SERVICE (9002)EUREKA
SERVER
(DISCOVERY)
EUREKA
SERVER
(9000)
EUREKA
CLIENT
EUREKA
CLIENT
RIBBON +
HYSTRIX
HYSTRIX
DASHBOARD
(8888)
40. MILAN 18/19.11.2015 - GIULIO SANTOLI
1. Go to the Spring Initializer site (https://start.spring.io)
2. Select Gradle Project with Spring Boot 1.2.7
3. Specify in Project Metadata:
Group: com.microservices
Artifact: hystrixdashboard
4. Add the following starters: Hystrix Dashboard
5. Generate the Project (hystrixdashboard.zip) and extract it.
6. Open the file build.gradle with your Java editor (IntelliJ)
Netflix Hystrix Dashboard
41. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixdashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixdashboardApplication.class, args);
}
}
HystrixdashboardApplication.java
Add this
annotation
server.port: ${PORT:8888}
spring.application.name: hystrix-dash
security.basic.enabled: false
application.yml
Create this
file in
"resources"
42. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:hystrixdashboard> gradlew bootRun
OPEN THE BROWSER AT: http://localhost:8888/hystrix
INSERT THE FOLLOWING LINK: http://localhost:9002/hystrix.stream
43. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:> ab -c 100 -n 1000 http://localhost:9002/api/recommendations/Alfa
44. MILAN 18/19.11.2015 - GIULIO SANTOLI
Scenario 6: Edge Server and Data Aggregation
MEMBERSHIP
SERVICE (9001)
RECOMMENDATIONS
SERVICE (9002)EUREKA
SERVER
(DISCOVERY)
EUREKA
SERVER
(9000)
EUREKA
CLIENT
EUREKA
CLIENT
RIBBON +
HYSTRIX
HYSTRIX
DASHBOARD
(8888)
ZUUL EDGE SERVER
(7777)
EUREKA
CLIENT
RIBBON +
HYSTRIX
TURBINE
AGGREGATION
(9999)
45. MILAN 18/19.11.2015 - GIULIO SANTOLI
1. Go to the Spring Initializer site (https://start.spring.io)
2. Select Gradle Project with Spring Boot 1.2.7
3. Specify in Project Metadata:
Group: com.microservices
Artifact: zuul
4. Add the following starters: Eureka Discovery, Hystrix, Ribbon, Zuul,
Actuator
5. Generate the Project (zuul.zip) and extract it.
6. Open the file build.gradle with your Java editor (IntelliJ)
Netflix Edge Server
46. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
ZuulApplication.java
Add this
annotation
49. MILAN 18/19.11.2015 - GIULIO SANTOLI
1. Go to the Spring Initializer site (https://start.spring.io)
2. Select Gradle Project with Spring Boot 1.2.7
3. Specify in Project Metadata:
Group: com.microservices
Artifact: turbine
4. Add the following starters: Eureka Discovery, Hystrix, Ribbon, Turbine,
Actuator
5. Generate the Project (turbine.zip) and extract it.
6. Open the file build.gradle with your Java editor (IntelliJ)
Netflix Monitoring Aggregation
50. MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
@SpringBootApplication
@EnableTurbine
public class TurbineApplication {
public static void main(String[] args) {
SpringApplication.run(TurbineApplication.class, args);
}
}
TurbineApplication.java
Add this
annotation
52. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:turbine> gradlew bootRun
OPEN THE BROWSER AT: http://localhost:8888/hystrix
INSERT THE FOLLOWING LINKS:
http://localhost:7777/hystrix.stream
http://localhost:9999/turbine.stream?cluster=EDGESERVER
http://localhost:9999/turbine.stream?cluster=RECOMMENDATIONS
55. MILAN 18/19.11.2015 - GIULIO SANTOLI
server:
port: ${PORT:9000}
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
---
# Eureka instance when used on Docker
spring:
profiles: docker
eureka:
instance:
hostname: eurekasrv
application.yml
Modify the file
for eureka
56. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:eurekaserver> gradlew bootRepackage
C:eurekaserver> java -jar buildlibseurekaserver-0.0.1-SNAPSHOT.jar
FROM java:8
VOLUME /tmp
ENV SPRING_PROFILES_ACTIVE docker
COPY build/libs/eurekaserver-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
EXPOSE 9000
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile
Create this file in
"eurekaserver"
57. MILAN 18/19.11.2015 - GIULIO SANTOLI
eureka:
build: eurekaserver
restart: always
ports:
- "5000:9000"
docker-compose.yml
Create this file
In the main directory
58. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:> docker-compose build
C:> docker-compose up -d eureka
C:> docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------------------
workshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcp
C:> docker-compose logs eureka
C:> docker-machine env –shell cmd docker
192.168.99.100
OPEN THE BROWSER AT: http://192.168.99.100:5000/
71. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:hystrixdashboard> gradlew bootRepackage
C:hystrixdashboard> java -jar buildlibshystrixdashboard-0.0.1-SNAPSHOT.jar
FROM java:8
VOLUME /tmp
COPY build/libs/hystrixdashboard-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
EXPOSE 8888
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile
Create this file in
hystrixdashboard
72. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
hystrix:
build: hystrixdashboard
restart: always
ports:
- “5555:8888"
docker-compose.yml
Add the following
statements
73. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:> docker-compose build hystrix
C:> docker-compose up -d hystrix
C:> docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------------------------
workshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcp
workshop_hystrix_1 java -Djava.security.egd=f ... Up 0.0.0.0:5555->8888/tcp
workshop_membership_1 java -Djava.security.egd=f ... Up 0.0.0.0:5001->9001/tcp
workshop_recommendations_1 java -Djava.security.egd=f ... Up 0.0.0.0:5002->9002/tcp
C:> curl http://192.168.99.100:5002/api/recommendations/Alfa
C:> curl http://192.168.99.100:5002/api/recommendations/Beta
74. MILAN 18/19.11.2015 - GIULIO SANTOLI
OPEN THE BROWSER AT: http://192.168.99.100:5555/hystrix
INSERT THE FOLLOWING LINK: http://172.17.0.5:9002/hystrix.stream
75. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:> ab -c 100 -n 3000 http://192.168.99.100:5002/api/recommendations/Alfa
79. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: 192.168.99.100
Server Port: 5002
Document Path: /api/recommendations/Alfa
Document Length: 44 bytes
Concurrency Level: 50
Time taken for tests: 11.212 seconds
Complete requests: 1000
Failed requests: 72 (Connect: 0, Receive: 0, Length: 72, Exceptions: 0)
Total transferred: 243928 bytes
HTML transferred: 43928 bytes
Requests per second: 89.19 [#/sec] (mean)
Time per request: 560.624 [ms] (mean)
Time per request: 11.212 [ms] (mean, across all concurrent requests)
Transfer rate: 21.25 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 1.5 2 16
Processing: 7 455 461.0 383 5505
Waiting: 5 319 446.5 221 5290
Total: 9 458 461.0 385 5507
Percentage of the requests served within a certain time (ms)
50% 385
66% 459
75% 517
80% 567
90% 689
95% 1061
98% 2141
99% 2915
100% 5507 (longest request)
C:> ab -c 50 -n 1000 http://localhost:9002/api/recommendations/Alfa
80. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: 192.168.99.100
Server Port: 5002
Document Path: /api/recommendations/Alfa
Document Length: 44 bytes
Concurrency Level: 50
Time taken for tests: 14.943 seconds
Complete requests: 1000
Failed requests: 93 (Connect: 0, Receive: 0, Length: 93, Exceptions: 0)
Total transferred: 243907 bytes
HTML transferred: 43907 bytes
Requests per second: 66.92 [#/sec] (mean)
Time per request: 747.134 [ms] (mean)
Time per request: 14.943 [ms] (mean, across all concurrent requests)
Transfer rate: 15.94 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 2.0 2 24
Processing: 15 611 536.9 483 4565
Waiting: 14 432 514.3 288 4558
Total: 16 614 537.0 484 4568
Percentage of the requests served within a certain time (ms)
50% 484
66% 614
75% 709
80% 787
90% 1068
95% 1456
98% 2590
99% 3025
100% 4568 (longest request)
C:> ab -c 50 -n 1000 http://localhost:9002/api/recommendations/Alfa
91. MILAN 18/19.11.2015 - GIULIO SANTOLI
---
applications:
- name: giulio-eureka
memory: 256M
instances: 1
path: build/libs/eurekaserver-0.0.1-SNAPSHOT.jar
env:
JAVA_OPTS: "-Djava.security.egd=file:/dev/./urandom"
manifest.yml
Create this file
for eureka
Use a unique
Name!
C:eurekaserver> gradlew bootRepackage
C:eurekaserver> java -jar buildlibseurekaserver-0.0.1-SNAPSHOT.jar
C:eurekaserver> cf push
92. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:eurekaserver> cf apps
Getting apps in org giulio_santoli@it.ibm.com / space demo as giulio_santoli@it.ibm.com...
OK
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
93. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:> cf cups giulio-eureka-service -p "{"uri": "http://giulio-eureka.mybluemix.net/eureka/"}«
C:> cf services
Getting services in org giulio_santoli@it.ibm.com / space demo as giulio_santoli@it.ibm.com...
OK
name service plan bound apps last operation
giulio-eureka-service user-provided
Define a
custom service
98. MILAN 18/19.11.2015 - GIULIO SANTOLI
---
applications:
- name: giulio-recommendations
memory: 256M
instances: 1
path: build/libs/recommendations-0.0.1-SNAPSHOT.jar
env:
JAVA_OPTS: "-Djava.security.egd=file:/dev/./urandom"
services:
- giulio-eureka-service
manifest.yml
Create this file in
recommendations
Use a unique
Name!
C:recommendations> gradlew bootRepackage
C:recommendations> java -jar buildlibsrecommendations-0.0.1-SNAPSHOT.jar
C:recommendations> cf push
99. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:recommendations> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-membership started 1/1 256M 1G giulio-membership.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
C:recommendations> crul http://giulio-recommendations.mybluemix.net/api/recommendations/Alfa
100. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:recommendations> cf scale giulio-membership -i 2
C:recommendations> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-membership started 2/2 256M 1G giulio-membership.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
101. MILAN 18/19.11.2015 - GIULIO SANTOLI
---
applications:
- name: giulio-hystrix
memory: 256M
instances: 1
path: build/libs/hystrixdashboard-0.0.1-SNAPSHOT.jar
env:
JAVA_OPTS: "-Djava.security.egd=file:/dev/./urandom"
manifest.yml
Create this file in
hystrixdashboard
Use a unique
Name!
C:hystrixdashboard> cf push
102. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:hystrixdashboard> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.net
giulio-membership started 2/2 256M 1G giulio-membership.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
OPEN BROWSER AT: http://giulio-hystrix.mybluemix.net/hystrix
INSERT: http://giulio-recommendations.mybluemix.net:80/hystrix.stream
103. MILAN 18/19.11.2015 - GIULIO SANTOLI
MEMBERSHIP
(80)
Scenario 11: Canary Deployment in Cloud Foundry
RECOMMENDATIONS
(80)
MEMBERSHIP 1
(80)
EUREKA
(80)
EUREKA
SERVICE
MEMBERSHIP
(80)
MEMBERSHIP 2
(80)
104. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:membership> cf stop giulio-hystrix
C:membership> cf scale giulio-membership -i 3
C:membership> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-hystrix stopped 0/1 256M 1G giulio-hystrix.mybluemix.net
giulio-membership started 3/3 256M 1G giulio-membership.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
105. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: giulio-recommendations.mybluemix.net
Server Port: 80
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 30
Time taken for tests: 40.687 seconds
Complete requests: 200
Failed requests: 5 (Connect: 0, Receive: 0, Length: 5, Exceptions: 0)
Total transferred: 81594 bytes
HTML transferred: 8605 bytes
Requests per second: 4.92 [#/sec] (mean)
Time per request: 6103.125 [ms] (mean)
Time per request: 203.437 [ms] (mean, across all concurrent requests)
Transfer rate: 1.96 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 146 180 355.7 152 5183
Processing: 610 4436 1435.4 4448 9753
Waiting: 462 3066 1790.0 2799 9729
Total: 769 4616 1483.3 4599 9907
Percentage of the requests served within a certain time (ms)
50% 4599
66% 4646
75% 4654
80% 4675
90% 5210
95% 9642
98% 9890
99% 9901
100% 9907 (longest request)
C:> ab -c 30 -n 200 http://giulio-recommendations.mybluemix.net/api/recommendations/Alfa
106. MILAN 18/19.11.2015 - GIULIO SANTOLI
...
@RestController
@RequestMapping("/api/member")
class MembershipController {
…
@RequestMapping(method = RequestMethod.POST)
public Member register(@RequestBody Member member) { … }
@RequestMapping("/{user}")
Member login(@PathVariable String user) {
// delay();
return memberStore.get(user);
}
private void delay() { … }
}
...
MembershipApplication.java
Comment
this line
107. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:membership> gradlew bootRepackage
C:membership> cf scale giulio-membership -i 2
C:membership> cf push giulio-membershipv2
C:membership> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.net
giulio-membership started 2/2 256M 1G giulio-membership.mybluemix.net
giulio-membershipv2 started 1/1 256M 1G giulio-membershipv2.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
108. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: giulio-recommendations.mybluemix.net
Server Port: 80
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 30
Time taken for tests: 33.151 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 81589 bytes
HTML transferred: 8600 bytes
Requests per second: 6.03 [#/sec] (mean)
Time per request: 4972.644 [ms] (mean)
Time per request: 165.755 [ms] (mean, across all concurrent requests)
Transfer rate: 2.40 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 146 155 8.8 153 202
Processing: 178 4210 960.7 4502 6497
Waiting: 178 2735 1348.5 2768 6496
Total: 327 4365 959.7 4657 6649
Percentage of the requests served within a certain time (ms)
50% 4657
66% 4685
75% 4710
80% 4729
90% 4953
95% 5363
98% 5891
99% 6332
100% 6649 (longest request)
C:> ab -c 30 -n 200 http://giulio-recommendations.mybluemix.net/api/recommendations/Alfa
109. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:membership> cf scale giulio-membership -i 1
C:membership> cf scale giulio-membershipv2 -i 2
C:membership> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.net
giulio-membership started 1/1 256M 1G giulio-membership.mybluemix.net
giulio-membershipv2 started 2/2 256M 1G giulio-membershipv2.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
110. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: giulio-recommendations.mybluemix.net
Server Port: 80
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 30
Time taken for tests: 34.895 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 81590 bytes
HTML transferred: 8600 bytes
Requests per second: 5.73 [#/sec] (mean)
Time per request: 5234.177 [ms] (mean)
Time per request: 174.473 [ms] (mean, across all concurrent requests)
Transfer rate: 2.28 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 146 161 18.2 154 229
Processing: 178 4339 1066.0 4487 6084
Waiting: 176 2768 1427.3 2780 6083
Total: 335 4500 1071.1 4646 6308
Percentage of the requests served within a certain time (ms)
50% 4646
66% 4798
75% 4831
80% 4968
90% 5708
95% 5795
98% 5868
99% 6189
100% 6308 (longest request)
C:> ab -c 30 -n 200 http://giulio-recommendations.mybluemix.net/api/recommendations/Alfa
111. MILAN 18/19.11.2015 - GIULIO SANTOLI
C:membership> cf stop giulio-membership
C:membership> cf scale giulio-membershipv2 -i 3
C:membership> cf apps
name requested state instances memory disk urls
giulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
giulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.net
giulio-membership started 0/1 256M 1G giulio-membership.mybluemix.net
giulio-membershipv2 started 3/3 256M 1G giulio-membershipv2.mybluemix.net
giulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
112. MILAN 18/19.11.2015 - GIULIO SANTOLI
Server Hostname: giulio-recommendations.mybluemix.net
Server Port: 80
Document Path: /api/recommendations/Alfa
Document Length: 43 bytes
Concurrency Level: 30
Time taken for tests: 30.898 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 81591 bytes
HTML transferred: 8600 bytes
Requests per second: 6.47 [#/sec] (mean)
Time per request: 4634.710 [ms] (mean)
Time per request: 154.490 [ms] (mean, across all concurrent requests)
Transfer rate: 2.58 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 147 153 4.9 151 188
Processing: 215 4122 941.2 4449 4585
Waiting: 211 2344 1262.3 2324 4583
Total: 364 4274 941.1 4601 4738
Percentage of the requests served within a certain time (ms)
50% 4601
66% 4613
75% 4624
80% 4634
90% 4658
95% 4664
98% 4676
99% 4732
100% 4738 (longest request)
C:> ab -c 30 -n 200 http://giulio-recommendations.mybluemix.net/api/recommendations/Alfa