主頁 > 軟體設計 > 微服務設計(四)---微服務網關與鏈路追蹤

微服務設計(四)---微服務網關與鏈路追蹤

2022-09-26 07:25:11 軟體設計

一、微服務網關概述

  如下圖:

  不同的微服務一般會有不同的網路地址,客戶端在訪問這些微服務時必須記住幾十甚至幾百個地址,這對于客戶端方來說太復雜也難以維護,如果讓客戶端直接與各個微服務通訊,可能會有很多問題: 客戶端會請求多個不同的服務,需要維護不同的請求地址,增加開發難度 在某些場景下存在跨域請求的問題 加大身份認證的難度,每個微服務需要獨立認證,因此,我們需要一個微服務網關,介于客戶端與服務器之間的中間層,所有的外部請求都會先經過微服務網關,客戶端只需要與網關互動,只知道一個網關地址即可,這樣簡化了開發,還有以下優點: 1、易于監控 2、易于認證 3、減少了客戶端與各個微服務之間的互動次數,

1、服務網關的概念

   API網關是一個服務器,是系統對外的唯一入口,API網關封裝了系統內部架構,為每個客戶端提供 一個定制的API,API網關方式的核心要點是,所有的客戶端和消費端都通過統一的網關接入微服務,在 網關層處理所有的非業務功能,通常,網關也是提供REST/HTTP的訪問API,服務端通過API-GW注冊和 管理服務,

2、作用和應用場景

  網關具有的職責,如身份驗證、監控、負載均衡、快取、請求分片與管理、靜態回應處理,當然,最主要的職責還是與“外界聯系”,

3、常見的API網關實作方式

  Kong

  基于Nginx+Lua開發,性能高,穩定,有多個可用的插件(限流、鑒權等等)可以開箱即用, 問題:只支持Http協議;二次開發,自由擴展困難;提供管理API,缺乏更易用的管控、配置方 式,

  Zuul

  Netflix開源,功能豐富,使用JAVA開發,易于二次開發;需要運行在web容器中,如Tomcat, 問題:缺乏管控,無法動態配置;依賴組件較多;處理Http請求依賴的是Web容器,性能不如 Nginx;

  Traefik

  Go語言開發;輕量易用;提供大多數的功能:服務路由,負載均衡等等;提供WebUI 問題:二進制檔案部署,二次開發難度大;UI更多的是監控,缺乏配置、管理能力;

  Spring Cloud Gateway

  SpringCloud提供的網關服務 Nginx+lua實作 使用Nginx的反向代理和負載均衡可實作對api服務器的負載均衡及高可用 問題:自注冊的問題和網關本身的擴展性

4、基于Nginx的網關實作

(1) Nginx介紹

(2) Nginx反向代理

  多個客戶端給服務器發送的請求,Nginx服務器接收到之后,按照一定的規則分發給了后端的業務處理服務器進行處理了,此時~請求的來源也就是客戶端是明確的,但是請求具體由哪臺服務器處理的并不明確了,Nginx扮演的就是一個反向代理角色,客戶端是無感知代理的存在的,反向代理對外都是透明的,訪問者并不知道自己訪問的是一個代理,因為客戶端不需要任何配置就可以訪問,反向代理,"它代理的是服務端,代服務端接收請求",主要用于服務器集群分布式部署的情況下,反向代理隱藏了服務器的資訊,如果只是單純的需要一個最基礎的具備轉發功能的網關,那么使用Ngnix是一個不錯的選擇,

5、 微服務網關Zuul

(1)Zuul簡介

  Zuul是Netflix開源的微服務網關,它可以和Eureka、Ribbon、Hystrix等組件配合使用,Zuul組件的核心是一系列的過濾器,這些過濾器可以完成以下功能:

  動態路由:動態將請求路由到不同后端

  集群壓力測驗:逐漸增加指向集群的流量,以了解性能

  負載分配:為每一種負載型別分配對應容量,并棄用超出限定值的請求

  靜態回應處理:邊緣位置進行回應,避免轉發到內部集群

  身份認證和安全: 識別每一個資源的驗證要求,并拒絕那些不符的請求,

Spring Cloud對Zuul進行了整合和增強, 

(2)搭建Zuul網關服務器

   1)創建工程匯入依賴

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>

  2)撰寫啟動類

@SpringBootApplication
@EnableZuulProxy // 開啟Zuul的網關功能
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}

@EnableZuulProxy : 通過 @EnableZuulProxy 注解開啟Zuul網管功能

  3)撰寫配置

創建組態檔 application.yml ,并添加相應配置

server:
port: 8080 #服務埠
spring:
application:
name: api-gateway #指定服務名

(3)Zuul中的路由轉發

  “路由”是指根據請求URL,將請求分配到對應的處理程式,在微服務體系中,Zuul負責接收所有的請求,根據不同的URL匹配規則,將不同的請求轉發到不同的微服務處理,

zuul:
routes:
product-service: # 這里是路由id,隨意寫
path: /product-service/** # 這里是映射路徑
url: http://127.0.0.1:9002 # 映射路徑對應的實際url地址
sensitiveHeaders: #默認zuul會屏蔽cookie,cookie不會傳到下游服務,這里設定為空則取
消默認的黑名單,如果設定了具體的頭資訊則不會傳到下游服務

  只需要在application.yml檔案中配置路由規則即可:

  product-service:配置路由id,可以隨意取名 u

  rl:映射路徑對應的實際url地址

  path:配置映射路徑,這里將所有請求前綴為/product-service/的請求,轉發到http://127.0.0.1: 9002處理 配置好Zuul路由之后啟動服務,

(4)面向服務的路由

  微服務一般是由幾十、上百個服務組成,對于一個URL請求,最侄訓確認一個服務實體進行處理,如果對每個服務實體手動指定一個唯一訪問地址,然后根據URL去手動實作請求匹配,這樣做顯然就不合理, Zuul支持與Eureka整合開發,根據ServiceID自動的從注冊中心中獲取服務地址并轉發請求,這樣做的好處不僅可以通過單個端點來訪問應用的所有服務,而且在添加或移除服務實體的時候不用修改Zuul的 路由配置,

  1)添加Eureka客戶端依賴

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

  2)開啟Eureka客戶端發現功能

@SpringBootApplication
@EnableZuulProxy // 開啟Zuul的網關功能
@EnableDiscoveryClient
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}

  3)添加Eureka配置,獲取服務資訊

eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8761/eureka/
registry-fetch-interval-seconds: 5 # 獲取服務串列的周期:5s
instance:
preferIpAddress: true
ip-address: 127.0.0.1

  4)修改映射配置,通過服務名稱獲取

  因為已經有了Eureka客戶端,我們可以從Eureka獲取服務的地址資訊,因此映射時無需指定IP地址,而是通過服務名稱來訪問,而且Zuul已經集成了Ribbon的負載均衡功能,

#配置路由規則
zuul:
routes:
product-service: # 這里是路由id,隨意寫
path: /product-service/** # 這里是映射路徑
serviceId: shop-service-product #配置轉發的微服務名稱

serviceId: 指定需要轉發的微服務實體名稱

(5)Zuul加入后的架構

(6)Zuul中的過濾器

  Zuul它包含了兩個核心功能:對請求的路由和過濾,其中路由功能負責將外部請求轉發到具體的微服務實體上,是實作外部訪問統一入口的基礎;而過濾器功能則負責對請求的處理程序進行干預,是實作請求校驗、服務聚合等功能的基礎,其實,路由功能在真正運行時,它的路由映射和請求轉發同樣也由幾個不同的過濾器完成的,所以,過濾器可以說是Zuul實作API網關功能最為核心的部件,每一個進入Zuul的HTTP請求都會經過一系列的過濾器處理鏈得到請求回應并回傳給客戶端,

 1)ZuulFilter簡介

  Zuul 中的過濾器跟我們之前使用的 javax.servlet.Filter 不一樣,javax.servlet.Filter 只有一種型別,可以通過配置 urlPatterns 來攔截對應的請求,而 Zuul 中的過濾器總共有 4 種型別,且每種型別都有對 應的使用場景,

  1. PRE:這種過濾器在請求被路由之前呼叫,我們可利用這種過濾器實作身份驗證、在集群中選擇請 求的微服務、記錄除錯資訊等,

  2. ROUTING:這種過濾器將請求路由到微服務,這種過濾器用于構建發送給微服務的請求,并使用 Apache HttpClient或Netfilx Ribbon請求微服務,

  3. POST:這種過濾器在路由到微服務以后執行,這種過濾器可用來為回應添加標準的HTTP Header、收集統計資訊和指標、將回應從微服務發送給客戶端等,

  4. ERROR:在其他階段發生錯誤時執行該過濾器,

  Zuul提供了自定義過濾器的功能實作起來也十分簡單,只需要撰寫一個類去實作zuul提供的介面

public abstract ZuulFilter implements IZuulFilter{
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 來自IZuulFilter
Object run() throws ZuulException;// IZuulFilter
}

  ZuulFilter是過濾器的頂級父類,在這里我們看一下其中定義的4個最重要的方法

  shouldFilter :回傳一個 Boolean 值,判斷該過濾器是否需要執行,回傳true執行,回傳false 不執行,

  run :過濾器的具體業務邏輯,

  filterType :回傳字串,代表過濾器的型別,包含以下4種:

    pre :請求在被路由之前執行

    routing :在路由請求時呼叫

    post :在routing和errror過濾器之后呼叫

    error :處理請求時發生錯誤呼叫

  filterOrder :通過回傳的int值來定義過濾器的執行順序,數字越小優先級越高,

(7) 生命周期

  正常流程: 請求到達首先會經過pre型別過濾器,而后到達routing型別,進行路由,請求就到達真正的 服務提供者,執行請求,回傳結果后,會到達post過濾器,而后回傳回應, 例外流程: 整個程序中,pre或者routing過濾器出現例外,都會直接進入error過濾器,再error處理完畢 后,會將請求交給POST過濾器,最后回傳給用戶, 如果是error過濾器自己出現例外,最終也會進入POST過濾器,而后回傳, 如果是POST過濾器出現例外,會跳轉到error過濾器,但是與pre和routing不同的時,請求不會再到達POST過濾器了, 不同過濾器的場景: 請求鑒權:一般放在pre型別,如果發現沒有訪問權限,直接就攔截了 例外處理:一般會在error型別和post型別過濾器中結合來處理, 服務呼叫時長統計:pre和post結合使用,

(8)Zuul網關存在的問題

  在實際使用中我們會發現直接使用Zuul會存在諸多問題,包括: 性能問題 Zuul1x版本本質上就是一個同步Servlet,采用多執行緒阻塞模型進行請求轉發,簡單講,每來 一個請求,Servlet容器要為該請求分配一個執行緒專門負責處理這個請求,直到回應回傳客戶 端這個執行緒才會被釋放回傳容器執行緒池,如果后臺服務呼叫比較耗時,那么這個執行緒就會被阻塞,阻塞期間執行緒資源被占用,不能干其它事情,我們知道Servlet容器執行緒池的大小是有限制的,當前端請求量大,而后臺慢服務比較多時,很容易耗盡容器執行緒池內的執行緒,造成容器無法接受新的請求, 不支持任何長連接,如websocket

(9) Zuul網關的替換方案

  Zuul2.x版本 SpringCloud Gateway

5 、微服務網關GateWay

  Zuul 1.x 是一個基于阻塞 IO 的 API Gateway 以及 Servlet;直到 2018 年 5 月,Zuul 2.x(基于 Netty,也是非阻塞的,支持長連接)才發布,但 Spring Cloud 暫時還沒有整合計劃,Spring Cloud Gateway 比 Zuul 1.x 系列的性能和功能整體要好,

(1)Gateway簡介

  Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的網關,旨在為微服務架構提供一種簡單而有效的統一的 API 路由管理方式,統一訪問介面,Spring Cloud Gateway 作為 Spring Cloud 生態系中的網關,目標是替代 Netflix ZUUL,其不僅提供統一的路 由方式,并且基于 Filter 鏈的方式提供了網關基本的功能,例如:安全,監控/埋點,和限流等,它是基 于Nttey的回應式開發模式,

上表為Spring Cloud Gateway與Zuul的性能對比,從結果可知,Spring Cloud Gateway的RPS是Zuul 的1.6倍

(2)核心概念

  1. 路由(route) 路由是網關最基礎的部分,路由資訊由一個ID、一個目的URL、一組斷言工廠和一 組Filter組成,如果斷言為真,則說明請求URL和配置的路由匹配,

  2. 斷言(predicates) Java8中的斷言函式,Spring Cloud Gateway中的斷言函式輸入型別是 Spring5.0框架中的ServerWebExchange,Spring Cloud Gateway中的斷言函式允許開發者去定 義匹配來自Http Request中的任何資訊,比如請求頭和引數等,

  3. 過濾器(filter) 一個標準的Spring webFilter,Spring Cloud Gateway中的Filter分為兩種型別, 分別是Gateway Filter和Global Filter,過濾器Filter可以對請求和回應進行處理,

(3) 入門案例

  1) 創建工程匯入依賴

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

注意SpringCloud Gateway使用的web框架為webflux,和SpringMVC不兼容,引入的限流組件是 hystrix,redis底層不再使用jedis,而是lettuce,

  2) 配置啟動類

@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
}
}

  3) 撰寫組態檔

創建 application.yml 組態檔

server:
port: 8080 #服務埠
spring:
application:
name: api-gateway #指定服務名
cloud:
gateway:
routes:
- id: product-service
uri: http://127.0.0.1:9002
predicates:
- Path=/product/**

id:我們自定義的路由 ID,保持唯一

uri:目標服務地址

predicates:路由條件,Predicate 接受一個輸入引數,回傳一個布林值結果,

該介面包含多種默 認方法來將 Predicate 組合成其他復雜的邏輯(比如:與,或,非), filters:過濾規則,暫時沒用,

(4)路由規則

  Spring Cloud Gateway 的功能很強大,前面我們只是使用了 predicates 進行了簡單的條件匹配,其實 Spring Cloud Gataway 幫我們內置了很多 Predicates 功能,在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性實作了各種路由匹配規則,有通過 Header、請求引數等不同的條件來進行作為條件匹配到對應的路由,

eg:

#路由斷言之后匹配
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/24

(5)過濾器

Spring Cloud Gateway除了具備請求路由功能之外,也支持對請求的過濾,通過Zuul網關類似,也是通 過過濾器的形式來實作的,那么接下來我們一起來研究一下Gateway中的過濾器

(6)過濾器基礎

  1) 過濾器的生命周期

  Spring Cloud Gateway 的 Filter 的生命周期不像 Zuul 的那么豐富,它只有兩個:“pre” 和 “post”,

  PRE: 這種過濾器在請求被路由之前呼叫,我們可利用這種過濾器實作身份驗證、在集群中選擇 請求的微服務、記錄除錯資訊等,

  POST:這種過濾器在路由到微服務以后執行,這種過濾器可用來為回應添加標準的 HTTP Header、收集統計資訊和指標、將回應從微服務發送給客戶端等,

  2) 過濾器型別 Spring Cloud Gateway 的 Filter 從作用范圍可分為另外兩種GatewayFilter 與 GlobalFilter,

  GatewayFilter:應用到單個路由或者一個分組的路由上,

  GlobalFilter:應用到所有的路由上,

(7) 區域過濾器

  區域過濾器(GatewayFilter),是針對單個路由的過濾器,可以對訪問的URL過濾,進行切面處理,在 Spring Cloud Gateway中通過GatewayFilter的形式內置了很多不同型別的區域過濾器,這里簡單將 Spring Cloud Gateway內置的所有過濾器工廠整理成了一張表格,雖然不是很詳細,但能作為速覽使 用,如下:

  每個過濾器工廠都對應一個實作類,并且這些類的名稱必須以 GatewayFilterFactory 結尾,這是 Spring Cloud Gateway的一個約定,例如 AddRequestHeader 對應的實作類為 AddRequestHeaderGatewayFilterFactory ,對于這些過濾器的使用方式可以參考官方檔案

(8)全域過濾器

  全域過濾器(GlobalFilter)作用于所有路由,Spring Cloud Gateway 定義了Global Filter介面,用戶 可以自定義實作自己的Global Filter,通過全域過濾器可以實作對權限的統一校驗,安全性驗證等功 能,并且全域過濾器也是程式員使用比較多的過濾器, Spring Cloud Gateway內部也是通過一系列的內置全域過濾器對整個路由轉發進行處理如下:

(9)統一鑒權

  內置的過濾器已經可以完成大部分的功能,但是對于企業開發的一些業務功能處理,還是需要我們自己 撰寫過濾器來實作的,那么我們一起通過代碼的形式自定義一個過濾器,去完成統一的權限校驗,

(10) 鑒權邏輯

  開發中的鑒權邏輯: 當客戶端第一次請求服務時,服務端對用戶進行資訊認證(登錄) 認證通過,將用戶資訊進行加密形成token,回傳給客戶端,作為登錄憑證 以后每次請求,客戶端都攜帶認證的token 服務端對token進行解密,判斷是否有效,

如上圖,對于驗證用戶是否已經登錄鑒權的程序可以在網關層統一檢驗,檢驗的標準就是請求中是否攜 帶token憑證以及token的正確性,

(11)網關限流

   常見的限流演算法

  1) 計數器 計數器限流演算法是最簡單的一種限流實作方式,其本質是通過維護一個單位時間內的計數器,每次請求 計數器加1,當單位時間內計數器累加到大于設定的閾值,則之后的請求都被拒絕,直到單位時間已經 過去,再將計數器重置為零

  2) 漏桶演算法

  漏桶演算法可以很好地限制容量池的大小,從而防止流量暴增,漏桶可以看作是一個帶有常量服務時間的 單服務器佇列,如果漏桶(包快取)溢位,那么資料包會被丟棄, 在網路中,漏桶演算法可以控制埠的 流量輸出速率,平滑網路上的突發流量,實作流量整形,從而為網路提供一個穩定的流量,

為了更好的控制流量,漏桶演算法需要通過兩個變數進行控制:一個是桶的大小,支持流量突發增多時可 以存多少的水(burst),另一個是水桶漏洞的大小(rate),

  3) 令牌桶演算法

  令牌桶演算法是對漏桶演算法的一種改進,桶演算法能夠限制請求呼叫的速率,而令牌桶演算法能夠在限制呼叫 的平均速率的同時還允許一定程度的突發呼叫,在令牌桶演算法中,存在一個桶,用來存放固定數量的令 牌,演算法中存在一種機制,以一定的速率往桶中放令牌,每次請求呼叫需要先獲取令牌,只有拿到令 牌,才有機會繼續執行,否則選擇選擇等待可用的令牌、或者直接拒絕,放令牌這個動作是持續不斷的 進行,如果桶中令牌數達到上限,就丟棄令牌,所以就存在這種情況,桶中一直有大量的可用令牌,這 時進來的請求就可以直接拿到令牌執行,比如設定qps為100,那么限流器初始化完成一秒后,桶中就 已經有100個令牌了,這時服務還沒完全啟動好,等啟動完成對外提供服務時,該限流器可以抵擋瞬時 的100個請求,所以,只有桶中沒有令牌時,請求才會進行等待,最后相當于以一定的速率執行,

(12)基于Filter的限流

  SpringCloudGateway官方就提供了基于令牌桶的限流支持,基于其內置的過濾器工廠 RequestRateLimiterGatewayFilterFactory 實作,在過濾器工廠中是通過Redis和lua腳本結合的方 式進行流量控制,

(13)基于Sentinel的限流

  Sentinel 支持對 Spring Cloud Gateway、Zuul 等主流的 API Gateway 進行限流,

  從 1.6.0 版本開始,Sentinel 提供了 Spring Cloud Gateway 的適配模塊,可以提供兩種資源維度的限 流: route 維度:即在 Spring 組態檔中配置的路由條目,資源名為對應的 routeId 自定義 API 維度:用戶可以利用 Sentinel 提供的 API 來自定義一些 API 分組 Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模塊,此模塊中包含網關限流的規則 和自定義 API 的物體和管理邏輯: GatewayFlowRule :網關限流規則,針對 API Gateway 的場景定制的限流規則,可以針對不同 route 或自定義的 API 分組進行限流,支持針對請求中的引數、Header、來源 IP 等進行定制化的 限流, ApiDefinition :用戶自定義的 API 定義分組,可以看做是一些 URL 匹配的組合,比如我們可以 定義一個 API 叫 my_api ,請求 path 模式為 /foo/** 和 /baz/** 的都歸到 my_api 這個 API 分組下面,限流的時候可以針對這個自定義的 API 分組維度進行限流,

  基于Sentinel 的Gateway限流是通過其提供的Filter來完成的,使用時只需注入對應的 SentinelGatewayFilter 實體以及 SentinelGatewayBlockExceptionHandler 實體即可, @PostConstruct定義初始化的加載方法,用于指定資源的限流規則,這里資源的名稱為 orderservice ,統計時間是1秒內,限流閾值是1,表示每秒只能訪問一個請求,

(14)網關高可用

  高可用HA(High Availability)是分布式系統架構設計中必須考慮的因素之一,它通常是指,通過設計 減少系統不能提供服務的時間,我們都知道,單點是系統高可用的大敵,應該盡量在系統設計的程序中避免單點,方法論上,高可用保證的原則是“集群化”,或者 叫“冗余”:只有一個單點,掛了服務會受影響;如果有冗余備份,掛了還有其他backup能夠頂上,

  我們實際使用 Spring Cloud Gateway 的方式如上圖,不同的客戶端使用不同的負載將請求分發到后端 的 Gateway,Gateway 再通過HTTP呼叫后端服務,最后對外輸出,因此為了保證 Gateway 的高可用 性,前端可以同時啟動多個 Gateway 實體進行負載,在 Gateway 的前端使用 Nginx 或者 F5 進行負載 轉發以達到高可用性,

(15) 執行流程分析

  Spring Cloud Gateway 核心處理流程如上圖所示,Gateway的客戶端向 Spring Cloud Gateway 發 送請求,請求首先被 HttpWebHandlerAdapter 進行提取組裝成網關背景關系,然后網關的背景關系會傳遞 到 DispatcherHandler , DispatcherHandler 是所有請求的分發處理器, DispatcherHandler 主要 負責分發請求對應的處理器,比如請求分發到對應的 RoutePredicateHandlerMapping (路由斷言處 理映射器),路由斷言處理映射器主要作用用于路由查找,以及找到路由后回傳對應的 FilterWebHandler , FilterWebHandler 主要負責組裝Filter鏈并呼叫Filter執行一系列的Filter處理, 然后再把請求轉到后端對應的代理服務處理,處理完畢之后將Response回傳到Gateway客戶端,

二、微服務的鏈路追蹤概述

1、微服務架構下的問題

   在大型系統的微服務化構建中,一個系統會被拆分成許多模塊,這些模塊負責不同的功能,組合成系統,最終可以提供豐富的功能,在這種架構中,一次請求往往需要涉及到多個服務,互聯網應用構建在不同的軟體模塊集上,這些軟體模塊,有可能是由不同的團隊開發、可能使用不同的編程語言來實作、 有可能布在了幾千臺服務器,橫跨多個不同的資料中心,也就意味著這種架構形式也會存在一些問題: 如何快速發現問題? 如何判斷故障影響范圍? 如何梳理服務依賴以及依賴的合理性? 如何分析鏈路性能問題以及實時容量規劃? 分布式鏈路追蹤(Distributed Tracing),就是將一次分布式請求還原成呼叫鏈路,進行日志記錄,性能監控并將 一次分布式請求的呼叫情況集中展示,比如各個服務節點上的耗時、請求具體到達哪臺機器 上、每個服務節點的請求狀態等等, 目前業界比較流行的鏈路追蹤系統如:Twitter的Zipkin,阿里的鷹眼,美團的Mtrace,大眾點評的cat等,大部分都是基于google發表的Dapper,Dapper闡述了分布式系統,特別是微服務架構中鏈路 追蹤的概念、資料表示、埋點、傳遞、收集、存盤與展示等技術細節,

2、 Sleuth概述

     Spring Cloud Sleuth 主要功能就是在分布式系統中提供追蹤解決方案,并且兼容支持了 zipkin,只需要在pom檔案中引入相應的依賴即可,

(1)相關概念

  Spring Cloud Sleuth 為Spring Cloud提供了分布式根據的解決方案,它大量借用了Google Dapper的 設計,先來了解一下Sleuth中的術語和相關概念, Spring Cloud Sleuth采用的是Google的開源專案Dapper的專業術語, Span:基本作業單元,例如,在一個新建的span中發送一個RPC等同于發送一個回應請求給 RPC,span通過一個64位ID唯一標識,trace以另一個64位ID表示,span還有其他資料資訊,比 如摘要、時間戳事件、關鍵值注釋(tags)、span的ID、以及進度ID(通常是IP地址) span在不斷的啟動和停止,同時記錄了時間資訊,當你創建了一個span,你必須在未來的某個時 刻停止它, Trace:一系列spans組成的一個樹狀結構,例如,如果你正在跑一個分布式大資料工程,你可能 需要創建一個trace, Annotation:用來及時記錄一個事件的存在,一些核心annotations用來定義一個請求的開始和結 束 cs - Client Sent -客戶端發起一個請求,這個annotion描述了這個span的開始 sr - Server Received -服務端獲得請求并準備開始處理它,如果將其sr減去cs時間戳便可得到 網路延遲 ss - Server Sent -注解表明請求處理的完成(當請求回傳客戶端),如果ss減去sr時間戳便可得 到服務端需要的處理請求時間 cr - Client Received -表明span的結束,客戶端成功接收到服務端的回復,如果cr減去cs時間 戳便可得到客戶端從服務端獲取回復的所有所需時間

(2) 鏈路追蹤Sleuth入門

  查看日志檔案并不是一個很好的方法,當微服務越來越多日志檔案也會越來越多,通過Zipkin可以將日志聚合,并進行可視化展示和全文檢索,

(3)Zipkin的概述

  Zipkin 是 Twitter 的一個開源專案,它基于 Google Dapper 實作,它致力于收集服務的定時資料,以解決微服務架構中的延遲問題,包括資料的收集、存盤、查找和展現, 我們可以使用它來收集各個服務 器上請求鏈路的跟蹤資料,并通過它提供的 REST API 介面來輔助我們查詢跟蹤資料以實作對分布式系 統的監控程式,從而及時地發現系統中出現的延遲升高問題并找出系統性能瓶頸的根源,除了面向開發 的 API 介面之外,它也提供了方便的 UI 組件來幫助我們直觀的搜索跟蹤資訊和分析請求鏈路明細,比 如:可以查詢某段時間內各用戶請求的處理時間等, Zipkin 提供了可插拔資料存盤方式:InMemory、MySql、Cassandra 以及 Elasticsearch,

 上圖展示了 Zipkin 的基礎架構,它主要由 4 個核心組件構成:

Collector:收集器組件,它主要用于處理從外部系統發送過來的跟蹤資訊,將這些資訊轉換為 Zipkin 內部處理的 Span 格式,以支持后續的存盤、分析、展示等功能,

Storage:存盤組件,它主要對處理收集器接收到的跟蹤資訊,默認會將這些資訊存盤在記憶體中, 我們也可以修改此存盤策略,通過使用其他存盤組件將跟蹤資訊存盤到資料庫中,

RESTful API:API 組件,它主要用來提供外部訪問介面,比如給客戶端展示跟蹤資訊,或是外接系統訪問以實作監控等,

Web UI:UI 組件,基于 API 組件實作的上層應用,通過 UI 組件用戶可以方便而有直觀地查詢和 分析跟蹤資訊,

Zipkin 分為兩端,一個是 Zipkin 服務端,一個是 Zipkin 客戶端,客戶端也就是微服務的應用, 客戶端會配置服務端的 URL 地址,一旦發生服務間的呼叫的時候,會被配置在微服務里面的 Sleuth 的監聽器監聽,并生成相應的 Trace 和 Span 資訊發送給服務端, 發送的方式主要有兩種,一種是 HTTP 報文的方式,還有一種是訊息總線的方式如 RabbitMQ,不論哪種方式,我們都需要: 一個 Eureka 服務注冊中心,這里我們就用之前的 eureka 專案來當注冊中心, 一個 Zipkin 服務端, 多個微服務,這些微服務中配置Zipkin 客戶端,

(4)基于訊息中間件收集資料

  在默認情況下,Zipkin客戶端和Server之間是使用HTTP請求的方式進行通信(即同步的請求方式),在網路波動,Server端例外等情況下可能存在資訊收集不及時的問題,Zipkin支持與rabbitMQ整合完成異步訊息傳輸, 加了MQ之后,通信程序如下圖所示:

(5)存盤跟蹤資料

  Zipkin Server默認時間追蹤資料資訊保存到記憶體,這種方式不適合生產環境,因為一旦Service關閉重啟或者服務崩潰,就會導致歷史資料消失,Zipkin支持將追蹤資料持久化到mysql資料庫或者存盤到elasticsearch中,

 

 感謝閱讀,借鑒了不少大佬資料,如需轉載,請注明出處,謝謝!https://www.cnblogs.com/huyangshu-fs/p/13888664.html

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/509539.html

標籤:架構設計

上一篇:微服務設計(三)---服務呼叫Feign及服務熔斷機制Hystrix

下一篇:建造者模式(創建型)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more