MILAN 18/19.11.2015 - GIULIO SANTOLI
RECOMMENDATIONS
SERVICE (9002)
MEMBERSHIP
SERVICE (9001)
Scenario 1: Naive Implementation
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
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@RestControllerpublic 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
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:\Bluemix\workshop\membership\build\classes\main started by Giulio in C:\Bluemix\workshop\membership)
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 context 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$WhitelabelErrorViewConfig
uration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [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; initMethodName=nul
l; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$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 CET 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()
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
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
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"
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> gradlew bootRunC:\membership> curl localhost:9001/api/member/AlfaC:\membership> curl localhost:9001/api/member/Beta
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
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;
@SpringBootApplicationpublic class RecommendationsApplication {
public static void main(String[] args) {SpringApplication.run(RecommendationsApplication.class, args);
}
@Beanpublic RestTemplate restTemplate() {
return new RestTemplate();}
}
RecommendationsApplication.java
Add this
method
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
MILAN 18/19.11.2015 - GIULIO SANTOLI
...@RestController@RequestMapping("/api/recommendations")class RecommendationController {
@AutowiredRestTemplate 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
MILAN 18/19.11.2015 - GIULIO SANTOLI
server:port: ${PORT:9002}
application.yml
Create this
file in
"resources"
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\recommendations> gradlew bootRunC:\recommendations> curl http://localhost:9002/api/recommendations/AlfaC:\recommendations> curl http://localhost:9002/api/recommendations/Beta
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
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
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
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
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@EnableEurekaServerpublic class EurekaserverApplication {
public static void main(String[] args) {SpringApplication.run(EurekaserverApplication.class, args);
}}
EurekaserverApplication.java
Add this
annotation
MILAN 18/19.11.2015 - GIULIO SANTOLI
server:port: ${PORT:9000}
eureka:instance:
hostname: localhostclient:
registerWithEureka: falsefetchRegistry: falseserviceUrl:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
application.yml
Create this
file in
"resources"
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\eurekaserver> gradlew bootRunC:\> curl -s -H "Accept: application/json" http://localhost:9000/eureka/apps
MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import …
@SpringBootApplication@RestController@EnableEurekaClientpublic class MembershipApplication { … }
...
MembershipApplication.java
Add this
annotation
MILAN 18/19.11.2015 - GIULIO SANTOLI
server:port: ${PORT:9001}
spring:application.name: membership
security:basic:
enabled: false
eureka:leaseRenewalIntervalInSeconds: 3client:
registryFetchIntervalSeconds: 5instanceInfoReplicationIntervalSeconds: 5initialInstanceInfoReplicationIntervalSeconds: 5serviceUrl:defaultZone: http://localhost:9000/eureka/
instance:metadataMap:instanceId: ${spring.application.name}:${server.port}
application.yml
Add
these
lines
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> gradlew bootRunC:\membership> curl http://localhost:9001/api/member/AlfaC:\> curl -s -H "Accept: application/json" http://localhost:9000/eureka/apps
MILAN 18/19.11.2015 - GIULIO SANTOLI
package com.microservices;
import ...
@EnableEurekaClientpublic class RecommendationsApplication {
public static void main(String[] args) { ... }
/* @Beanpublic 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
MILAN 18/19.11.2015 - GIULIO SANTOLI
server:port: ${PORT:9002}
spring:application.name: recommendations
security:basic:
enabled: false
eureka:leaseRenewalIntervalInSeconds: 3client:
registryFetchIntervalSeconds: 5instanceInfoReplicationIntervalSeconds: 5initialInstanceInfoReplicationIntervalSeconds: 5serviceUrl:defaultZone: http://localhost:9000/eureka/
instance:metadataMap:instanceId: ${spring.application.name}:${server.port}
application.yml
Add
these
lines
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\recommendations> gradlew bootRunC:\recommendations> curl http://localhost:9002/api/recommendations/AlfaC:\> curl -s -H "Accept: application/json" http://localhost:9000/eureka/apps
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
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> set PORT=9003 && gradlew bootRunC:\recommendations> curl http://localhost:9002/api/recommendations/AlfaC:\> curl -s -H "Accept: application/json" http://localhost:9000/eureka/apps
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
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
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
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
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\recommendations> gradlew bootRunC:\recommendations> curl http://localhost:9002/api/recommendations/Alfa[{"title":"Frozen"},{"title":"Big Hero 6"}]
(STOP MEMBERSHIP SERVICE)
C:\recommendations> curl http://localhost:9002/api/recommendations/Alfa[{"title":"Spiderman"},{"title":"Iron Man"}]
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
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
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)
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
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@EnableHystrixDashboardpublic 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-dashsecurity.basic.enabled: false
application.yml
Create this
file in
"resources"
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\hystrixdashboard> gradlew bootRunOPEN THE BROWSER AT: http://localhost:8888/hystrixINSERT THE FOLLOWING LINK: http://localhost:9002/hystrix.stream
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> ab -c 100 -n 1000 http://localhost:9002/api/recommendations/Alfa
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)
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
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@EnableZuulProxypublic class ZuulApplication {
public static void main(String[] args) {SpringApplication.run(ZuulApplication.class, args);
}}
ZuulApplication.java
Add this
annotation
MILAN 18/19.11.2015 - GIULIO SANTOLI
server.port: ${PORT:7777}spring.application.name: edgeserversecurity.basic.enabled: false
eureka:client.serviceUrl.defaultZone: http://localhost:9000/eureka/instance.metadataMap.instanceId: ${spring.application.name}:${server.port}
zuul:ignoredServices: '*'routes:
recommendations:path: /api/recommendations/**stripPrefix: false
membership:path: api/member/**stripPrefix: false
application.yml
Create this
file in
"resources"
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\zuul> curl http://localhost:7777/api/recommendations/AlfaC:\zuul> curl http://localhost:7777/api/recommendations/Beta
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
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@EnableTurbinepublic class TurbineApplication {
public static void main(String[] args) {SpringApplication.run(TurbineApplication.class, args);
}}
TurbineApplication.java
Add this
annotation
MILAN 18/19.11.2015 - GIULIO SANTOLI
server.port: ${PORT:7777}spring.application.name: edgeserversecurity.basic.enabled: false
eureka:client:
serviceUrl:defaultZone: http://localhost:9000/eureka/
zuul:ignoredServices: '*'routes:
recommendations:path: /api/recommendations/**stripPrefix: false
application.yml
Create this
file in
"resources"
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\turbine> gradlew bootRunOPEN THE BROWSER AT: http://localhost:8888/hystrixINSERT THE FOLLOWING LINKS:
http://localhost:7777/hystrix.streamhttp://localhost:9999/turbine.stream?cluster=EDGESERVERhttp://localhost:9999/turbine.stream?cluster=RECOMMENDATIONS
MILAN 18/19.11.2015 - GIULIO SANTOLI
Scenario 7: Running on Docker
RECOMMENDATIONS
(5002:9002)
MEMBERSHIP
(5001:9001)
EUREKA
(5000:9000)
link:eurekasrv
link:eurekasrv
Docker Engine
MILAN 18/19.11.2015 - GIULIO SANTOLI
server:port: ${PORT:9000}
eureka:instance:
hostname: localhostclient:
registerWithEureka: falsefetchRegistry: falseserviceUrl:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
---# Eureka instance when used on Dockerspring:profiles: docker
eureka:instance:
hostname: eurekasrv
application.yml
Modify the file
for eureka
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\eurekaserver> gradlew bootRepackageC:\eurekaserver> java -jar build\libs\eurekaserver-0.0.1-SNAPSHOT.jar
FROM java:8VOLUME /tmpENV SPRING_PROFILES_ACTIVE dockerCOPY build/libs/eurekaserver-0.0.1-SNAPSHOT.jar app.jarRUN bash -c 'touch /app.jar'EXPOSE 9000ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile
Create this file in
"eurekaserver"
MILAN 18/19.11.2015 - GIULIO SANTOLI
eureka:build: eurekaserverrestart: alwaysports:
- "5000:9000"
docker-compose.yml
Create this file
In the main directory
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> docker-compose build
C:\> docker-compose up -d eureka
C:\> docker-compose psName 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 docker192.168.99.100
OPEN THE BROWSER AT: http://192.168.99.100:5000/
MILAN 18/19.11.2015 - GIULIO SANTOLI
...
---spring:profiles: docker
logging.file: /tmp/membership.log
eureka:instance:
preferIpAddress : trueclient:
serviceUrl:defaultZone: http://eurekasrv:9000/eureka/
application.yml
Modify the file
for membership
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> gradlew bootRepackageC:\membership> java -jar build\libs\memberhip-0.0.1-SNAPSHOT.jar
FROM java:8VOLUME /tmpENV SPRING_PROFILES_ACTIVE dockerADD build/libs/membership-0.0.1-SNAPSHOT.jar app.jarRUN bash -c 'touch /app.jar'EXPOSE 9001ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile
Create this file in
memberhip
MILAN 18/19.11.2015 - GIULIO SANTOLI
eureka:build: eurekaserverrestart: alwaysports:
- "5000:9000"
membership:build: membershiprestart: alwayslinks:
- eureka:eurekasrvports:
- "5001:9001"
docker-compose.yml
Add the following
statements
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> docker-compose build membership
C:\> docker-compose up -d memberhip
C:\> docker-compose psName Command State Ports
-------------------------------------------------------------------------------------------------------------------workshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcpworkshop_membership_1 java -Djava.security.egd=f ... Up 0.0.0.0:5001->9001/tcp
C:\> docker-compose logs memberhip
C:\> curl http://192.168.99.100:5001/api/member/Alfa
OPEN THE BROWSER AT: http://192.168.99.100:5000/
MILAN 18/19.11.2015 - GIULIO SANTOLI
...
---spring:profiles: docker
logging.file: /tmp/recommendations.log
eureka:instance:
preferIpAddress : trueclient:
serviceUrl:defaultZone: http://eurekasrv:9000/eureka/
application.yml
Modify the file
for recommendations
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\recommendations> gradlew bootRepackageC:\recommendations> java -jar build\libs\recommendations-0.0.1-SNAPSHOT.jar
FROM java:8VOLUME /tmpENV SPRING_PROFILES_ACTIVE dockerADD build/libs/recommendations-0.0.1-SNAPSHOT.jar app.jarRUN bash -c 'touch /app.jar'EXPOSE 9002ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile
Create this file in
recommendations
MILAN 18/19.11.2015 - GIULIO SANTOLI
eureka:build: eurekaserverrestart: alwaysports:
- "5000:9000"
membership:build: membershiprestart: alwayslinks:
- eureka:eurekasrvports:
- "5001:9001"
recommendations:build: recommendationsrestart: alwaysports:
- "5002:9002"links:
- eureka:eurekasrv
docker-compose.yml
Add the following
statements
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> docker-compose build recommendations
C:\> docker-compose up -d recommendations
C:\> docker-compose psName Command State Ports----------------------------------------------------------------------------------------------------------------------------workshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcpworkshop_membership_1 java -Djava.security.egd=f ... Up 0.0.0.0:5001->9001/tcpworkshop_recommendations_1 java -Djava.security.egd=f ... Up 0.0.0.0:5002->9002/tcp
C:\> docker-compose logs recommendations
C:\> curl http://192.168.99.100:5002/api/recommendations/AlfaC:\> curl http://192.168.99.100:5002/api/recommendations/Beta
OPEN THE BROWSER AT: http://192.168.99.100:5000/
MILAN 18/19.11.2015 - GIULIO SANTOLI
MEMBERSHIP
(5001:9001)
Scenario 8: Hystrix and Load Balancing
RECOMMENDATIONS
(5002:9002)
MEMBERSHIP
(5001:9001)
EUREKA
(5000:9000)
link:eurekasrv
link:eurekasrv
Docker Engine
HYSTRIX
(5555:8888)
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\hystrixdashboard> gradlew bootRepackageC:\hystrixdashboard> java -jar build\libs\hystrixdashboard-0.0.1-SNAPSHOT.jar
FROM java:8VOLUME /tmpCOPY build/libs/hystrixdashboard-0.0.1-SNAPSHOT.jar app.jarRUN bash -c 'touch /app.jar'EXPOSE 8888ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile
Create this file in
hystrixdashboard
MILAN 18/19.11.2015 - GIULIO SANTOLI
...
hystrix:build: hystrixdashboardrestart: alwaysports:
- “5555:8888"
docker-compose.yml
Add the following
statements
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> docker-compose build hystrix
C:\> docker-compose up -d hystrix
C:\> docker-compose psName Command State Ports----------------------------------------------------------------------------------------------------------------------------workshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcpworkshop_hystrix_1 java -Djava.security.egd=f ... Up 0.0.0.0:5555->8888/tcpworkshop_membership_1 java -Djava.security.egd=f ... Up 0.0.0.0:5001->9001/tcpworkshop_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/AlfaC:\> curl http://192.168.99.100:5002/api/recommendations/Beta
MILAN 18/19.11.2015 - GIULIO SANTOLI
OPEN THE BROWSER AT: http://192.168.99.100:5555/hystrixINSERT THE FOLLOWING LINK: http://172.17.0.5:9002/hystrix.stream
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> ab -c 100 -n 3000 http://192.168.99.100:5002/api/recommendations/Alfa
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> docker-compose stop membershipC:\membership> docker-compose rm -f –v membership
...
membership:build: membershiprestart: alwayslinks:
- eureka:eurekasrvports:
- "5001:9001"
...
docker-compose.yml
Remove these
lines
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> docker-compose up -d membership
C:\> docker-compose scale membership=2
C:\> docker-compose psName Command State Ports----------------------------------------------------------------------------------------------------------------------------workshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcpworkshop_hystrix_1 java -Djava.security.egd=f ... Up 0.0.0.0:5555->8888/tcpworkshop_membership_1 java -Djava.security.egd=f ... Up 9001/tcpworkshop_membership_2 java -Djava.security.egd=f ... Up 9001/tcpworkshop_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/AlfaC:\> curl http://192.168.99.100:5002/api/recommendations/Beta
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
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
MILAN 18/19.11.2015 - GIULIO SANTOLI
Scenario 9: Centralized Logging with ELK
RECOMMENDATIONS
(5002:9002)
MEMBERSHIP
EUREKA
(5000:9000)
link:eurekasrv
link:eurekasrv
Docker Engine
ELASTICSEARCH
HYSTRIX
(5555:8888)
LOGSTASH
(/tmp)
KIBANA
(5601:5601)
link:elasticsearch
link:elasticsearch
volume:logstashfw
volume:logstashfw
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> docker-compose stop
C:\> docker-compose rm -f -v
C:\> docker-compose psName Command State Ports------------------------------
FROM logstashCOPY conf/logstash-spring-boot.conf /conf/logstash-spring-boot.confCOPY conf/custompatterns /opt/logstash/patterns/custompatterns
Dockerfile
Create this file in
logstash
MILAN 18/19.11.2015 - GIULIO SANTOLI
input {file {path => [ "/tmp/*.log" ]
}}
filter {multiline {
pattern => "^(%{TIMESTAMP_ISO8601})"negate => truewhat => "previous"
}grok {
# Do multiline matching with (?m) as the above mutliline filter may add newlines to the log messages.match => [ "message", "(?m)^%{TIMESTAMP_ISO8601:logtime}%{SPACE}%{LOGLEVEL:loglevel} %{SPACE}%{NUMBER:pid}%{SPACE}---
%{SPACE}%{SYSLOG5424SD:threadname}%{SPACE}%{JAVACLASSSHORT:classname}%{SPACE}:%{SPACE}%{GREEDYDATA:logmessage}" ]}
}
output {elasticsearch { hosts => ["elasticsearch:9200"] }stdout { codec => rubydebug }
}
logstash-spring-boot.conf
Create these file in
logstash/conf
JAVACLASSSHORT (?:[\.]?[a-zA-Z0-9-]+\.)*[A-Za-z0-9$]+ custompatterns
MILAN 18/19.11.2015 - GIULIO SANTOLI
...
elasticsearch:image: elasticsearchcommand: elasticsearch -Des.network.host=::0
kibana:image: kibanaports:- "5601:5601"
links:- elasticsearch
logstash:build: logstashcommand: logstash -f /conf/logstash-spring-boot.conflinks:- elasticsearch
volumes:- /tmp/
docker-compose.yml
Add the following
statements
MILAN 18/19.11.2015 - GIULIO SANTOLI
...
membership:build: membershiprestart: alwayslinks:
- eureka:eurekasrvvolumes_from:- logstash
recommendations:build: recommendationsrestart: alwaysports:
- "5002:9002"links:
- eureka:eurekasrvvolumes_from:- logstash
...
docker-compose.yml
Add these
statements
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\logstash> docker-compose build logstash
C:\logstash> docker-compose up -d elasticsearch eurekaC:\logstash> docker-compose up -d kibana logstashC:\logstash> docker-compose up -d membershipC:\logstash> docker-compose up -d recommendations
C:\>docker-compose psName Command State Ports------------------------------------------------------------------------------------------------------------------------------workshop_elasticsearch_1 /docker-entrypoint.sh elas ... Up 9200/tcp, 9300/tcpworkshop_eureka_1 java -Djava.security.egd=f ... Up 0.0.0.0:5000->9000/tcpworkshop_kibana_1 /docker-entrypoint.sh kibana Up 0.0.0.0:5601->5601/tcpworkshop_logstash_1 /docker-entrypoint.sh logs ... Upworkshop_membership_1 java -Djava.security.egd=f ... Up 9001/tcpworkshop_recommendations_1 java -Djava.security.egd=f ... Up 0.0.0.0:5002->9002/tcp
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\logstash> curl http://192.168.99.100:5002/api/recommendations/Alfa
MILAN 18/19.11.2015 - GIULIO SANTOLI
MEMBERSHIP
(80)
Scenario 10: Cloud Foundry
RECOMMENDATIONS
(80)
MEMBERSHIP
(80)
EUREKA
(80)
HYSTRIX
(80)
EUREKA
SERVICE
MILAN 18/19.11.2015 - GIULIO SANTOLI
server:port: ${PORT:9000}
eureka:instance:
hostname: ${vcap.application.uris[0]:localhost}client:
registerWithEureka: falsefetchRegistry: falseserviceUrl:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
---spring:profiles: docker
eureka:instance:
hostname: eurekasrv
application.yml
Modify the file
for eureka
MILAN 18/19.11.2015 - GIULIO SANTOLI
---applications:- name: giulio-eurekamemory: 256Minstances: 1path: build/libs/eurekaserver-0.0.1-SNAPSHOT.jarenv:
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 build\libs\eurekaserver-0.0.1-SNAPSHOT.jar
C:\eurekaserver> cf push
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\eurekaserver> cf appsGetting apps in org [email protected] / space demo as [email protected]
name requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.net
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\> cf cups giulio-eureka-service -p "{\"uri\": \"http://giulio-eureka.mybluemix.net/eureka/\"}«
C:\> cf servicesGetting services in org [email protected] / space demo as [email protected]
name service plan bound apps last operationgiulio-eureka-service user-provided
Define a
custom service
MILAN 18/19.11.2015 - GIULIO SANTOLI
server.port: ${PORT:9001}
spring.application.name: membership
security.basic.enabled: false
eureka:leaseRenewalIntervalInSeconds: 3client:registryFetchIntervalSeconds: 5instanceInfoReplicationIntervalSeconds: 5initialInstanceInfoReplicationIntervalSeconds: 5serviceUrl:defaultZone: ${vcap.services.giulio-eureka-service.credentials.uri:http://localhost:9000/eureka/}
instance:hostname: ${vcap.application.uris[0]:localhost}metadataMap:instanceId: ${spring.application.name}:${server.port}
---spring:profiles: cloud
eureka.instance.nonSecurePort: 80
...
application.yml
Modify the file
for members
MILAN 18/19.11.2015 - GIULIO SANTOLI
---applications:- name: giulio-membershipmemory: 256Minstances: 1path: build/libs/membership-0.0.1-SNAPSHOT.jarenv:
JAVA_OPTS: "-Djava.security.egd=file:/dev/./urandom"SPRING_PROFILES_ACTIVE: cloud
services:- giulio-eureka-service
manifest.yml
Create this file in
membership
Use a unique
Name!
C:\membership> gradlew bootRepackage
C:\membership> java -jar build\libs\membership-0.0.1-SNAPSHOT.jar
C:\membership> cf push
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> cf appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-membership started 1/1 256M 1G giulio-membership.mybluemix.net
C:\membership> curl http://giulio-membership.mybluemix.net/api/member/Alfa
MILAN 18/19.11.2015 - GIULIO SANTOLI
server.port: ${PORT:9002}
spring.application.name: recommendations
security.basic.enabled: false
eureka:leaseRenewalIntervalInSeconds: 3client:registryFetchIntervalSeconds: 5instanceInfoReplicationIntervalSeconds: 5initialInstanceInfoReplicationIntervalSeconds: 5serviceUrl:defaultZone: ${vcap.services.giulio-eureka-service.credentials.uri:http://localhost:9000/eureka/}
instance:hostname: ${vcap.application.uris[0]:localhost}metadataMap:instanceId: ${spring.application.name}:${server.port}
...
application.yml
Modify the file
for recommendations
MILAN 18/19.11.2015 - GIULIO SANTOLI
---applications:- name: giulio-recommendationsmemory: 256Minstances: 1path: build/libs/recommendations-0.0.1-SNAPSHOT.jarenv:
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 build\libs\recommendations-0.0.1-SNAPSHOT.jar
C:\recommendations> cf push
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\recommendations> cf appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-membership started 1/1 256M 1G giulio-membership.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
C:\recommendations> crul http://giulio-recommendations.mybluemix.net/api/recommendations/Alfa
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\recommendations> cf scale giulio-membership -i 2C:\recommendations> cf appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-membership started 2/2 256M 1G giulio-membership.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
MILAN 18/19.11.2015 - GIULIO SANTOLI
---applications:- name: giulio-hystrixmemory: 256Minstances: 1path: build/libs/hystrixdashboard-0.0.1-SNAPSHOT.jarenv:
JAVA_OPTS: "-Djava.security.egd=file:/dev/./urandom"
manifest.yml
Create this file in
hystrixdashboard
Use a unique
Name!
C:\hystrixdashboard> cf push
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\hystrixdashboard> cf appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.netgiulio-membership started 2/2 256M 1G giulio-membership.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
OPEN BROWSER AT: http://giulio-hystrix.mybluemix.net/hystrixINSERT: http://giulio-recommendations.mybluemix.net:80/hystrix.stream
MILAN 18/19.11.2015 - GIULIO SANTOLI
MEMBERSHIP
(80)
Scenario 11: Canary Deployment in Cloud Foundry
RECOMMENDATIONS
(80)MEMBERSHIP 1
(80)
EUREKA
(80)
EUREKA
SERVICEMEMBERSHIP
(80)MEMBERSHIP 2
(80)
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> cf stop giulio-hystrixC:\membership> cf scale giulio-membership -i 3C:\membership> cf appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-hystrix stopped 0/1 256M 1G giulio-hystrix.mybluemix.netgiulio-membership started 3/3 256M 1G giulio-membership.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
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
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
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 appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.netgiulio-membership started 2/2 256M 1G giulio-membership.mybluemix.netgiulio-membershipv2 started 1/1 256M 1G giulio-membershipv2.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
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
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 appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.netgiulio-membership started 1/1 256M 1G giulio-membership.mybluemix.netgiulio-membershipv2 started 2/2 256M 1G giulio-membershipv2.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
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
MILAN 18/19.11.2015 - GIULIO SANTOLI
C:\membership> cf stop giulio-membership
C:\membership> cf scale giulio-membershipv2 -i 3
C:\membership> cf appsname requested state instances memory disk urlsgiulio-eureka started 1/1 256M 1G giulio-eureka.mybluemix.netgiulio-hystrix started 1/1 256M 1G giulio-hystrix.mybluemix.netgiulio-membership started 0/1 256M 1G giulio-membership.mybluemix.netgiulio-membershipv2 started 3/3 256M 1G giulio-membershipv2.mybluemix.netgiulio-recommendations started 1/1 256M 1G giulio-recommendations.mybluemix.net
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