2018-08-30 14:40:07.0|分类: docker+node.js+zookeeper构建微服务|浏览量: 1902
|
docker镜像官网 https://hub.docker.com/u/library/ zipkin镜像版本列表 https://hub.docker.com/r/openzipkin/zipkin/tags/ 随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题。 跟踪器(Tracers)存在在你的应用程序中生存,记录时间和关于操作的元数据。他们经常使用库,因此他们的使用对用户是透明的。例如,当它收到一个请求并发送一个响应时,一个感应器(instrumented )的web服务器记录。所收集的跟踪数据称为Span。 zipkin重要概念: Span:基本工作单元,一次链路调用(可以是RPC,DB等没有特定的限制)创建一个span,通过一个64位ID标识它, span通过还有其他的数据,例如描述信息,时间戳,key-value对的(Annotation)tag信息,parent-id等,其中parent-id 可以表示span调用链路来源,通俗的理解span就是一次请求信息 Trace:类似于树结构的Span集合,表示一条调用链路,存在唯一标识 Annotation: 注解,用来记录请求特定事件相关信息(例如时间),通常包含四个注解信息
官网提供例子流程图: ┌─────────────┐ ┌───────────────────────┐ ┌─────────────┐ ┌──────────────────┐
│ User Code │ │ Trace Instrumentation │ │ Http Client │ │ Zipkin Collector │
└─────────────┘ └───────────────────────┘ └─────────────┘ └──────────────────┘
│ │ │ │
┌─────────┐
│ ──┤GET /foo ├─▶ │ ────┐ │ │
└─────────┘ │ record tags
│ │ ◀───┘ │ │
────┐
│ │ │ add trace headers │ │
◀───┘
│ │ ────┐ │ │
│ record timestamp
│ │ ◀───┘ │ │
┌─────────────────┐
│ │ ──┤GET /foo ├─▶ │ │
│X-B3-TraceId: aa │ ────┐
│ │ │X-B3-SpanId: 6b │ │ │ │
└─────────────────┘ │ invoke
│ │ │ │ request │
│
│ │ │ │ │
┌────────┐ ◀───┘
│ │ ◀─────┤200 OK ├─────── │ │
────┐ └────────┘
│ │ │ record duration │ │
┌────────┐ ◀───┘
│ ◀──┤200 OK ├── │ │ │
└────────┘ ┌────────────────────────────────┐
│ │ ──┤ asynchronously report span ├────▶ │
│ │
│{ │
│ "traceId": "aa", │
│ "id": "6b", │
│ "name": "get", │
│ "timestamp": 1483945573944000,│
│ "duration": 386000, │
│ "annotations": [ │
│--snip-- │
└────────────────────────────────┘docker安装zipkin docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin1.22.0
用springboot构建一个例子,例子访问流程图如下:
business/order/user服务程序,代码非常相似。zipkin-conca是zipkin基础代码,business/order/user都需要引用zipkin-conca。 business项目内容: App.java package com.cookqq.business;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* Hello world!
*
*/
@SpringBootApplication(scanBasePackages="com.cookqq")
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}BusinessController.java package com.cookqq.business;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class BusinessController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping( method=RequestMethod.GET, path="/show")
public String show(){
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
return restTemplate.getForObject("http://127.0.0.1:8081/order", String.class);
}
}application.properties server.port=8080 zipkin.endpoint=http://192.168.99.100:9411/api/v1/spans zipkin.service=business pom.xml <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> <groupId>com.cookqq</groupId> <artifactId>business</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>business</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <repositories> <repository> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> </repository> <repository> <id>jcenter</id> <name>jcenter Repository</name> <url>http://jcenter.bintray.com/</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.cookqq</groupId> <artifactId>zipkin-conca</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project> zipkin-conca项目 ZipkinConfiguration类 package com.cookqq.zipkin.conca;
import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.http.HttpRequest;
import com.github.kristofa.brave.http.SpanNameProvider;
import com.github.kristofa.brave.mysql.MySQLStatementInterceptorManagementBean;
import com.github.kristofa.brave.spring.BraveClientHttpRequestInterceptor;
import com.github.kristofa.brave.spring.ServletHandlerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import zipkin.Span;
import zipkin.reporter.AsyncReporter;
import zipkin.reporter.Reporter;
import zipkin.reporter.Sender;
import zipkin.reporter.okhttp3.OkHttpSender;
import javax.annotation.PostConstruct;
import java.util.List;
@Configuration
@Import({RestTemplate.class, BraveClientHttpRequestInterceptor.class, ServletHandlerInterceptor.class})
public class ZipkinConfiguration extends WebMvcConfigurerAdapter {
@Autowired
private ZipkinProperties zipkinProperties;
@Bean
public Sender sender() {
return OkHttpSender.create(zipkinProperties.getEndpoint());
}
@Bean
public Reporter<Span> reporter() {
// return new LoggingReporter();
return AsyncReporter.builder(sender()).build();
}
@Bean
public Brave brave() {
return new Brave.Builder(zipkinProperties.getService()).reporter(reporter()).build();
}
@Bean
public SpanNameProvider spanNameProvider() {
// return new DefaultSpanNameProvider();
return new SpanNameProvider() {
public String spanName(HttpRequest httpRequest) {
return String.format(
"%s %s",
httpRequest.getHttpMethod(),
httpRequest.getUri().getPath()
);
}
};
}
// @Bean
// public MySQLStatementInterceptorManagementBean mySQLStatementInterceptorManagementBean() {
// return new MySQLStatementInterceptorManagementBean(brave().clientTracer());
// }
@Autowired
private RestTemplate restTemplate;
@Autowired
private BraveClientHttpRequestInterceptor clientInterceptor;
@Autowired
private ServletHandlerInterceptor serverInterceptor;
@PostConstruct
public void init() {
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
interceptors.add(clientInterceptor);
restTemplate.setInterceptors(interceptors);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(serverInterceptor);
}
}ZipkinProperties类 package com.cookqq.zipkin.conca;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("zipkin")
public class ZipkinProperties {
private String endpoint;
private String service;
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
}pom.xml <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> <groupId>com.cookqq</groupId> <artifactId>zipkin-conca</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>zipkin-conca</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> <version>1.5.2.RELEASE</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.7.RELEASE</version> <scope>provided</scope> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-spring-web-servlet-interceptor</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-spring-resttemplate-interceptors</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-mysql</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>io.zipkin.reporter</groupId> <artifactId>zipkin-sender-okhttp3</artifactId> <version>0.6.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> 启动三个项目,访问http://localhost:8080/show
上述代码测试过zipkin版本1.22.0,2.6.0,2.8.0(支持), 2.10.0(不支持) |
