Spring Cloud系列之Eureka
Spring Cloud系列之配置中心Config
Spring Cloud系列之gateway
Spring Cloud系列之Feign
Spring Cloud系列之Hystrix
Spring Cloud系列之鏈路追蹤
網(wǎng)關的角色是作為一個 API 架構(gòu),用來保護、增強和控制對于 API 服務的訪問。從面向?qū)ο笤O計的角度看,它與外觀模式類似。API網(wǎng)關封裝了系統(tǒng)內(nèi)部架構(gòu),為每個客戶端提供一個定制的API。它可能還具有其它職責,如身份驗證、日志、黑白名單、監(jiān)控、負載均衡、緩存、請求分片與管理、靜態(tài)響應處理。API網(wǎng)關方式的核心要點是,所有的客戶端和消費端都通過統(tǒng)一的網(wǎng)關接入微服務,在網(wǎng)關層處理所有的非業(yè)務功能。通常,網(wǎng)關也是提供REST/HTTP的訪問API。 下面我們來看一張網(wǎng)關所處的架構(gòu)圖

從這張圖上看到有四個層次,最上層是我們用戶層,第二層是我們的負載均衡器,第三層就是我們的網(wǎng)關,最后是我們內(nèi)部的微服務,在接入網(wǎng)關的時候為什么需要在上面需要一個負載均衡器,因為我們想讓網(wǎng)關無狀態(tài),無狀態(tài)的網(wǎng)關有一個好處,可以部署很多,不會有單點,即使掛了一臺,其他的網(wǎng)關還在,這個對整個系統(tǒng)的穩(wěn)定性起來非常重要的作用。一般的系統(tǒng)會有一個LB,然后對應多個網(wǎng)關。網(wǎng)關能起到的作用很多:
最重要的一個重要反向路由,當外面的請求進來之后,怎么找到內(nèi)部具體的微服務,這個是網(wǎng)關起來重要職責,將外部的調(diào)用轉(zhuǎn)化為內(nèi)部的服務服務,這個就是反向路由
第二個是認證安全,網(wǎng)關像是一個門衛(wèi),有一些訪問是正常的訪問,有一些是惡意的訪問,例如說爬蟲,甚至是一些黑客行為,網(wǎng)關需要將其攔截在外部- 第三個重要職責是限流熔斷,比方說,有一個門,外面有流量進來,正常來說流量是比較穩(wěn)定的,但也有可能有突發(fā)流量,有可能網(wǎng)站在搞促銷,這個時候可能就有流量的洪峰闖進來,如果說內(nèi)部沒有好的限流熔斷措施,可能造成內(nèi)部整個服務的服務器癱瘓,網(wǎng)關就要承擔限流熔斷的職責。
網(wǎng)關要承擔日志監(jiān)控的職責,外部的訪問所有的流量都要經(jīng)過網(wǎng)關,那么可以在網(wǎng)關上可以對所有的流量做訪問的審計,把它作為日志保存起來,另外可以通過分析日志,知道性能的調(diào)用情況,能夠?qū)φ麄€流量情況進行監(jiān)控
zuul快被springcloud家族拋棄了,在這里我們著重介紹下SpringCloud Gateway
SpringCloud Gateway
簡介
SpringCloud Gateway 是 Spring Cloud 的一個全新項目,該項目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發(fā)的網(wǎng)關,它旨在為微服務架構(gòu)提供一種簡單有效的統(tǒng)一的 API 路由管理方式。
SpringCloud Gateway 作為 Spring Cloud 生態(tài)系統(tǒng)中的網(wǎng)關,目標是替代 Zuul,在Spring Cloud 2.0以上版本中,沒有對新版本的Zuul 2.0以上最新高性能版本進行集成,仍然還是使用的Zuul 2.0之前的非Reactor模式的老版本。而為了提升網(wǎng)關的性能,SpringCloud Gateway是基于WebFlux框架實現(xiàn)的,而WebFlux框架底層則使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway 的目標,不僅提供統(tǒng)一的路由方式,并且基于 Filter 鏈的方式提供了網(wǎng)關基本的功能,例如:安全,監(jiān)控/指標,和限流。
Spring Cloud Gateway 底層使用了高性能的通信框架Netty。
核心概念
路由(route):網(wǎng)關配置的基本組成模塊,和Zuul的路由配置模塊類似。一個Route模塊由一個 ID,一個目標 URI,一組斷言和一組過濾器定義。如果斷言為真,則路由匹配,目標URI會被訪問。
-
斷言(Predicate):參考了 Java 8 的 Predicate,可以使用它來匹配來自 HTTP 請求的任何內(nèi)容,例如 headers 或請求參數(shù)。斷言的輸入類型是一個 ServerWebExchange。類似于nginx中的location匹配一樣
spring cloud gateway幫我們內(nèi)置了很多Predicate功能,實現(xiàn)了各種路由匹配規(guī)則(通過header、請求參數(shù)等作為條件)匹配到相應的路由
斷言體系包含:
時間類斷言
cookie類斷言
header請求頭斷言
host請求主機類斷言
method請求方式類斷言
path請求路徑斷言
queryparam請求參數(shù)類斷言
remoteaddr遠程地址類斷言
過濾器(Filter):和Zuul的過濾器在概念上類似,可以使用它攔截和修改請求,并且對上游的響應,進行二次處理。過濾器為org.springframework.cloud.gateway.filter.GatewayFilter類的實例。
下面是其官網(wǎng)中對工作過程描述圖,如下:
[圖片上傳失敗...(image-a26eae-1640333180160)]
總結(jié)下:
客戶端想gateway發(fā)出請求,然后在gateway handler mapping中找到與請求相匹配的路由,將其發(fā)送到gateway web handler,handler再通過指定的過濾鏈路來將請求發(fā)送到我們實際的服務并執(zhí)行業(yè)務邏輯,然后返回,其中過濾器用虛線分隔,是因為過濾器可能會在發(fā)送代理請求之前(pre)或者之后(post)執(zhí)行業(yè)務邏輯;
Filter在pre前我們可以做請求的合法性校驗、權(quán)限校驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等等,在post之后我們也可以做響應內(nèi)容的修改、日志輸出、流量監(jiān)控等等。
入門
- 引入依賴:
<dependencies>
<!--spring cloud gateway依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--網(wǎng)關也是一個eureka客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
注意:gateway不需要引入web模塊,他引入的是webflux
- 配置文件
server:
port: 10003
spring:
application:
name: gateway
zipkin:
# zipkin server的請求地址
base-url: http://localhost:10005/
sender:
type: web
sleuth:
sampler:
probability: 1
cloud:
gateway:
routes:
# 路由id,可以隨意寫
- id: user-api-route
# 代理的服務地址;lb表示從eureka中獲取具體服務
uri: lb://user-api
# 路由斷言,可以配置映射路徑
predicates:
- Path=/user/**
filters: # 表示過濾1個路徑,2表示兩個路徑,以此類推
- StripPrefix=1
config:
enabled: true
# 與遠程倉庫中的配置文件的application保持一致
name: gateway
# 遠程倉庫中的配置文件的profile保持一致
profile: dev
# 遠程倉庫中的 分支 版本保持一致
label: master
# config server地址
uri: http://localhost:10002/
# 配置的用戶名密碼
username: root
password: root
#eureka 參數(shù)配置
eureka:
# 此實例注冊到eureka服務端的唯一的實例ID,其組成為${spring.application.name}:${spring.application.instance_id:${random.value}}
instance:
# 與此實例相關聯(lián)的主機名,是其他實例可以用來進行請求的準確名稱
hostname: localhost
# 獲取實例的ip地址
prefer-ip-address: true
# eureka客戶需要多長時間發(fā)送心跳給eureka服務器,表明它仍然活著,默認為30 秒
lease-renewal-interval-in-seconds: 10
# Eureka服務器在接收到實例的最后一次發(fā)出的心跳后,需要等待多久才可以將此實例刪除,默認為90秒
lease-expiration-duration-in-seconds: 30
client:
# 注冊自己
register-with-eureka: true
# 不拉取服務
fetch-registry: true
# 配置服務地址
service-url:
# eureka 服務地址,如果是集群的話;需要指定其它集群eureka地址 ,如果是多臺eureka server 地址以逗號隔開
defaultZone: http://127.0.0.1:10001/eureka
- 啟動類
/**
* @Description:
* @author: dy
*/
@EnableDiscoveryClient //開啟Eureka客戶端發(fā)現(xiàn)功能
@SpringBootApplication
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class, args);
}
}
基礎功能這樣配置就夠了,運行結(jié)果訪問接口:

gateway過濾器
從過濾器的生命周期角度來說,分為兩個pre和post:
pre前我們可以做請求的合法性校驗、權(quán)限校驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等等
post之后我們也可以做響應內(nèi)容的修改、日志輸出、流量監(jiān)控等等。
過濾器類型“
gatewayFilter 應用到單個路由上
globalfilter 應用到全部路由上
下面我們就以全局過濾器來實現(xiàn)一個功能:
比如實現(xiàn)校驗用戶是否登錄,判斷用戶請求頭里面是否有token,代碼如下:
/**
* @Description:
* @author: dy
*/
@Component //讓容器掃描到就等同于注冊了
public class TokenGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("-----------------全局過濾器MyGlobalFilter------------------- --");
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (StringUtils.isBlank(token)) {
//沒有登錄拒絕訪問,返回
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//合法請求放行、執(zhí)行后續(xù)的過濾器
return chain.filter(exchange);
}
/**
* 過濾器的執(zhí)行順序
* @return
*/
@Override
public int getOrder() {
//值越小越先執(zhí)行
return 1;
}
}