# springcloud_demo
**Repository Path**: liu_fei_4552/springcloud_demo
## Basic Information
- **Project Name**: springcloud_demo
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-08-30
- **Last Updated**: 2021-09-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 学习springcloud所搭建
## eureka显示注册ip
##### 在服务提供者,通过instance.instance-id配置控制台显示服务ip
## eureka服务剔除问题
##### 默认每隔30秒发送一次心跳,如果90秒内没有发送心跳就认为宕机,在服务的提供者设置心跳间隔,设置续约到期时间
## eureka的自我保护机制(统计宕机服务超过百分之八十五就会自动启用自我保护,不再提出服务)
```yaml
server:
enable-self-preservation: false #关闭自我保护机制
eviction-interval-timer-in-ms: 4000 #设置提出服务间隔
```
### 上面参数只是建议开发时使用,生产保持默认值就好
#### Ribbon 就是一个负载均衡器,有助于控制HTTP和TCP客户端行为。在SpringCloud中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。
#### 1. 服务调用 :基于Ribbon实现服务调用,是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助RestTemplate最终进行调用
#### 2. 负载均衡(服务端的负载均衡:nginx f5;客户端的负载均衡:Ribbon是一个典型的客户端负载均衡器,Ribbon会获取服务的所有地址,根据内部的负载均衡算法获取本次请求的有效地址)
* com.netflix.loadbalancer.RoundRobinRule :以轮询的方式进行负载均衡。
* com.netflix.loadbalancer.RandomRule :随机策略
* com.netflix.loadbalancer.RetryRule :重试策略。
* com.netflix.loadbalancer.WeightedResponseTimeRule :权重策略。会计算每个服务的权
重,越高的被调用的可能性越大。
* com.netflix.loadbalancer.BestAvailableRule :最佳策略。遍历所有的服务实例,过滤掉
故障实例,并返回请求数最小的实例返回。
* com.netflix.loadbalancer.AvailabilityFilteringRule :可用过滤策略。过滤掉故障和请
求数超过阈值的服务实例,再从剩下的实力中轮询调用。
```yaml
service-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
```
### 重试机制
```xml
org.springframework.retry
spring-retry
```
```yaml
service-product:
ribbon:
#重试配置
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
```
## consul注册中心
#### 1.强一致性(cp)
#### 2.eureka 最终一致性(ap)
### 安装consul
#### 1.下载安装就好了 [consul下载地址](https://www.consul.io/downloads)
#### 2.进入开发者模式快速启动
```shell
##以开发者模式快速启动
consul agent -dev -client=0.0.0.0
```
#### 3.进入到管理后台界面 http://localhost:8500
### 将微服务注册到注册中心consul
#### 1.添加依赖
```xml
org.springframework.cloud
spring-cloud-starter-consul-discovery
org.springframework.boot
spring-boot-starter-actuator
```
#### 2.yml配置
```yaml
cloud:
consul:
host: 127.0.0.1 #主机地址
port: 8500 #端口
discovery:
register: true #是否需要注册
#注册的实例id(唯一标识)
instance-id: ${spring.application.name}-1
#服务名称
service-name: ${spring.application.name}
#服务请求端口
port: ${server.port}
#指定开启ip地址注册
prefer-ip-address: true
#当前服务的请求ip
ip-address: ${spring.cloud.client.ip-address}
```
##### 特别注意在服务起名字时如果使用下划线调用时不通过,可以使用中划线
### 将微服务注册到注册中心consul
##### 由于SpringCloud对Consul进行了封装。对于在消费者端获取服务提供者信息和Eureka是一致的。同样使用 DiscoveryClient 完成调用获取微服务实例信息
## consul集群
#### [集群搭建](https://www.bilibili.com/video/BV1eE41187Ug?p=40&spm_id_from=pageDriver)
## Feign组件
#### 1.导入依赖
```xml
org.springframework.cloud
spring-cloud-starter-openfeign
```
#### 2.配置调用接口
```java
/**
* @ClassNameProductFeignClient
* @Description 声明需要调用的微服务名称
* @Author liufei
* @Date2021/9/1 14:47
* @Version V1.0
* @FeignClient
* name:服务提供者的名称
**/
@FeignClient(name = "service-product")
public interface ProductFeignClient {
/**
* 配置需要调用的微服务接口
*/
@RequestMapping(value = "/product/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable("id") Long id);
}
```
#### 3.在启动类上激活feign
```java
@SpringBootApplication
@EntityScan("com.java.entity")
@EnableEurekaClient
@EnableFeignClients
public class OrderApplication {}
```
#### 4.通过自动的接口调用远程微服务
```java
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
//注入restTemplate对象
@Autowired
private RestTemplate restTemplate;
/**
* 注入DiscoveryClient :
* springcloud提供的获取原数组的工具类
* 调用方法获取服务的元数据信息
*
*/
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private ProductFeignClient productFeignClient;
@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
Product product = null;
product =productFeignClient.findById(id);
return product;
}
}
```
### 5.打印feign日志
```yaml
#配置feign日志的输出
#日志配置:
#NONE :不输出日志
#BASIC :适用于生产环境追踪问题
#HEADERS :在BASIC的基础上,记录请求头和响应头信息
#FULL :记录所有
feign:
client:
config:
service-product:
loggerLevel: FULL
logging:
level:
com.java.feign.ProductFeignClient: debug
```
## Hystrix组件
#### 1.对Feign的支持 引入依赖,因为feign中已经包含所以不需要另外增加依赖
#### 2.在fenign的配置文件中开启hystrix
```yaml
feign:
client:
config:
service-product:
loggerLevel: FULL
hystrix:
enabled: true
```
#### 3.自定义一个接口实现类,这个实现类就是熔断触发的降级逻辑
```java
/**
* @ClassNameProductFeignClientCallBack
* @Description
* @Author liufei
* @Date2021/9/1 18:04
* @Version V1.0
**/
@Component
public class ProductFeignClientCallBack implements ProductFeignClient{
/**
*
*熔断降级的方法
* @param id
*/
@Override
public Product findById(Long id) {
Product product=new Product();
product.setProductName("触发降级方法");
return product;
}
}
```
#### 4.修改feginClient接口添加降级方法的支持
```java
@FeignClient(name = "service-product",fallback = ProductFeignClientCallBack.class)
public interface ProductFeignClient {}
```
#### 5.hystrix的超时时间 当在规定的时间内,没有获取到微服务的数据,这个时候会自动的触发熔断降级方法
```yaml
hystrix:
command:
default:
excution:
isolation:
thread:
timeoutInMilliseconds: 3000 #默认的连接超时时间为1秒
```
#### 6.hystrix监控
#### * 添加坐标
```xml
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.cloud
spring-cloud-starter-netflix-hystrix-dashboard
```
#### * 在启动类上激活hystrix
```java
//激活hystrix
@EnableHystrix
```
#### * 增加配置
```yaml
#hystrix监控所需
management:
endpoints:
web:
exposure:
include: '*'
```
#### * 页面上访问 http://localhost:9002/actuator/hystrix.stream
#### * 监控地址为 http://localhost:9002/hystrix
### turbine监控系统可以监控所有的想监控的服务
#### * 生产上使用单独的监控服务 监控地址http://localhost:8031/turbine.stream 页面访问地址为 http://localhost:8031/hystrix
## Sentinel组件
#### * Sentinel控制台下载安装 [官网地址](https://github.com/alibaba/Sentinel/releases)
#### * 启动命令
```shell script
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.6.3.jar
```
#### * 启动之后的访问地址为 http://localhost:8080 默认账号和密码都是 sentinel
#### * 父pom中增加依赖
```yaml
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.1.0.RELEASE
pom
import
```
#### * 在需要的项目中增加依赖
```yaml
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
```
#### * 增加注解编写降级方法
```java
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Autowired
private ProductFeignClient productFeignClient;
@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
/**
*@SentinelResource(blockHandler = "orderBlockHandler",fallback = "orderFallback")
* blockHandler 熔断执行的方法
* fallback 异常执行的方法
* value 资源名称 不设置就是类名加方法名
*/
@SentinelResource(value ="orderBuyId",blockHandler = "orderBlockHandler",fallback = "orderFallback")
public Product findById(@PathVariable Long id) {
if(id != 1){
throw new RuntimeException("错误");
}
Product product = null;
product =productFeignClient.findById(id);
return product;
}
/**
* 定义降级逻辑
* hystrix和sentinel区别
* hystrix只有一个方法
* sentinel熔断执行熔断的方法、抛出异常执行异常的方法
* @param id
* @return
*/
public Product orderBlockHandler(Long id){
Product product=new Product();
product.setProductName("触发熔断的降级方法");
return product;
}
public Product orderFallback(Long id){
Product product=new Product();
product.setProductName("触发抛出异常的方法");
return product;
}
}
```
#### * 加在本地配置规则source下面增加一个json,yml中增加配置
```yaml
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource: #因为sentinel读取内存中的数据每次项目重启就会导致配置消失,我们可以读取本地资源配置
ds1:
file:
file: classpath:flowrule.json
data-type: json
rule-type: flow
```
## Sentinel对feign支持
#### 1.引入依赖
```yaml
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
```
#### 1.在yml上打开sentinel 其他的和hystrix一样
```yaml
#激活sentinel的支持
feign:
sentinel:
enabled: true
```
## 微服务网关,主要解决客户端需要记录各个微服务的ip地址及出现跨域及各个微服务独立认证登录信息等情况(身份验证、监控、缓存、负载均衡、请求分片、静态响应)
### zuul网关
#### 创建zuul网关服务
#### 增加坐标
```xml
org.springframework.cloud
spring-cloud-starter-netflix-zuul
```
#### 增加配置
```yaml
server:
port: 8080 #端口
spring:
application:
name: api-zuul-server #服务名称
```
#### 开启zull注解
```java
@SpringBootApplication
//开启zuul网关功能
@EnableZuulProxy
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class,args);
}
}
```
#### 路由:根据请求的url将请求分配到对应的微服务中进行处理
```yaml
# 路由配置
zuul:
routes:
#商品微服务
product-server: #路由id,随便写
path: /product-service/** #localhost:8080/product-service/*****
url: http://127.0.0.1:9011 #映射路径实际对应的微服务
```
#### 集成eureka
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
```
```yaml
# 路由配置
zuul:
routes:
#商品微服务
product-server: #路由id,随便写
path: /product-service/** #localhost:8080/product-service/*****
#url: http://127.0.0.1:9011 #映射路径实际对应的微服务
serviceId: service-product #配置转发的微服务的服务名称
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
```
#### 简化路由配置
```yaml
# 路由配置
zuul:
routes:
#商品微服务
#product-server: #路由id,随便写
#path: /product-service/** #localhost:8080/product-service/*****
#serviceId: service-product #配置转发的微服务的服务名称
#如果路由id和对应的微服务的serviceId一致的话
service-product: /product-service/**
```
#### 路由如果当前的服务名称service-product,默认的请求映射路径 /service-product/**
#### zuul网关过滤器
* pre 转发到微服务之前执行的过滤器
* routing:在路由请求时执行的过滤器
* post:执行微服务获取返回值之后执行的过滤器
* error:在整个阶段抛出异常的时候执行的过滤器
#### 自定义过滤器
```java
/**
* @ClassNameLoginFilter
* @Description 自定义zuul过滤器
* @Author liufei
* @Date2021/9/3 11:42
* @Version V1.0
**/
@Component
public class LoginFilter extends ZuulFilter {
/**
* 定义过滤器类型
* pre
* routing
* post
* error
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 指定过滤器的执行顺序
* 返回值越小,执行顺序越高
* @return
*/
@Override
public int filterOrder() {
return 1;
}
/**
* 过滤器是否生效
* true:使用此过滤器
* false:不使用此过滤器
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 执行过滤器的业务逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
System.out.println("执行了过滤器");
return null;
}
}
```
#### zuul网关的不足
1.同步servlet的形式就是一个请求一个线程去执行完才会释放,如果请求量过大就会导致线程阻塞。(同步阻塞式网关)
2.zuul网关不支持websocket
## Springcloud Gateway网关
#### 路由配置
1. 创建工程导入坐标(注意gateway和startweb冲突所以要摒弃web才能启动成功)
```xml
org.springframework.cloud
spring-cloud-starter-gateway
```
2. 编写启动类
```java
@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class,args);
}
}
```
3. 编写yaml
```yaml
server:
port: 8080 #端口
spring:
application:
name: api-gateway-server #服务名称
#配置springcloudgateway的路由
cloud:
gateway:
routes:
#配置路由 :路由id,路由到微服务的uri,断言(判断条件)
- id: service-product
uri: http://127.0.0.1:9011
predicates:
- Path=/product/**
```
4. 路由规则
```yaml
#路由断言之后匹配
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://xxxx.com
#路由断言之前匹配
predicates:
- After=xxxxx
#路由断言之前匹配
spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://xxxxxx.com
predicates:
- Before=xxxxxxx
#路由断言之间
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://xxxx.com
predicates:
- Between=xxxx,xxxx
#路由断言Cookie匹配,此predicate匹配给定名称(chocolate)和正则表达式(ch.p)
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://xxxx.com
predicates:
- Cookie=chocolate, ch.p
#路由断言Header匹配,header名称匹配X-Request-Id,且正则表达式匹配\d+
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://xxxx.com
predicates:
- Header=X-Request-Id, \d+
#路由断言匹配Host匹配,匹配下面Host主机列表,**代表可变参数
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://xxxx.com
predicates:
- Host=**.somehost.org,**.anotherhost.org
#路由断言Method匹配,匹配的是请求的HTTP方法
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://xxxx.com
predicates:
- Method=GET
#路由断言匹配,{segment}为可变参数
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://xxxx.com
predicates:
- Path=/foo/{segment},/bar/{segment}
#路由断言Query匹配,将请求的参数param(baz)进行匹配,也可以进行regexp正则表达式匹配 (参数包含
foo,并且foo的值匹配ba.)
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://xxxx.com
predicates:
- Query=baz 或 Query=foo,ba.
#路由断言RemoteAddr匹配,将匹配192.168.1.1~192.168.1.254之间的ip地址,其中24为子网掩码位
数即255.255.255.0
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/2
```
5.动态路由
```yaml
server:
port: 8080 #端口
spring:
application:
name: api-gateway-server #服务名称
#配置springcloudgateway的路由
cloud:
gateway:
routes:
#配置路由 :路由id,路由到微服务的uri,断言(判断条件)
- id: service-product
#uri: http://127.0.0.1:9011
uri: lb://service-product #lb://根据微服务名称从注册中心拉取服务请求路径
predicates:
- Path=/product/**
```
6.开启微服务名称的转发
```yaml
#配置自动的根据微服务名称进行路由转发
discovery:
locator:
enabled: true #开启根据服务名称自动转发
lower-case-service-id: true #微服务名称以小写形式呈现
```
#### 过滤器
1. springcloud Gateway 的filter的生命周期不想zuul的那么丰富,它只有:"pre"和"post"
2. pre 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
3. post 这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的http head、收集统计信息和指标、将响应从微服务发送给客户端等。
#### 统一鉴权
```java
@Component
public class LoginFilter implements GlobalFilter, Ordered {
/**
* 执行过滤器中的业务逻辑
* 对请求参数中的access-token进行认证
* 如果存在此参数:代表已经认证成功
* 如果不存在此参数:认证失败
* ServerWebExchange:相当于请求和响应的上下文(zuul中的RequestContext)
* @param exchange
* @param chain
* @return
*/
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("执行了自定义的全局过滤器");
//获取请求参数access-token
String token = exchange.getRequest().getQueryParams().getFirst("access-token");
//判断
if(StringUtils.isEmpty(token)){
System.out.println("没有登录");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//请求结束
return exchange.getResponse().setComplete();
}
//如果存在继续执行
return chain.filter(exchange);
}
/**
* 指定过滤器的执行顺序,返回值越小执行优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
```
#### 网关限流
1. 计数器算法
2. 漏桶算法
3. 令牌桶算法
#### 网关实现方式
1. 基于Filter的限流(基于redis)
* 准备redis
* 在工程中引入redis的相应依赖
```xml
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-starter-data-redis-reactive
```
* 修改网关中的application.yml配置
```yaml
server:
port: 8080 #端口
spring:
application:
name: api-gateway-server #服务名称
redis:
host: localhost
pool: 6379
database: 0
#配置springcloudgateway的路由
cloud:
gateway:
routes:
#配置路由 :路由id,路由到微服务的uri,断言(判断条件)
- id: service-product
#uri: http://127.0.0.1:9011
uri: lb://service-product #lb://根据微服务名称从注册中心拉取服务请求路径
predicates:
#- Path=/product/**
- Path=/product-service/** #将当前的请求转发到 http://127.0.0.1:9011/product/1
filters:
#使用限流过滤器,是springcloud gataway提供
- name: RequestRateLimiter
args:
key-resolver: '#{@pathKeyResolver}'
redis-rate-limiter.replenishRate: 1 #向令牌桶中填充的速率
redis-rate-limiter-bursCapacity: 3 # 令牌桶的容量
- RewritePath=/product-service/(?.*),/$\{segment} #路径重写的过滤器,yml中$写为$\
#配置自动的根据微服务名称进行路由转发
discovery:
locator:
enabled: true #开启根据服务名称自动转发
lower-case-service-id: true #微服务名称以小写形式呈现
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
```
* 配置redis中key的解析器KeySesolver
```java
@Configuration
public class KeyResolverConfiguration {
/**
* 编写基于请求路径的限流规则
* 基于ip
* 基于参数
*/
@Bean
public KeyResolver pathKeyResolver(){
//自定义的keyResolver
return new KeyResolver() {
@Override
/**
* ServerWebExchange
* 上下文参数
*/
public Mono resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getPath().toString());
}
};
}
}
```
2. 基于Sentinel的限流
#### 网关的高可用 使用Nginx做高可用
## 链路追踪
#### seluth入门
1. 导入坐标
```xml
org.springframework.cloud
spring-cloud-starter-sleuth
```
2. 增加yaml配置
```yaml
logging:
level:
root: INFO
com.java.feign.ProductFeignClient: debug
org.springframework.web.servlet.DispatcherServlet: DEBUG
org.springframework.cloud.sleuth: DEBUG
```
#### zipkin
1. zipkin server [zipkin官网](https://zipkin.io/)
2. 添加zipkin依赖
```xml
org.springframework.cloud
spring-cloud-starter-zipkin
```
3.增加配置yaml
````yaml
spring:
zipkin:
base-url: http://127.0.0.1:9411/
sender:
type: web #数据的传输方式,以http的形式向server发送数据
sleuth:
sampler:
probability: 1 #采样比
````
4.数据持久化 启动服务命令为
创建数据库为zipkin
表为
````sql
/*
SQLyog Ultimate v11.33 (64 bit)
MySQL - 5.5.58 : Database - zipkin
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`zipkin` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `zipkin`;
/*Table structure for table `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) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
`a_value` blob 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) DEFAULT NULL COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` int(11) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` binary(16) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` smallint(6) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` varchar(255) DEFAULT NULL COMMENT 'Null when Binary/Annotation.endpoint is null',
UNIQUE KEY `trace_id_high` (`trace_id_high`,`trace_id`,`span_id`,`a_key`,`a_timestamp`) COMMENT 'Ignore insert on duplicate',
KEY `trace_id_high_2` (`trace_id_high`,`trace_id`,`span_id`) COMMENT 'for joining with zipkin_spans',
KEY `trace_id_high_3` (`trace_id_high`,`trace_id`) COMMENT 'for getTraces/ByIds',
KEY `endpoint_service_name` (`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames',
KEY `a_type` (`a_type`) COMMENT 'for getTraces',
KEY `a_key` (`a_key`) COMMENT 'for getTraces',
KEY `trace_id` (`trace_id`,`span_id`,`a_key`) COMMENT 'for dependencies job'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;
/*Data for the table `zipkin_annotations` */
/*Table structure for table `zipkin_dependencies` */
DROP TABLE IF EXISTS `zipkin_dependencies`;
CREATE TABLE `zipkin_dependencies` (
`day` date NOT NULL,
`parent` varchar(255) NOT NULL,
`child` varchar(255) NOT NULL,
`call_count` bigint(20) DEFAULT NULL,
UNIQUE KEY `day` (`day`,`parent`,`child`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;
/*Data for the table `zipkin_dependencies` */
/*Table structure for table `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) NOT NULL,
`parent_id` bigint(20) DEFAULT NULL,
`debug` bit(1) DEFAULT NULL,
`start_ts` bigint(20) DEFAULT NULL COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
`duration` bigint(20) DEFAULT NULL COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
UNIQUE KEY `trace_id_high` (`trace_id_high`,`trace_id`,`id`) COMMENT 'ignore insert on duplicate',
KEY `trace_id_high_2` (`trace_id_high`,`trace_id`,`id`) COMMENT 'for joining with zipkin_annotations',
KEY `trace_id_high_3` (`trace_id_high`,`trace_id`) COMMENT 'for getTracesByIds',
KEY `name` (`name`) COMMENT 'for getTraces and getSpanNames',
KEY `start_ts` (`start_ts`) COMMENT 'for getTraces ordering and range'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;
/*Data for the table `zipkin_spans` */
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
````
````shell script
java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin
````
5. 修改消息传输方式(使用消息中间件):
- 准备rabbitmq服务器
- 修改zipkin客户端将消息发送到中间件
- 修改zipkin服务端,从rabbit中拉取消息
## springcloud Stream(主要是封装消息中间件,如果需要切换只需要更改配置就好了)
## 配置中心
#### 常见的配置中心
1. springcloud config
2. Apollo
3. Disconf
#### springcloud config入门