文章目錄
目錄
文章目錄
前言
一、網(wǎng)關(guān)
1.1 gateway介紹
1.2 如何使用gateway?
1.3 網(wǎng)關(guān)優(yōu)化
1.4自定義斷言和過濾器
1.4.1 自定義斷言
二、Sleuth--鏈路追蹤
2.1 鏈路追蹤介紹
2.2 Sleuth介紹
2.3 使用
2.4?Zipkin的集成
?2.5 使用可視化zipkin來監(jiān)控微服務(wù)
總結(jié)
前言
一、網(wǎng)關(guān)
所謂的API網(wǎng)關(guān),就是指系統(tǒng)的統(tǒng)一入口,它封裝了應(yīng)用程序的內(nèi)部結(jié)構(gòu),為客戶端提供統(tǒng)一服 務(wù),一些與業(yè)務(wù)本身功能無關(guān)的公共邏輯可以在這里實(shí)現(xiàn),諸如認(rèn)證、鑒權(quán)、監(jiān)控(黑白名單)、路由轉(zhuǎn)發(fā)等等。
1.1 gateway介紹
Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等術(shù)開發(fā)的網(wǎng)關(guān),它旨在為微服務(wù)架構(gòu)提供一種簡單有效的==統(tǒng)一的 API 路由管理方式==。它的目標(biāo)是替代 Netflix Zuul,其不僅提供統(tǒng)一的路由方式,并且==基于 Filter 鏈的方式提供了網(wǎng)關(guān)基本的功能==,例如:安全,監(jiān)控和限流。
優(yōu)點(diǎn):
l 性能強(qiáng)勁:是第一代網(wǎng)關(guān)Zuul的1.6倍
l 功能強(qiáng)大:內(nèi)置了很多實(shí)用的功能,例如轉(zhuǎn)發(fā)、監(jiān)控、限流等
l 設(shè)計(jì)優(yōu)雅,容易擴(kuò)展.
缺點(diǎn):
l 其實(shí)現(xiàn)依賴Netty與WebFlux,不是傳統(tǒng)的Servlet編程模型,學(xué)習(xí)成本高
l 不能將其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包執(zhí)行 web.Jar
l 需要Spring Boot 2.0及以上的版本,才支持.
因?yàn)間ateway它內(nèi)置的服務(wù)器Netty,所以不能在使用Tomcat服務(wù)器。
1.2 如何使用gateway?
創(chuàng)建一個(gè)網(wǎng)關(guān)模塊,引入依賴
?<dependencies>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-gateway</artifactId>
? ? ? ? </dependency>
? ? </dependencies>
修改application.yml文件
server:
port: 7777
#配置路由
spring:
cloud:
gateway:
routes:
- id: my-product #路由的標(biāo)識,值唯一,默認(rèn)隨機(jī)產(chǎn)生一個(gè)唯一值
uri: http://localhost:8080 #它是網(wǎng)關(guān)真實(shí)轉(zhuǎn)發(fā)到的地址
order: 0 #路由的優(yōu)先級,值越小優(yōu)先級越高
predicates: #斷言: 它返回boolean值,如果返回的為true,則轉(zhuǎn)發(fā)到真實(shí)的地址 http://localhost:8080/product/getById/1
- Path=/product/**
- id: my-order
uri: http://localhost:8090
order: 0
predicates:
- Path=/order/**
?然后編寫一個(gè)springboot 啟動(dòng)類就能使用了
1.3 網(wǎng)關(guān)優(yōu)化
把網(wǎng)關(guān)也放入nacos注冊中心
<dependency>
? ? ? ? ? ? <groupId>com.alibaba.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
? ? ? ? </dependency>
?修改各個(gè)微服務(wù)之間的負(fù)載均衡
server:
port: 7777
#配置路由
spring:
cloud:
gateway:
routes:
- id: my-product #路由的標(biāo)識,值唯一,默認(rèn)隨機(jī)產(chǎn)生一個(gè)唯一值
uri: lb://my-product #它是網(wǎng)關(guān)真實(shí)轉(zhuǎn)發(fā)到的地址
order: 0 #路由的優(yōu)先級,值越小優(yōu)先級越高
predicates: #斷言: 它返回boolean值,如果返回的為true,則轉(zhuǎn)發(fā)到真實(shí)的地址 http://localhost:8080/product/getById/1
- Path=/product/**
- id: my-order
uri: lb://my-order #lb 基于ribbon的負(fù)載均衡 默認(rèn)輪詢
order: 0
predicates:
- Path=/order/**
簡約模式
?#開啟簡約模式
spring.cloud.gateway.discovery.locator.enabled=true
然后前端訪問的時(shí)候路徑上必須要加上服務(wù)的名稱
http://localhost:7777/my-order/order/get/1?
1.4自定義斷言和過濾器
1.4.1 自定義斷言
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
public static final String MIN = "min";
public static final String MAX = "max";
public AgeRoutePredicateFactory() {
super(AgeRoutePredicateFactory.Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
//讀取配置文件中的內(nèi)容
return Arrays.asList("min", "max");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return (t)->{
ServerHttpRequest request = t.getRequest();
String age = request.getHeaders().getFirst("age").toString();
if(StrUtil.isNotEmpty(age)&& NumberUtil.isInteger(age)){
int i = Integer.parseInt(age);
if(i>=config.getMin() &&i<=config.getMax()){
return true;
}
}
return false;
};
}
@Validated
public static class Config {
@NotNull
private Integer min;
@NotNull
private Integer max;
public Integer getMin() {
return min;
}
public void setMin(Integer min) {
this.min = min;
}
public Integer getMax() {
return max;
}
public void setMax(Integer max) {
this.max = max;
}
}
}
分析:添加年齡的斷言 需要在配置文件中使用
? ? ?predicates:
? ? ? ? ? ? - Path=/product/**
# ? ? ? ? ? ?- Header=X-Request-Id, \d+ 請求頭必須帶數(shù)字
? ? ? ? ? ? - Age=18,28 限制18到28的訪問自定義斷言的時(shí)候要寫成 xxxRoutePredicateFactory 然后使用就 -xxx
?網(wǎng)關(guān)過濾器
引入工具依賴
<dependency>
? ? ? ? ? ? <groupId>cn.hutool</groupId>
? ? ? ? ? ? <artifactId>hutool-all</artifactId>
? ? ? ? ? ? <version>5.8.12</version>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>com.alibaba</groupId>
? ? ? ? ? ? <artifactId>fastjson</artifactId>
? ? ? ? ? ? <version>1.2.83</version>
? ? ? ? </dependency>
@Component
public class LoginFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//哪些路徑允許放行
RequestPath path = request.getPath();
if("/login".equals(path)){
return chain.filter(exchange);
}
//獲取請求頭
String token = request.getHeaders().getFirst("token");
if(StrUtil.isNotEmpty(token)&&"admin".equals(token)){
return chain.filter(exchange);
}
//3.2封裝返回?cái)?shù)據(jù)
Map<String, Object> map = new HashMap<>();
map.put("msg", "未登錄");
map.put("code", "NOTLOGING");
//3.3作JSON轉(zhuǎn)換
byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8);
//3.4調(diào)用bufferFactory方法,生成DataBuffer對象
DataBuffer buffer = response.bufferFactory().wrap(bytes);
//4.調(diào)用Mono中的just方法,返回要寫給前端的JSON數(shù)據(jù)
return response.writeWith(Mono.just(buffer));
}
@Override
public int getOrder() {
return 0;
}
}
二、Sleuth--鏈路追蹤
2.1 鏈路追蹤介紹
在大型系統(tǒng)的微服務(wù)化構(gòu)建中,一個(gè)系統(tǒng)被拆分成了許多微服務(wù)。這些模塊負(fù)責(zé)不同的功能,組合成系統(tǒng),最終可以提供豐富的功能。在這種架構(gòu)中,一次請求往往需要涉及到多個(gè)服務(wù)?;ヂ?lián)網(wǎng)應(yīng)用構(gòu)建在不同的軟件模塊集上,這些軟件模塊,有可能是由不同的團(tuán)隊(duì)開發(fā)、可能使用不同的編程語言來實(shí)現(xiàn)、有可能布在了幾千臺(tái)服務(wù)器,橫跨多個(gè)不同的數(shù)據(jù)中心【區(qū)域】,也就意味著這種架構(gòu)形式也會(huì)存在一些問題:
l 如何快速發(fā)現(xiàn)問題?
l 如何判斷故障影響范圍?
l 如何梳理服務(wù)依賴?
l 如何分析鏈路性能問題以及實(shí)時(shí)容量規(guī)劃?
分布式鏈路追蹤(Distributed Tracing),就是將一次分布式請求還原成調(diào)用鏈路,進(jìn)行日志記錄,性能監(jiān)控并將一次分布式請求的調(diào)用情況集中展示。比如各個(gè)服務(wù)節(jié)點(diǎn)上的耗時(shí)、請求具體到達(dá)哪臺(tái)機(jī)器上IP、每個(gè)服務(wù)節(jié)點(diǎn)的請求狀態(tài)200 500等等。
2.2 Sleuth介紹
SpringCloud Sleuth主要功能就是在分布式系統(tǒng)中提供追蹤解決方案。它大量借用了Google Dapper的設(shè)計(jì), 先來了解一下Sleuth中的術(shù)語和相關(guān)概念。
Trace(一條完整鏈路--包含很多span(微服務(wù)接口))
由一組Trace Id(貫穿整個(gè)鏈路)相同的Span串聯(lián)形成一個(gè)樹狀結(jié)構(gòu)。為了實(shí)現(xiàn)請求跟蹤,當(dāng)請求到達(dá)分布式系統(tǒng)的入口端點(diǎn)時(shí),只需要服務(wù)跟蹤框架為該請求創(chuàng)建一個(gè)唯一的標(biāo)識(即TraceId),同時(shí)在分布式系統(tǒng)內(nèi)部流轉(zhuǎn)的時(shí)候,框架始終保持傳遞該唯一值,直到整個(gè)請求的返回。那么我們就可以使用該唯一標(biāo)識將所有的請求串聯(lián)起來,形成一條完整的請求鏈路。
*Span*
代表了一組基本的工作單元。為了統(tǒng)計(jì)各處理單元的延遲,當(dāng)請求到達(dá)各個(gè)服務(wù)組件的時(shí)候,也通過一個(gè)唯一標(biāo)識(SpanId)來標(biāo)記它的開始、具體過程和結(jié)束。通過SpanId的開始和結(jié)束時(shí)間戳,就能統(tǒng)計(jì)該span的調(diào)用時(shí)間,除此之外,我們還可以獲取如事件的名稱。請求信息等元數(shù)據(jù)。
*Annotation*
用它記錄一段時(shí)間內(nèi)的事件,內(nèi)部使用的重要注釋:
l cs(Client Send)客戶端發(fā)出請求,開始一個(gè)請求的命令
l sr(Server Received)服務(wù)端接受到請求開始進(jìn)行處理, sr-cs = 網(wǎng)絡(luò)延遲(服務(wù)調(diào)用的時(shí)間)
l ss(Server Send)服務(wù)端處理完畢準(zhǔn)備發(fā)送到客戶端,ss - sr = 服務(wù)器上的請求處理時(shí)間
l cr(Client Reveived)客戶端接受到服務(wù)端的響應(yīng),請求結(jié)束。 cr - cs = 請求的總時(shí)間
2.3 使用
在父工程中引入依賴 所有子模塊都加入到鏈路監(jiān)控中
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
2.4?Zipkin的集成
Zipkin 是 Twitter 的一個(gè)開源項(xiàng)目,它基于Google Dapper實(shí)現(xiàn),它致力于收集服務(wù)的定時(shí)數(shù)據(jù),以解決微服務(wù)架構(gòu)中的延遲問題,包括數(shù)據(jù)的收集、存儲(chǔ)展現(xiàn)、查找和我們可以使用它來收集各個(gè)服務(wù)器上請求鏈路的跟蹤數(shù)據(jù),并通過它提供的REST API接口來輔助我們查詢跟蹤數(shù)據(jù)以實(shí)現(xiàn)對分布式系統(tǒng)的監(jiān)控程序,從而及時(shí)地發(fā)現(xiàn)系統(tǒng)中出現(xiàn)的延遲升高問題并找出系統(tǒng)性能瓶頸的根源
除了面向開發(fā)的 API 接口之外,它也提供了方便的UI組件來幫助我們直觀的搜索跟蹤信息和分析請求鏈路明細(xì),比如:可以查詢某段時(shí)間內(nèi)各用戶請求的處理時(shí)間等。
Zipkin 提供了可插拔數(shù)據(jù)存儲(chǔ)方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。
它主要由 4 個(gè)核心組件構(gòu)成:
l Collector:收集器組件,它主要用于處理從外部系統(tǒng)發(fā)送過來的跟蹤信息,將這些信息轉(zhuǎn)換為Zipkin 內(nèi)部處理的 Span 格式,以支持后續(xù)的存儲(chǔ)、分析、展示等功能。
l Storage:存儲(chǔ)組件,它主要對處理收集器接收到的跟蹤信息,默認(rèn)會(huì)將這些信息存儲(chǔ)在內(nèi)存中,我們也可以修改此存儲(chǔ)策略,通過使用其他存儲(chǔ)組件將跟蹤信息存儲(chǔ)到數(shù)據(jù)庫中。
l RESTful API:API 組件,它主要用來提供外部訪問接口。比如給客戶端展示跟蹤信息,或是外接系統(tǒng)訪問以實(shí)現(xiàn)監(jiān)控等。
l Web UI:UI 組件,基于 API 組件實(shí)現(xiàn)的上層應(yīng)用。通過 UI 組件用戶可以方便而有直觀地查詢和分析跟蹤信息。
Zipkin 分為兩端,一個(gè)是 Zipkin 服務(wù)端,一個(gè)是 Zipkin 客戶端,客戶端也就是微服務(wù)的應(yīng)用。客戶端會(huì)配置服務(wù)端的 URL 地址,一旦發(fā)生服務(wù)間的調(diào)用的時(shí)候,會(huì)被配置在微服務(wù)里面的 Sleuth 的監(jiān)聽器監(jiān)聽,并生成相應(yīng)的 Trace 和 Span 信息發(fā)送給服務(wù)端。
?2.5 使用可視化zipkin來監(jiān)控微服務(wù)
下載zipkin的jar包 在mysql中創(chuàng)建zipkin的數(shù)據(jù)庫來持久化監(jiān)控?cái)?shù)據(jù)
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 --MYSQL_USER=root --MYSQL_PASS=root
在父項(xiàng)目中引入依賴
??<dependency>
? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-zipkin</artifactId>
? ? ? ? </dependency>
然后每個(gè)微服務(wù)模塊都配置
# zipkin的配置
spring.zipkin.base-url=http://localhost:9411
#zipkin不注冊到nacos上
spring.zipkin.discovery-client-enabled=false
# zipkin要把sleuth產(chǎn)生的日志,抽取的比例。 0.03
spring.sleuth.sampler.probability=1.0
?通過瀏覽器訪問 http://localhost:9411訪問 完成微服務(wù)的鏈路追蹤文章來源:http://www.zghlxwxcb.cn/news/detail-431260.html
總結(jié)
待補(bǔ)充文章來源地址http://www.zghlxwxcb.cn/news/detail-431260.html
到了這里,關(guān)于spring cloud gateway網(wǎng)關(guān)和鏈路監(jiān)控的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!