SpringCloud Sleuth Profile
Spring Cloud Spring Cloud Sleuth is a distributed tracking solution.
Spring Cloud Sleuth learn the terminology of Dapper.
Span : the basic unit of work. Span includes a unique 64-bit ID, a 64-bit trace code description information, event timestamp, key-value annotations (tags), ID span handler (typically IP).
The Trace : a group formed by Span tree structure.
Annotation : for events occurring in time record. Annotation commonly used as follows:
- cs: The client sends (client send) a client initiates a request to start showing span
- sr: receiving server (server received) server receives the client's request and begins processing, sr - cs delay time for the network
- ss: sending server (server send) server processes the request ready to return data to the client. ss - sr server-side processing time represents the time it takes to request
- cr: receiving client (client received) the client receives the processing result, indicating the end of span. cr - cs of time that the client receives the server data of time
The following figure shows Span and Trace link in the system
SpringCloud Sleuth defaults Http way transmission of information to the span Zipkin
Specified in the file application.properties
spring.zipkin.sender.type=web
RabbitMQ asynchronous transmit information using span
Why RabbitMQ messaging middleware sends span information
- sleuth default to http communication, the data to zipkin for page rendering, but if http transfer process due to force majeure lead to http communication is interrupted, then the data communication will be lost. The use of middleware, then, RabbitMQ message queue can backlog million level messages, you can continue to consume after next reconnection.
- With the increase of thread concurrency after upgrade, RabbitMQ asynchronous transmit data clearly has more advantages.
- RabbitMQ supports message queue persistence, can fall through the library status message, return queue, the queue mirroring other technical means to ensure its availability.
Examples
Example Introduction
Sample contains sleuth-search, sleuth-cart, sleuth-order three systems for analog systems commercially under the single process, the user can then order now to find a product, you can search the plurality of items to the cart, and orders, calling the situation that is search -> cart -> order, or search -> order.
Use example RestTemplate
be done between the three systems http
request response request method also follow Restful
style.
Imprint
Version must correspond to good, some low version of SpringBoot not compatible with the new version of SpringCloud and zipkin
tool | version |
---|---|
SpringBoot | 2.1.6.RELEASE |
SpringCloud | Greenwich.SR3 |
zipkin | 2.16.2 |
Project structure
demo-cloudsleuth
|- sleuth-search
|- sleuth-cart
|- sleuth-order
pom.xml
Import dependence
<!-- 引入 springboot 和 springcloud 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
<!-- Springboot 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Configuring RestTemplate, RestTemplate is packaged http SpringBoot provide tools that can help us simplify the use of http.
package com.anqi.cart.resttmplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(5000);
return factory;
}
}
application.properties the three systems, namely the port 808180828083
#server.port=8081 server.port=8082
server.port=8083
server.servlet.context-path=/
spring.zipkin.base-url=http://localhost:9411/
spring.zipkin.service.name=sleuth-cart
#使用默认 http 方式收集 span 需要配置此项
#spring.zipkin.sender.type=web
#sleuth 使用 rabbitmq 来向 zipkin 发送数据
spring.zipkin.sender.type=rabbit
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#设置采样率默认为 0.1 注意之前的版本是percentage 新版本中更换为 probability
spring.sleuth.sampler.probability=1
RestTemplate arranged in three systems, to simplify the http request
package com.anqi.cart.resttmplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(5000);
return factory;
}
}
@RequestMapping("cart")
@RestController
public class CartController {
@Autowired
RestTemplate restTemplate;
@Autowired
CartService cartService;
private static final String orderUrl = "http://localhost:8084/order/create";
@GetMapping("/add/{cartId}")
public String addToCart(@PathVariable("cartId") String cartId) {
cartService.addProductToCart(cartId, "小米8");
ResponseEntity<String> res = restTemplate.getForEntity(orderUrl, String.class);
return res.getBody();
}
}
@RequestMapping("order")
@RestController
public class OrderController {
@GetMapping("/create")
public String creatOrder() {
System.out.println("create order");
return "create_order";
}
}
@RestController
public class SearchController {
@Autowired
RestTemplate restTemplate;
private static final String cartUrl = "http://localhost:8083/cart/add/1";
private static final String orderUrl = "http://localhost:8084/order/create";
@GetMapping("/search")
public String search() {
ResponseEntity<String> cartRes = restTemplate.getForEntity(cartUrl, String.class);
ResponseEntity<String> orderRes = restTemplate.getForEntity(orderUrl, String.class);
return "cart:" + cartRes.getBody() + "- order:" + orderRes.getBody();
}
}
Analysis of operating results
The default http transmission span information
start upZipkin
java -jar zipkin-server-2.16.2-exec.jar
Web pages manually access
http://localhost:8082/search
We visited the site zipkin case inquiry call
http://localhost:9411/zipkin/traces/94b954d843012ca9
We can clearly see the call to complete the three systems of relations from the figure
The figure below shows zipkin calls preview, we asked four times http://localhost:8082/search
to a more intuitive observation data. In the following interface, it is simple and the number of display calls Span overall delay.
Access which we enter a complete chain of calls a node to get the data.
The following is a link to track full details, including information on all seven span of more than see page show the following data to be rendered are made.
[
{
"traceId": "94b954d843012ca9",
"parentId": "bab70b1e69a5f3e3",
"id": "96387b33a823ca8f",
"kind": "SERVER",
"name": "get /order/create",
"timestamp": 1569060494069123,
"duration": 1161,
"localEndpoint": {
"serviceName": "sletuth-order",
"ipv4": "192.168.0.107"
},
"remoteEndpoint": {
"ipv4": "127.0.0.1",
"port": 49863
},
"tags": {
"http.method": "GET",
"http.path": "/order/create",
"mvc.controller.class": "OrderController",
"mvc.controller.method": "creatOrder"
},
"shared": true
},
{
"traceId": "94b954d843012ca9",
"parentId": "94b954d843012ca9",
"id": "90f7e5cfa89e0d80",
"kind": "SERVER",
"name": "get /order/create",
"timestamp": 1569060494076287,
"duration": 1296,
"localEndpoint": {
"serviceName": "sletuth-order",
"ipv4": "192.168.0.107"
},
"remoteEndpoint": {
"ipv4": "127.0.0.1",
"port": 49864
},
"tags": {
"http.method": "GET",
"http.path": "/order/create",
"mvc.controller.class": "OrderController",
"mvc.controller.method": "creatOrder"
},
"shared": true
},
{
"traceId": "94b954d843012ca9",
"parentId": "94b954d843012ca9",
"id": "bab70b1e69a5f3e3",
"kind": "CLIENT",
"name": "get",
"timestamp": 1569060494063693,
"duration": 10374,
"localEndpoint": {
"serviceName": "sleuth-search",
"ipv4": "192.168.0.107"
},
"tags": {
"http.method": "GET",
"http.path": "/cart/add/1"
}
},
{
"traceId": "94b954d843012ca9",
"parentId": "94b954d843012ca9",
"id": "90f7e5cfa89e0d80",
"kind": "CLIENT",
"name": "get",
"timestamp": 1569060494074966,
"duration": 2848,
"localEndpoint": {
"serviceName": "sleuth-search",
"ipv4": "192.168.0.107"
},
"tags": {
"http.method": "GET",
"http.path": "/order/create"
}
},
{
"traceId": "94b954d843012ca9",
"id": "94b954d843012ca9",
"kind": "SERVER",
"name": "get /search",
"timestamp": 1569060494062631,
"duration": 16332,
"localEndpoint": {
"serviceName": "sleuth-search",
"ipv4": "192.168.0.107"
},
"remoteEndpoint": {
"ipv6": "::1",
"port": 49859
},
"tags": {
"http.method": "GET",
"http.path": "/search",
"mvc.controller.class": "SearchController",
"mvc.controller.method": "search"
}
},
{
"traceId": "94b954d843012ca9",
"parentId": "bab70b1e69a5f3e3",
"id": "96387b33a823ca8f",
"kind": "CLIENT",
"name": "get",
"timestamp": 1569060494067090,
"duration": 3197,
"localEndpoint": {
"serviceName": "sleuth-cart",
"ipv4": "192.168.0.107"
},
"tags": {
"http.method": "GET",
"http.path": "/order/create"
}
},
{
"traceId": "94b954d843012ca9",
"parentId": "94b954d843012ca9",
"id": "bab70b1e69a5f3e3",
"kind": "SERVER",
"name": "get /cart/add/{cartid}",
"timestamp": 1569060494066140,
"duration": 8150,
"localEndpoint": {
"serviceName": "sleuth-cart",
"ipv4": "192.168.0.107"
},
"remoteEndpoint": {
"ipv4": "127.0.0.1",
"port": 49862
},
"tags": {
"http.method": "GET",
"http.path": "/cart/add/1",
"mvc.controller.class": "CartController",
"mvc.controller.method": "addToCart"
},
"shared": true
}
]
RabbitMQ Use cases
Start zipkin, pay attention to the parameters
java -jar zipkin-server-2.16.2-exec.jar --RABBIT_ADDRESSES=localhost:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/
Start rabbitmq
rabbitmq-server
During the test and find more ways mq delay is almost the same, but with the increase in the number of threads is to increase the amount of concurrency, mq transmission delay will be significantly lower than http.