本篇文章為大家展示了如何進行SpringCloud Gateway 全鏈路實現(xiàn)分析,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
創(chuàng)新互聯(lián)主營沙依巴克網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app軟件開發(fā)公司,沙依巴克h5小程序設(shè)計搭建,沙依巴克網(wǎng)站營銷推廣歡迎沙依巴克等地區(qū)企業(yè)咨詢
隨著微服務(wù)架構(gòu)的流行,服務(wù)按照不同的維度進行拆分,一次請求往往需要涉及到多個服務(wù)。而諸多的服務(wù)可能分布在了幾千臺服務(wù)器,橫跨多個不同的數(shù)據(jù)中心。為了快速定位和解決故障,應(yīng)用性能進行分析,全鏈路監(jiān)控組件就在這樣的問題背景下產(chǎn)生了。最出名的是谷歌公開的論文提到的 Google Dapper。想要在這個上下文中理解分布式系統(tǒng)的行為,就需要監(jiān)控那些橫跨了不同的應(yīng)用、不同的服務(wù)器之間的關(guān)聯(lián)動作。
通過業(yè)務(wù)調(diào)用過程中添加并傳遞調(diào)用鏈ID,實現(xiàn)應(yīng)用間生成鏈路數(shù)據(jù),最終串聯(lián)成一條完整的調(diào)用鏈。 其中整個調(diào)用過程中每個請求都要透傳TxId、SpanId和pSpanId。
作為Spring Cloud官方推出的第二代網(wǎng)關(guān)框架,Spring cloud gateway是基于Spring 5.0、Spring Boot2.0和Reactor等技術(shù)開發(fā)的網(wǎng)關(guān),采用了NIO模型進行通信。
1.2.2 Mono與Flux
Mono表示的是包含 0 或者 1 個元素的異步序列,即要么成功發(fā)布元素,要么錯誤
Flux和Mono之間可以相互轉(zhuǎn)換,比如對一個 Flux 序列進行計數(shù)操作,得到的結(jié)果是一個 Mono對象,或者把兩個 Mono 序列合并在一起,得到的是一個 Flux 對象。
Spring Cloud Gateway作為入口網(wǎng)關(guān),主要負(fù)責(zé)服務(wù)的路由轉(zhuǎn)發(fā)。如果網(wǎng)關(guān)沒有進行監(jiān)控,則全鏈路會缺失網(wǎng)關(guān)節(jié)點,直接展示為用戶訪問后續(xù)應(yīng)用;不能有效定位用戶請求慢是網(wǎng)關(guān)問題還是后續(xù)節(jié)點。
3.1.1 Spring Cloud Gateway的請求入口
org.springframework.http.server.reactive.ReactorHttpHandlerAdapter#apply 先將接收到的HttpServerRequest或者最終需要返回的HttpServerResponse包裝轉(zhuǎn)換為ReactorServerHttpRequest和ReactorServerHttpResponse,再處理請求。
public Mono<Void> apply(HttpServerRequest request, HttpServerResponse response) { NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(response.alloc()); ServerHttpRequest adaptedRequest; ServerHttpResponse adaptedResponse; try { adaptedRequest = new ReactorServerHttpRequest(request, bufferFactory); adaptedResponse = new ReactorServerHttpResponse(response, bufferFactory); } catch (URISyntaxException ex) { logger.error("Invalid URL ">
3.1.2 構(gòu)造網(wǎng)關(guān)上下文
org.springframework.web.server.adapter.HttpWebHandlerAdapter#handle
createExchange()構(gòu)造網(wǎng)關(guān)上下文ServerWebExchange
getDelegate()通過委托的方式獲取一系列需要處理的WebHandler
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) { ServerWebExchange exchange = createExchange(request, response); return getDelegate().handle(exchange) .onErrorResume(ex -> handleFailure(request, response, ex)) .then(Mono.defer(response::setComplete)); } protected ServerWebExchange createExchange(ServerHttpRequest request, ServerHttpResponse response) { return new DefaultServerWebExchange(request, response, this.sessionManager, getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext); }
3.1.3 進入Filter鏈
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle 獲得 GatewayFilter 數(shù)組,并根據(jù)獲得的 GatewayFilter 數(shù)組創(chuàng)建DefaultGatewayFilterChain,過濾處理請求。
public Mono<Void> handle(ServerWebExchange exchange) { Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); List<GatewayFilter> gatewayFilters = route.getFilters(); List<GatewayFilter> combined = new ArrayList<>(this.globalFilters); combined.addAll(gatewayFilters); AnnotationAwareOrderComparator.sort(combined); logger.debug("Sorted gatewayFilterFactories: "+ combined); return new DefaultGatewayFilterChain(combined).filter(exchange); }
3.1.4 執(zhí)行Filter鏈
org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain#filter 過濾器的鏈?zhǔn)秸{(diào)用
public Mono<Void> filter(ServerWebExchange exchange) { return Mono.defer(() -> { if (this.index < filters.size()) { GatewayFilter filter = filters.get(this.index); DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1); return filter.filter(exchange, chain); } else { return Mono.empty(); // complete } }); }
3.1.5 Gateway Filter適配器
org.springframework.cloud.gateway.handler.FilteringWebHandler$GatewayFilterAdapter#filter GatewayFilterAdapter是GlobalFilter過濾器的包裝類,最終委托Global Filter進行執(zhí)行。
private static class GatewayFilterAdapter implements GatewayFilter { private final GlobalFilter delegate; public GatewayFilterAdapter(GlobalFilter delegate) { this.delegate = delegate; } public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return this.delegate.filter(exchange, chain); } }
3.1.6 Netty路由網(wǎng)關(guān)過濾器
org.springframework.cloud.gateway.filter.NettyRoutingFilter#filter
GlobalFilter實現(xiàn)有很多,此處只分析NettyRoutingFIlter和NettyWriteResponseFilter。而NettyRoutingFilter負(fù)責(zé)使用 Netty HttpClient 代理對下游的請求。
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 獲得 requestUrl URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); // 判斷是否能夠處理,http或https前綴 String scheme = requestUrl.getScheme(); if (isAlreadyRouted(exchange) || (!"http".equals(scheme) && !"https".equals(scheme))) { return chain.filter(exchange); } // 設(shè)置已經(jīng)路由 setAlreadyRouted(exchange); ServerHttpRequest request = exchange.getRequest(); // 創(chuàng)建Netty Request Method對象 final HttpMethod method = HttpMethod.valueOf(request.getMethod().toString()); final String url = requestUrl.toString(); HttpHeaders filtered = filterRequest(this.headersFilters.getIfAvailable(), exchange); final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders(); filtered.forEach(httpHeaders::set); String transferEncoding = request.getHeaders().getFirst(HttpHeaders.TRANSFER_ENCODING); boolean chunkedTransfer = "chunked".equalsIgnoreCase(transferEncoding); boolean preserveHost = exchange.getAttributeOrDefault(PRESERVE_HOST_HEADER_ATTRIBUTE, false); // 請求后端服務(wù) return this.httpClient.request(method, url, req -> { final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach) .headers(httpHeaders) .chunkedTransfer(chunkedTransfer) .failOnServerError(false) .failOnClientError(false); if (preserveHost) { String host = request.getHeaders().getFirst(HttpHeaders.HOST); proxyRequest.header(HttpHeaders.HOST, host); } return proxyRequest.sendHeaders() //發(fā)送請求頭 .send(request.getBody().map(dataBuffer -> // 發(fā)送請求Body ((NettyDataBuffer)dataBuffer).getNativeBuffer())); }).doOnNext(res -> { ServerHttpResponse response = exchange.getResponse(); // put headers and status so filters can modify the response HttpHeaders headers = new HttpHeaders(); res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue())); exchange.getAttributes().put("original_response_content_type", headers.getContentType()); HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter( this.headersFilters.getIfAvailable(), headers, exchange, Type.RESPONSE); response.getHeaders().putAll(filteredResponseHeaders); HttpStatus status = HttpStatus.resolve(res.status().code()); if (status != null) { response.setStatusCode(status); } else if (response instanceof AbstractServerHttpResponse) { // https://jira.spring.io/browse/SPR-16748 ((AbstractServerHttpResponse) response).setStatusCodeValue(res.status().code()); } else { throw new IllegalStateException("Unable to set status code on response: ">
3.1.7 Netty 回寫響應(yīng)網(wǎng)關(guān)過濾器
org.springframework.cloud.gateway.filter.NettyWriteResponseFilter#filter NettyWriteResponseFilter 與NettyRoutingFilter成對出現(xiàn),負(fù)責(zé)將代理響應(yīng)寫回網(wǎng)關(guān)客戶端響應(yīng)。
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // then方法實現(xiàn)After Filter邏輯 return chain.filter(exchange).then(Mono.defer(() -> { // 獲得Netty Response HttpClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR); if (clientResponse == null) { return Mono.empty(); } log.trace("NettyWriteResponseFilter start"); ServerHttpResponse response = exchange.getResponse(); // 將Netty Response回寫給客戶端 NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory(); //TODO: what if it's not netty final Flux<NettyDataBuffer> body = clientResponse.receive() .retain() // ByteBufFlux => ByteBufFlux .map(factory::wrap); // ByteBufFlux => Flux<NettyDataBuffer> MediaType contentType = response.getHeaders().getContentType(); return (isStreamingMediaType(contentType) ? response.writeAndFlushWith(body.map(Flux::just)) : response.writeWith(body)); })); }
當(dāng)最終將網(wǎng)關(guān)也進行監(jiān)控,可以全局的看到應(yīng)用請求流轉(zhuǎn),網(wǎng)關(guān)的請求業(yè)務(wù)分流,各應(yīng)用的調(diào)用負(fù)載情況。
上述內(nèi)容就是如何進行SpringCloud Gateway 全鏈路實現(xiàn)分析,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章題目:如何進行SpringCloudGateway全鏈路實現(xiàn)分析
本文URL:http://muchs.cn/article28/jpdejp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、品牌網(wǎng)站設(shè)計、做網(wǎng)站、品牌網(wǎng)站制作、云服務(wù)器、虛擬主機
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)