網關配置文件的講解
route組成部分
id:路由的ID
uri:匹配路由的轉發地址
- predicates:配置該路由的斷言,通過PredicateDefinition類進行接收配置。
轉發的判斷條件,SpringCloud Gateway支持多種方式,常見如:Path、Query、Method、Header等
predicates:
- Host=
- Path=
- Method=
- Header=
- Query=
- Cookie=
- Before=2020-09-09T01:01:01.000+08:00 #可以在這個時間之間訪問
order:路由的優先級,數字越小,優先級越高。
- filters: 過濾器
比如一開始的
filters: #過濾器,請求在傳遞過程中通過過濾器修改
- StripPrefix=1 #去掉第一層前綴
過濾器分爲
局部過濾器GatewayFilter:應用在某個路由上,每個過濾器工廠都對應一個實現類,並且這些類的名稱必須以 GatewayFilterFactory 結尾
全局過濾器:作用全部路由上,比如在網關模塊創建一個全局過濾器,用於進行身份驗證
@Component
public class UserGlobalFilter implements GlobalFilter,Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("token");
System.out.println(token);
if(StringUtils.isBlank(token)){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//繼續往下執行
return chain.filter(exchange);
}
//數字越小,優先級越高
@Override
public int getOrder() {
return 0;
}
}
網關不要加太多業務邏輯,否則會影響性能
交互過程
- 客戶端向Spring Cloud Gateway發出請求
- 如果網關處理程序映射確定請求與路由匹配
- 則將其發送到網關Web處理程序
- 通過特定過濾器鏈運行,前置處理-後置處理
order就是定義過濾器的級別的
鏈路追蹤問題
在微服務的各個服務之間的調用的時候,如何確定調用鏈路出現了問題怎麼快速排查,鏈路耗時長怎麼定位是哪個服務,傳統的監控工具並無法滿足,分佈式鏈路系統由此誕生。
將一次請求分佈式調用,使用GPS定位串起來,記錄每個調用的耗時、性能等日誌,並通過可視化工具展示出來,我們是用Sleuth和zipking
Sleuth組件
一個組件,專門用於記錄鏈路數據的開源組件
- 在每個服務添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
這個組件是爲了記錄一下鏈路信息的
2. 使用zipkin來可視化
下載jar包,然後啓動
java -jar zipkin-server-2.12.9-exec.jar
zipkin組成:Collector、Storage、Restful API、Web UI組成
sleuth收集跟蹤信息通過http請求發送給zipkin server
zipkin server進行跟蹤信息的存儲以及提供Rest API即可
Zipkin UI調用其API接口進行數據展示默認存儲是內存,可也用mysql 或者elasticsearch等存儲
3. 微服務加入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
4.填寫配置
spring:
application:
name: api-gateway
zipkin:
base-url: http://vm02:9411/ #zipkin地址
discovery-client-enabled: false #不用開啓服務發現
sleuth:
sampler:
probability: 1.0 #採樣百分比
默認爲0.1,即10%,這裏配置1,是記錄全部的sleuth信息,是爲了收集到更多的數據(僅供測試用)。
在分佈式系統中,過於頻繁的採樣會影響系統性能,所以這裏配置需要採用一個合適的值。
- 然後重新啓動服務,接着,在Zipkin的網頁查看
後端idea也有相應的鏈路顯示
第一個值,spring.application.name的值
第二個值,96f95a0dd81fe3ab ,sleuth生成的一個ID,叫Trace ID,用來標識一條請求鏈路,一條請求鏈路中包含一個Trace ID,多個Span ID
第三個值,852ef4cfcdecabf3、spanid 基本的工作單元,獲取元數據,如發送一個http
第四個值:false,是否要將該信息輸出到zipkin服務中來收集和展示。
但是現在的鏈路信息,當服務重啓之後,就會丟失掉,現在進行把信息持久化到mysql
在mysql創建表
CREATE TABLE IF NOT EXISTS zipkin_spans (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL,
`id` BIGINT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`remote_service_name` VARCHAR(255),
`parent_id` BIGINT,
`debug` BIT(1),
`start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
`duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';
CREATE TABLE IF NOT EXISTS zipkin_annotations (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
`span_id` BIGINT 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 NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
`a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';
CREATE TABLE IF NOT EXISTS zipkin_dependencies (
`day` DATE NOT NULL,
`parent` VARCHAR(255) NOT NULL,
`child` VARCHAR(255) NOT NULL,
`call_count` BIGINT,
`error_count` BIGINT,
PRIMARY KEY (`day`, `parent`, `child`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
用下面命令重新啓動
java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin_log --MYSQL_USER=root --MYSQL_PASS=xdclass.net