Merge pull request #1281 from eugenp/sla-pr/1159-tim-doha

BAEL-574 - Intro to Zipkin
This commit is contained in:
slavisa-baeldung 2017-03-02 09:19:13 +01:00 committed by GitHub
commit beaf59933e
17 changed files with 282 additions and 18 deletions

View File

@ -1,3 +1,12 @@
### Relevant Articles: ### Relevant Articles:
- [Spring Cloud Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping) - [Spring Cloud Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping)
- [Spring Cloud Securing Services](http://www.baeldung.com/spring-cloud-securing-services) - [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)

View File

@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug
spring.redis.host=localhost spring.redis.host=localhost
spring.redis.port=6379 spring.redis.port=6379
spring.sleuth.sampler.percentage=1.0
spring.sleuth.web.skipPattern=(^cleanup.*)

View File

@ -24,4 +24,7 @@ logging.level.org.springframework.security=debug
logging.level.org.springframework.cloud.netflix.zuul=debug logging.level.org.springframework.cloud.netflix.zuul=debug
spring.redis.host=localhost spring.redis.host=localhost
spring.redis.port=6379 spring.redis.port=6379
spring.sleuth.sampler.percentage=1.0
spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*)

View File

@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug
spring.redis.host=localhost spring.redis.host=localhost
spring.redis.port=6379 spring.redis.port=6379
spring.sleuth.sampler.percentage=1.0
spring.sleuth.web.skipPattern=(^cleanup.*)

View File

@ -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

View File

@ -41,6 +41,11 @@
<artifactId>spring-boot-starter-data-redis</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -1,6 +1,9 @@
package com.baeldung.spring.cloud.bootstrap.gateway; 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.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; 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.RibbonClientSpecification;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 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.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import zipkin.Span;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -18,23 +26,50 @@ import java.util.List;
@EnableZuulProxy @EnableZuulProxy
@EnableEurekaClient @EnableEurekaClient
public class GatewayApplication { public class GatewayApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args); SpringApplication.run(GatewayApplication.class, args);
} }
@Autowired(required = false) @Autowired(required = false)
private List<RibbonClientSpecification> configurations = new ArrayList<>(); private List<RibbonClientSpecification> configurations = new ArrayList<>();
@Autowired
private EurekaClient eurekaClient;
@Autowired
private SpanMetricReporter spanMetricReporter;
@Autowired
private ZipkinProperties zipkinProperties;
@Value("${spring.sleuth.web.skipPattern}")
private String skipPattern;
@Bean @Bean
@LoadBalanced @LoadBalanced
RestTemplate restTemplate() { RestTemplate restTemplate() {
return new RestTemplate(); return new RestTemplate();
} }
@Bean @Bean
public SpringClientFactory springClientFactory() { public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory(); SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(this.configurations); factory.setConfigurations(this.configurations);
return factory; 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);
}
};
}
} }

View File

@ -23,6 +23,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/book-service/books").permitAll() .antMatchers("/book-service/books").permitAll()
.antMatchers("/zipkin/**").permitAll()
.antMatchers("/eureka/**").hasRole("ADMIN") .antMatchers("/eureka/**").hasRole("ADMIN")
.anyRequest().authenticated() .anyRequest().authenticated()
.and() .and()

View File

@ -16,6 +16,7 @@
<module>gateway</module> <module>gateway</module>
<module>svc-book</module> <module>svc-book</module>
<module>svc-rating</module> <module>svc-rating</module>
<module>zipkin</module>
</modules> </modules>

View File

@ -53,6 +53,11 @@
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -1,13 +1,52 @@
package com.baeldung.spring.cloud.bootstrap.svcbook; 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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 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 @SpringBootApplication
@EnableEurekaClient @EnableEurekaClient
public class BookServiceApplication { 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) { public static void main(String[] args) {
SpringApplication.run(BookServiceApplication.class, 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);
}
};
}
} }

View File

@ -4,4 +4,4 @@ spring.cloud.config.discovery.enabled=true
spring.cloud.config.username=configUser spring.cloud.config.username=configUser
spring.cloud.config.password=configPassword 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/

View File

@ -53,6 +53,11 @@
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -1,13 +1,51 @@
package com.baeldung.spring.cloud.bootstrap.svcrating; 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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 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 @SpringBootApplication
@EnableEurekaClient @EnableEurekaClient
public class RatingServiceApplication { 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) { public static void main(String[] args) {
SpringApplication.run(RatingServiceApplication.class, 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);
}
};
}
} }

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>zipkin</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<spring-cloud-dependencies.version>Brixton.SR7</spring-cloud-dependencies.version>
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
</properties>
</project>

View File

@ -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);
}
}

View File

@ -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/