介绍:
Twitter的zipkin是一个致力于收集Twitter所有的分布式服务的时间数据的分布式跟踪系统。它提供了收集数据,和查询数据两大服务。系统的理论模型来自于Google Dapper 论文。通过采集跟踪数据可以帮助开发者深入了解在分布式系统中某一个特定的请求时如何执行的。
zipkin-server
pom.xml 添加依赖
<!--zipkin依赖 -->
<!--此依赖会自动引入spring-cloud-sleuth-stream并且引入zipkin的依赖包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<scope>runtime</scope>
</dependency>
<!--保存到数据库需要如下依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
application.properties 配置
server.port=9411
spring.application.name=zipkin-server
spring.sleuth.enabled=false
#rabbitmq配置
spring.rabbitmq.host=172.20.4.132
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=111111
zipkin.storage.type=mysql
#spring.datasource.schema[0]=classpath:/zipkin.sql
spring.datasource.url=jdbc:mysql://172.20.4.135:3306/zipkin?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=root
spring.datasource.password=111111
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.initialize=true
spring.datasource.continue-on-error=true
application启动入口
@SpringBootApplication
@EnableZipkinStreamServer
public class SleuthServerApplication {
public static void main(String[] args) {
SpringApplication.run(SleuthServerApplication.class,args);
}
}
rabbitMQ
我是直接阿里云下载的docker镜像
docker pull registry.cn-hangzhou.aliyuncs.com/zp-k8s/rabbitmq:3-management
docker run -d --net host --name rabbitmq registry.cn-hangzhou.aliyuncs.com/zp-k8s/rabbitmq:3-management
docker exec -it 容器id /bin/bash
通过find 命令查找rabbit安装目录
找到rabbitmqctl执行
./rabbitmqctl add_user admin 111111
./rabbitmqctl set_user_tags admin administrator
配置完用户密码和权限后,登录到webUI
至此zipkin-server端的全部配置完成。
服务demo
service1
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
application.properties
spring.application.name=orderService
server.port=9981
#spring.zipkin.baseUrl=http://localhost:9411
spring.zipkin.enabled=true
spring.sleuth.sampler.percentage=1
#rabbitmq配置
spring.rabbitmq.host=172.20.4.132
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=111111
java 示例代码,其实就是普通的服务调用
@SpringBootApplication
public class SleuthClientApplication1 {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(SleuthClientApplication1.class, args);
}
}
@RestController
class OrderController {
private static final Log log = LogFactory.getLog(OrderController.class);
@Autowired
private RestTemplate restTemplate;
private String url="http://localhost:9982";
@RequestMapping("/order-info/{id}")
public String service1(@PathVariable("id") String id,ModelMap model) throws Exception {
log.info("fetch order info ");
model.addAttribute("order", id+"订单信息。。。。");
Thread.sleep(200L);
String coupon = this.restTemplate.getForObject(url + "/coupon/"+id, String.class);
model.addAttribute("coupon", coupon);
String point = this.restTemplate.getForObject(url + "/point/"+id, String.class);
model.addAttribute("point", point);
return model.toString();
}
@RequestMapping("/order-info-cycle/{id}")
public String cycle(@PathVariable("id") String id,ModelMap model) throws Exception {
log.info("fetch order info ");
model.addAttribute("order", id+"订单信息。。。。");
Thread.sleep(200L);
String coupon = this.restTemplate.getForObject(url + "/coupon/"+id, String.class);
model.addAttribute("coupon", coupon);
String point = this.restTemplate.getForObject(url + "/point/"+id, String.class);
model.addAttribute("point", point);
String cycle = this.restTemplate.getForObject(url + "/do2/"+id, String.class);
model.addAttribute("cycle", cycle);
return model.toString();
}
}
@RestController
class CycleController {
private static final Log log = LogFactory.getLog(CycleController.class);
@RequestMapping("/do1/{id}")
public String hi(@PathVariable("id") String id) throws Exception {
log.info("do1"+id);
Thread.sleep(50L);
return "the "+id+" cycle in order do1";
}
}
server2
pom.xml 是一样的
application.properties
spring.application.name=couponService
server.port=9982
#spring.zipkin.baseUrl=http://localhost:9411
spring.zipkin.enabled=true
spring.sleuth.sampler.percentage=1
spring.rabbitmq.host=172.20.4.132
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=111111
java 代码
package com.yonyou.sleuth;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.context.annotation.Bean;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class SleuthClientApplication2 {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(SleuthClientApplication2.class, args);
}
}
@RestController
class CouponController {
private static final Log log = LogFactory.getLog(CouponController.class);
@RequestMapping("/coupon/{id}")
public String hi(@PathVariable("id") String id) throws Exception {
log.info("coupon"+id);
Thread.sleep(100L);
return "the "+id+" coupon is 100";
}
}
@RestController
class PointController {
private static final Log log = LogFactory.getLog(PointController.class);
@RequestMapping("/point/{id}")
public String hi(@PathVariable("id") String id) throws Exception {
log.info("point"+id);
Thread.sleep(100L);
return "the "+id+" point is 10000";
}
}
@RestController
class CycleController {
private static final Log log = LogFactory.getLog(CycleController.class);
@Autowired
private RestTemplate restTemplate;
private String url="http://localhost:9981";
@RequestMapping("/do2/{id}")
public String hi(@PathVariable("id") String id) throws Exception {
log.info("do2"+id);
Thread.sleep(200L);
String cycle = this.restTemplate.getForObject(url + "/do1/"+id, String.class);
return "the "+id+" do2 in oter service - "+cycle;
}
}
至此完成,启动 zipkin-server、service1、service2
访问 http://localhost:9981/order-info-cycle/1
返回:{order=1订单信息。。。。, coupon=the 1 coupon is 100, point=the 1 point is 10000, cycle=the 1 do2 in oter service - the 1 cycle in order do1}
或者 http://localhost:9981/order-info/1
返回:{order=1订单信息。。。。, coupon=the 1 coupon is 100, point=the 1 point is 10000}
访问zipkin-server webui :http://172.20.4.132:9411/
The end!