一、SpringCloudStream消息驱动
SpringCloudStream看名字就知道他和消息队列相关,但它又不是消息队列,准确来说它类似于硬件里面的驱动程序,也就是前面说的适配器模式的体现。
在系统开发里面难免用到消息队列,但各个的消息队列又有所区别,SpringCloudStream的作用就是屏蔽各种消息队列的区别,对消息队列的API进行进一步的抽象,使得在springcloud里面能更加方便的集成各种消息系统。
首先来看SpringCloudStream的组成:
不管是生产者还是消费者,并不会直接和消息中间件打交道,在SpringCloudStream中抽象了已成binder(绑定层),有了这一层,使用者并不关心具体的消息中间件配置了,由访问层真正的和消息队列进行通信。
代码Git地址:https://gitee.com/hankin_chj/springcloud-micro-service.git
1、创建消息生产者
创建一个新的模块springcloud-micro-stream-provider,这模块负责生产一个消息
1.1、pom文件如下,映入springcloudstream的相关组件
<dependencies>
<dependency>
<groupId>com.chj</groupId>
<artifactId>springcloud-micro-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
</dependencies>
1.2、修改application.yml文件
server:
port: 8401
spring:
application:
name: springcloud-micro-stream-provider
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
1.3、stream-provider定义一个消息发送接口
public interface IMessageProvider {
void send(Product product);
}
stream-provider定义接口的实现类:
package com.chj.service.impl;
import com.chj.service.IMessageProvider;
import com.chj.vo.Product;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import javax.annotation.Resource;
@EnableBinding(Source.class)
public class MessageProviderImpl implements IMessageProvider {
@Resource
private MessageChannel output; // 消息的发送管道
@Override
public void send(Product product) {
output.send(MessageBuilder.withPayload(product).build());
}
}
1.4、stream-provider定义启动类主程序
@SpringBootApplication
public class StreamProviderApp {
public static void main(String[] args) {
SpringApplication.run(StreamProviderApp.class,args);
}
}
1.5、stream-provider编写测试类
@SpringBootTest(classes = StreamProviderApp.class)
@RunWith(SpringRunner.class)
public class TestMessageProvider {
@Resource
private IMessageProvider messageProvider;
@Test
public void testSend() {
Product product = new Product();
product.setProductId(1L);
product.setProductName("messageName");
product.setProductDesc("test springcloud stream message");
messageProvider.send(product);
}
}
1.5、运行测试方法
查看RabbitMQ控制台:http://localhost:15672/,已经产生了个消息:
对于RabbitMQ来说,在这默认的Exchange的类型是Topic。
2、创建消息消费者
新建模块springcloud-micro-stream-consumer,作为消息的消费者。
2.1、修改pom文件如下
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>com.chj</groupId>
<artifactId>springcloud-micro-api</artifactId>
</dependency>
</dependencies>
2.2、修改application.yml配置文件
server:
port: 8402
spring:
application:
name: springcloud-micro-stream-consumer
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
2.3、定义一个消息的监听
@Component
@EnableBinding(Sink.class)
public class MessageListener {
@StreamListener(Sink.INPUT)
public void input(Message<Product> message) {
System.err.println("【*** 消息接收 ***】" + message.getPayload());
}
}
2.4、创建启动类
@SpringBootApplication
public class StreamConsumerApp {
public static void main(String[] args) {
SpringApplication.run(StreamConsumerApp.class,args);
}
}
启动后,发现rabbitmq里面已经有了一个消费者
stream-provider运行测试类,stream-consumer已经收到消息:
【rabbitmq】在消息队列中,也检测到了这匿名队列,可以发现Exchange默认的类型就是TOPIC,RoutingKey我们没有自定,默认的就是#,会给所有的消费者发消息。
3、自定义消息通道
前面在创建消息生产者的时候用到了@EnableBinding(Source.class)
在创建消息消费者的时候用到了@EnableBinding(Sink.class)
3.1、可以查看下Source.class与Sink.class的源码:
public interface Source {
String OUTPUT = "output";
@Output("output")
MessageChannel output();
}
public interface Sink {
String INPUT = "input";
@Input("input")
SubscribableChannel input();
}
其实这个input、output就是对应配置文件里面的内容,其实用户也是可以自定义管道信息的。
由于在tream-provider与stream-consumer这两个模块中都需要用到自定义管道信息,所以我们在系统api模块增加stream支持。
3.2、springcloud-micro-api修改pom文件,增加stream的支持
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
</dependencies>
3.3、api模块增加管道接口
public interface DefaultProcess {
public static final String OUTPUT = "hankin_output"; // 输出通道名称
public static final String INPUT = "hankin_input"; // 输入通道名称
@Input(DefaultProcess.INPUT)
public SubscribableChannel input();
@Output(DefaultProcess.OUTPUT)
public MessageChannel output();
}
3.4、stream-provider修改application.yml配置文件
server:
port: 8401
spring:
application:
name: springcloud-micro-stream-provider
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
hankin_output:
# output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
3.5、stream-consumer修改application.yml文件
spring:
application:
name: springcloud-micro-stream-consumer
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
hankin_input:
# input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
3.6、stream-provider修改MessageProviderImpl发送实现类
//@EnableBinding(Source.class)
@EnableBinding(DefaultProcess.class)
public class MessageProviderImpl implements IMessageProvider {
@Resource
@Qualifier("hankin_output") //TODO 用于查询注定名称注解对应 @Output(DefaultProcess.OUTPUT)
private MessageChannel output; // 消息的发送管道
@Override
public void send(Product product) {
output.send(MessageBuilder.withPayload(product).build());
}
}
3.7、stream-consumer修改MessageListener
@Component
//@EnableBinding(Sink.class)
@EnableBinding(DefaultProcess.class)
public class MessageListener {
// @StreamListener(Sink.INPUT)
@StreamListener(DefaultProcess.INPUT) //TODO 用于查询注定名称注解对应 @Input(DefaultProcess.INPUT)
public void input(Message<Product> message) {
System.err.println("【*** 消息接收 ***】" + message.getPayload());
}
}
修改之后就可以用自定义管道了。
3.8、分别启动服务消费者和提供者
测试发小消息成功后,查看MQ管理平台多了我们自定义的管道名字,实际对应的就是exchange。
4、分组(队列)
Group分组其实就是对应rabbitmq里面得队列,在前面的案例中,我们并没有指定group,产生的就是一个匿名队列。如果启动了多个stream-consumer接收者,但并没有指定group,那么将会产生多个匿名的消息队列,导致多个接收者都会收到同一个消息,也就是说一个消息被重复消费了,这在某些业务场景来说是并不运行的。
这个时候就需要用到group分组了,对于不想重复消费个某消息的各个消费者必须属于同一个组。
4.1、stream-consumer修改application.yml
server:
port: 8402
spring:
application:
name: springcloud-micro-stream-consumer
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
hankin_input:
# input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
group: hankin_group
4.2、启动了多个stream-consumer接收者
由于指定了group,在rabbitmq也就只会产生一个队列。
这个时候服务生产者stream-provider发送的任何消息都只会被同一个group的某一个消费者处理了。
5、设置RoutingKey
RoutingKey其实是RabbitMQ的概念,在RabbitMQ里面其实有好几种Exchange,在SpringCloudStream里面默认就是使用的最通用的Topic。如果没有配置RoutingKey,它使用的RoutingKey其实就是#,既类似于fanout的广播类型,其实也可以使用RoutingKey来实现类似于direct类型,也就是直连方式。
5.1、stream-consumer修改application.yml配置文件
server:
port: 8402
spring:
application:
name: springcloud-micro-stream-consumer
cloud:
stream:
rabbit:
bindings:
hankin_input:
consumer:
bindingRoutingKey: hankinKey # 设置一个RoutingKey信息
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
hankin_input:
# input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
group: hankin_group
5.2、stream-provider定义RoutingKey的表达式配置
server:
port: 8401
spring:
application:
name: springcloud-micro-stream-provider
cloud:
stream:
rabbit:
bindings:
hankin_output:
producer:
routingKeyExpression: '''hankinKey'''
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
addresses: localhost
port: 5672
username: admin
password: admin
virtual-host: /
bindings: # 服务的整合处理
hankin_output:
# output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
destination: HnakinExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
5.3、运行服务测试
二、SpringCloudSleuth链路跟踪
在微服务的架构下,系统由大量服务组成,每个服务可能是由不同的团队开发,开发使用不同的语言,部署在几千台服务器上,并且横跨多个不同的数据中心,一次请求绝大多数情况会涉及多个服务,在系统发生故障的时候,想要快速定位和解决问题,就需要跟踪服务请求序列。
SpringCloudSleuth使用的核心组件是Twitter推出的Zipkin监控组件,zipkin就是一个分布式的跟踪系统,用户收集服务的数据。
1、基本使用
1.1、新建跟踪服务
新建立模块springcloud-micro-sleuth,这个模块用户跟踪用户的请求,把请求的链路进行展示
Pom依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
1.2、修改application.yml文件
server:
port: 8601
spring:
application:
name: springcloud-micro-sleuth
management:
metrics:
web:
server:
auto-time-requests: false
1.3、新建启动类@EnableZipkinServer
@SpringBootApplication
@EnableZipkinServer
public class SleuthApp {
public static void main(String[] args) {
SpringApplication.run(SleuthApp.class,args);
}
}
2、客户端配置
为了演示链路追踪,需要启动一些列服务:eureka、user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix等服务。下图为显示的最终结果:
启动eureka这个服务的目的是让product、users两服务注册到其中,后面需要zuul的调用。
2.1、修改以下服务的pom文件,增加sleuth的支持
需要修改的服务:user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix
<!-- springcloud sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
偶尔有可能下载不到,如果不行,用下面这个:
<!-- springcloud sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
2.2、修改以下服务的application.yml文件,增加zipkin的配置
需要修改的服务:user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix
spring:
zipkin: # 添加springcloud链路追踪sleuth
base-url: http://localhost:8601 #所有的数据提交到此服务之中
sender:
type: web #提交的类型是web 服务
sleuth:
sampler:
probability: 1.0 # 定义抽样比率,默认为0.1
2.3、依次启动服务测试
需要依次启动:eureka、user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix
首先访问接口:http://localhost/consumer/product/getProductAndUser?id=1
访问跟踪服务:http://localhost:8601/zipkin/dependency/
结果如下如所示:
3、数据持久化
现在以及成功实现了一个 SpringCloudSleuth 的基本操作,但会发现,如果重新启动sleuth服务,所有的链路跟踪数据都会丢失,那么这些数据应该存储到数据库里面的。但又有另外一个问题,如果请并发量特别大,对于mysql来说可能会承受不了这么大的并发,为了解决这个问题,可以使用消息队列缓冲处理,最后才从mq中把数据存到mysql中。
3.1、先在数据库里面创建zipkin的表
DROP DATABASE IF EXISTS zipkin ;
CREATE DATABASE zipkin CHARACTER SET UTF8 ;
USE zipkin ;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for zipkin_annotations
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_annotations`;
CREATE TABLE `zipkin_annotations` (
`trace_id_high` bigint(20) NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
`span_id` bigint(20) NOT NULL COMMENT 'coincides with zipkin_spans.id',
`a_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
`a_value` blob NULL COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
`a_type` int(11) NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
`a_timestamp` bigint(20) NULL DEFAULT NULL COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` int(11) NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` binary(16) NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` smallint(6) NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
UNIQUE INDEX `trace_id_high`(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) USING BTREE COMMENT 'Ignore insert on duplicate',
INDEX `trace_id_high_2`(`trace_id_high`, `trace_id`, `span_id`) USING BTREE COMMENT 'for joining with zipkin_spans',
INDEX `trace_id_high_3`(`trace_id_high`, `trace_id`) USING BTREE COMMENT 'for getTraces/ByIds',
INDEX `endpoint_service_name`(`endpoint_service_name`) USING BTREE COMMENT 'for getTraces and getServiceNames',
INDEX `a_type`(`a_type`) USING BTREE COMMENT 'for getTraces and autocomplete values',
INDEX `a_key`(`a_key`) USING BTREE COMMENT 'for getTraces and autocomplete values',
INDEX `trace_id`(`trace_id`, `span_id`, `a_key`) USING BTREE COMMENT 'for dependencies job'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compressed;
-- ----------------------------
-- Table structure for zipkin_dependencies
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_dependencies`;
CREATE TABLE `zipkin_dependencies` (
`day` date NOT NULL,
`parent` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`child` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`call_count` bigint(20) NULL DEFAULT NULL,
`error_count` bigint(20) NULL DEFAULT NULL,
UNIQUE INDEX `day`(`day`, `parent`, `child`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compressed;
-- ----------------------------
-- Table structure for zipkin_spans
-- ----------------------------
DROP TABLE IF EXISTS `zipkin_spans`;
CREATE TABLE `zipkin_spans` (
`trace_id_high` bigint(20) NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` bigint(20) NOT NULL,
`id` bigint(20) NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`parent_id` bigint(20) NULL DEFAULT NULL,
`debug` bit(1) NULL DEFAULT NULL,
`start_ts` bigint(20) NULL DEFAULT NULL COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
`duration` bigint(20) NULL DEFAULT NULL COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
UNIQUE INDEX `trace_id_high`(`trace_id_high`, `trace_id`, `id`) USING BTREE COMMENT 'ignore insert on duplicate',
INDEX `trace_id_high_2`(`trace_id_high`, `trace_id`, `id`) USING BTREE COMMENT 'for joining with zipkin_annotations',
INDEX `trace_id_high_3`(`trace_id_high`, `trace_id`) USING BTREE COMMENT 'for getTracesByIds',
INDEX `name`(`name`) USING BTREE COMMENT 'for getTraces and getSpanNames',
INDEX `start_ts`(`start_ts`) USING BTREE COMMENT 'for getTraces ordering and range'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compressed;
SET FOREIGN_KEY_CHECKS = 1;
3.2、sleuth服务修改pom文件
springcloud-micro-sleuth服务修改pom文件,增加数据库,消息队列相关的依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.9.4</version>
</dependency>
<!-- 链路数据持久化支持 -->
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-collector-rabbitmq</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
3.3、sleuth服务修改application.yml文件
server:
port: 8601
spring:
application:
name: springcloud-micro-sleuth
management:
metrics:
web:
server:
auto-time-requests: false
# 链路追踪数据持久化配置
zipkin:
collector:
sample-rate: 1.0
http:
enabled: false
rabbitmq:
addresses: localhost:5672
username: admin
password: admin
queue: zipkin
virtual-host: /
storage:
type: mysql
mysql:
host: localhost
port: 3306
username: root
password: root
db: zipkin
3.4、其他服务增加RabbitMQ相关依赖
确认客户方都有rabbitmq的依赖,修改pom文件,增加相关依赖,主要涉及链路追踪的服务有:
user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix
<!-- springcloud sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
3.5、相关application.yml文件修改zipkin的配置
修改以下服务的application.yml文件,修改zipkin的配置type改为rabbit,主要涉及链路追踪的服务有:
user-hystrix、product-hystrix、zuul-gateway、consumer-feign-hystrix
spring:
zipkin: # 添加springcloud链路追踪sleuth
base-url: http://localhost:8601 #所有的数据提交到此服务之中
sender:
type: RABBIT #提交的类型是web 服务
sleuth:
sampler:
probability: 1.0 # 定义抽样比率,默认为0.1
3.6、依次启动测试
需要依次启动的服务:
springcloud-micro-eureka
springcloud-micro-product-hystrix
springcloud-micro-user-hystrix
springcloud-micro-zuul-gateway
springcloud-micro-consumer-feign-hystrix
然后访问:http://localhost/consumer/product/getProductAndUser?id=1
查看链路追踪以来分析如下所示:http://localhost:8601/zipkin/
http://localhost:15672/#/queues/%2F/zipkin,数据一节通过rabbitmq传输,并且数据已经到了数据库
具体配置参考:
https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml
三、Springcloud admin
1、Maven依赖
Springcloud admin是基于spring-boot-starter-actuator实现的:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
把actuator负责统计数据,admin是根据统计出来的数据来进行展示的,可以很好的监控整个微服务系统中的实例运行情况信息。
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
<version>LATEST</version>
</dependency>
2、启动类加注解
@SpringBootApplication
@EnableEurekaClient
@EnableAdminServer
public class MicroAdminApplication {
public static void main(String[] args) {
SpringApplication.run(MicroAdminApplication.class,args);
}
}
3、安全配置
application.properties配置信息如下:
spring.application.name=springcloud-micro-admin
server.port=8282
#是否注册到eureka
eureka.client.registerWithEureka=true
#是否从eureka中拉取注册信息
eureka.client.fetchRegistry=true
eureka.client.serviceUrl.defaultZone: http://admin:admin@eureka1:7001/eureka,http://admin:admin@eureka2:7002/eureka,http://admin:admin@eureka3:7003/eureka
# 安全配置
spring.security.user.name=admin
spring.security.user.password=admin
eureka.instance.metadata-map.user.name=${spring.security.user.name}
eureka.instance.metadata-map.user.password=${spring.security.user.password}
展示效果如下: