diff --git a/spring-cloud/spring-cloud-bootstrap/README.MD b/spring-cloud/spring-cloud-bootstrap/README.MD index d6f8faf31e..251c861830 100644 --- a/spring-cloud/spring-cloud-bootstrap/README.MD +++ b/spring-cloud/spring-cloud-bootstrap/README.MD @@ -1,3 +1,12 @@ ### Relevant Articles: - [Spring Cloud – Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping) - [Spring Cloud – Securing Services](http://www.baeldung.com/spring-cloud-securing-services) + +- To run the project: + - copy the appliction-config folder to c:\Users\{username}\ on Windows or /Users/{username}/ on *nix. Then open a git bash terminal in application-config and run: + - git init + - git add . + - git commit -m "First commit" + - start the config server + - start the discover server + - start all the other servers in any order (gateway, svc-book, svc-rating, zipkin) diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties index e1244a0cf0..49f7d1ed91 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties @@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug spring.redis.host=localhost spring.redis.port=6379 + +spring.sleuth.sampler.percentage=1.0 +spring.sleuth.web.skipPattern=(^cleanup.*) diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties index 09f7f3bf4a..e9e593284c 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties @@ -24,4 +24,7 @@ logging.level.org.springframework.security=debug logging.level.org.springframework.cloud.netflix.zuul=debug spring.redis.host=localhost -spring.redis.port=6379 \ No newline at end of file +spring.redis.port=6379 + +spring.sleuth.sampler.percentage=1.0 +spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*) \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties index 4817d12c83..b7cbb6fbd6 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties @@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug spring.redis.host=localhost spring.redis.port=6379 + +spring.sleuth.sampler.percentage=1.0 +spring.sleuth.web.skipPattern=(^cleanup.*) diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties b/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties new file mode 100644 index 0000000000..ca3aed2263 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties @@ -0,0 +1,7 @@ +spring.application.name=zipkin +server.port=9411 + +eureka.client.region = default +eureka.client.registryFetchIntervalSeconds = 5 + +logging.level.org.springframework.web=debug diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml index 044730ba22..97c440c249 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml @@ -41,6 +41,11 @@ spring-boot-starter-data-redis + + org.springframework.cloud + spring-cloud-starter-zipkin + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java index b5ae1e4e7b..16aae66cab 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java @@ -1,6 +1,9 @@ package com.baeldung.spring.cloud.bootstrap.gateway; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; @@ -8,8 +11,13 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.cloud.sleuth.metric.SpanMetricReporter; +import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; +import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; +import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; +import zipkin.Span; import java.util.ArrayList; import java.util.List; @@ -18,23 +26,50 @@ import java.util.List; @EnableZuulProxy @EnableEurekaClient public class GatewayApplication { - public static void main(String[] args) { - SpringApplication.run(GatewayApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class, args); + } - @Autowired(required = false) - private List configurations = new ArrayList<>(); + @Autowired(required = false) + private List configurations = new ArrayList<>(); + @Autowired + private EurekaClient eurekaClient; + @Autowired + private SpanMetricReporter spanMetricReporter; + @Autowired + private ZipkinProperties zipkinProperties; + @Value("${spring.sleuth.web.skipPattern}") + private String skipPattern; - @Bean - @LoadBalanced - RestTemplate restTemplate() { - return new RestTemplate(); - } + @Bean + @LoadBalanced + RestTemplate restTemplate() { + return new RestTemplate(); + } - @Bean - public SpringClientFactory springClientFactory() { - SpringClientFactory factory = new SpringClientFactory(); - factory.setConfigurations(this.configurations); - return factory; - } + @Bean + public SpringClientFactory springClientFactory() { + SpringClientFactory factory = new SpringClientFactory(); + factory.setConfigurations(this.configurations); + return factory; + } + + @Bean + public ZipkinSpanReporter makeZipkinSpanReporter() { + return new ZipkinSpanReporter() { + private HttpZipkinSpanReporter delegate; + private String baseUrl; + + @Override + public void report(Span span) { + InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); + if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) { + baseUrl = instance.getHomePageUrl(); + delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter); + if (!span.name.matches(skipPattern)) delegate.report(span); + } + if (!span.name.matches(skipPattern)) delegate.report(span); + } + }; + } } diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java index 9e5c424403..935e50ec72 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java @@ -23,6 +23,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/book-service/books").permitAll() + .antMatchers("/zipkin/**").permitAll() .antMatchers("/eureka/**").hasRole("ADMIN") .anyRequest().authenticated() .and() diff --git a/spring-cloud/spring-cloud-bootstrap/pom.xml b/spring-cloud/spring-cloud-bootstrap/pom.xml index ccfbdb9735..83879cf7d4 100644 --- a/spring-cloud/spring-cloud-bootstrap/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/pom.xml @@ -16,6 +16,7 @@ gateway svc-book svc-rating + zipkin diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml index c351c444f6..cbf7083b83 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml @@ -53,6 +53,11 @@ runtime + + org.springframework.cloud + spring-cloud-starter-zipkin + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java index c5499cd924..63ff0fb134 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java @@ -1,13 +1,52 @@ package com.baeldung.spring.cloud.bootstrap.svcbook; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.sleuth.metric.SpanMetricReporter; +import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; +import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; +import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; +import org.springframework.context.annotation.Bean; +import zipkin.Span; @SpringBootApplication @EnableEurekaClient public class BookServiceApplication { + + @Autowired + private EurekaClient eurekaClient; + @Autowired + private SpanMetricReporter spanMetricReporter; + @Autowired + private ZipkinProperties zipkinProperties; + @Value("${spring.sleuth.web.skipPattern}") + private String skipPattern; + public static void main(String[] args) { SpringApplication.run(BookServiceApplication.class, args); } + + @Bean + public ZipkinSpanReporter makeZipkinSpanReporter() { + return new ZipkinSpanReporter() { + private HttpZipkinSpanReporter delegate; + private String baseUrl; + + @Override + public void report(Span span) { + InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); + if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) { + baseUrl = instance.getHomePageUrl(); + delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter); + if (!span.name.matches(skipPattern)) delegate.report(span); + } + if (!span.name.matches(skipPattern)) delegate.report(span); + } + }; + } } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties index 8f3a3261ac..481cdc182c 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties @@ -4,4 +4,4 @@ spring.cloud.config.discovery.enabled=true spring.cloud.config.username=configUser spring.cloud.config.password=configPassword -eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ +eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml index 2285286812..f02ba88f04 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml @@ -53,6 +53,11 @@ runtime + + org.springframework.cloud + spring-cloud-starter-zipkin + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java index 61074e0bcc..0d85c5c825 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java @@ -1,13 +1,51 @@ package com.baeldung.spring.cloud.bootstrap.svcrating; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.sleuth.metric.SpanMetricReporter; +import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; +import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; +import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; +import org.springframework.context.annotation.Bean; +import zipkin.Span; @SpringBootApplication @EnableEurekaClient public class RatingServiceApplication { + @Autowired + private EurekaClient eurekaClient; + @Autowired + private SpanMetricReporter spanMetricReporter; + @Autowired + private ZipkinProperties zipkinProperties; + @Value("${spring.sleuth.web.skipPattern}") + private String skipPattern; + public static void main(String[] args) { SpringApplication.run(RatingServiceApplication.class, args); } + + @Bean + public ZipkinSpanReporter makeZipkinSpanReporter() { + return new ZipkinSpanReporter() { + private HttpZipkinSpanReporter delegate; + private String baseUrl; + + @Override + public void report(Span span) { + InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); + if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) { + baseUrl = instance.getHomePageUrl(); + delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter); + if (!span.name.matches(skipPattern)) delegate.report(span); + } + if (!span.name.matches(skipPattern)) delegate.report(span); + } + }; + } } \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml new file mode 100644 index 0000000000..c2fd7cd2dc --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + zipkin + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.4.RELEASE + + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-eureka + + + + io.zipkin.java + zipkin-server + + + + io.zipkin.java + zipkin-autoconfigure-ui + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*LiveTest.java + + + + + + + + Brixton.SR7 + 3.6.0 + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java new file mode 100644 index 0000000000..bb1355e258 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.bootstrap.zipkin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import zipkin.server.EnableZipkinServer; + +@SpringBootApplication +@EnableEurekaClient +@EnableZipkinServer +public class ZipkinApplication { + public static void main(String[] args) { + SpringApplication.run(ZipkinApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..9569179a4f --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties @@ -0,0 +1,7 @@ +spring.cloud.config.name=zipkin +spring.cloud.config.discovery.service-id=config +spring.cloud.config.discovery.enabled=true +spring.cloud.config.username=configUser +spring.cloud.config.password=configPassword + +eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file