微服務 02

一、網關路由

網關就是網絡的關口。數據在網絡間傳輸,從一個網絡傳輸到另一網絡時就需要經過網關來做數據的路由和轉發以及數據安全的校驗。

路由是網關的核心功能之一,決定如何將客戶端請求映射到后端服務。

1、快速入門

創建新模塊,引入網關依賴,編寫啟動類,配置路由規則????????

依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>hmall</artifactId><groupId>com.heima</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>hm-gateway</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><dependencies><!--common--><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency><!--網關--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos discovery--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--負載均衡--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

?新建yml/yaml文件配置路由

server:port: 8080
spring:application:name: gatewaycloud:nacos:server-addr: 192.168.150.101:8848gateway:routes:- id: item # 路由規則id,自定義,唯一uri: lb://item-service # 路由的目標服務,lb代表負載均衡,會從注冊中心拉取服務列表(微服務名,從yaml文件里找的)predicates: # 路由斷言,判斷當前請求是否符合當前規則,符合則路由到目標服務(請求路徑,看controller)- Path=/items/**,/search/** # 這里是以請求路徑作為判斷規則(有多個路徑逗號分割,或者下一行重新寫 - Path=/search/**)- id: carturi: lb://cart-servicepredicates:- Path=/carts/**- id: useruri: lb://user-servicepredicates:- Path=/users/**,/addresses/**- id: tradeuri: lb://trade-servicepredicates:- Path=/orders/**- id: payuri: lb://pay-servicepredicates:- Path=/pay-orders/**

路由包含四個屬性:

  • id:路由的唯一標示

  • predicates:路由斷言,其實就是匹配條件

  • filters:路由過濾器,對請求或響應做特殊處理。

  • uri:路由目標地址,lb://代表負載均衡,從注冊中心獲取目標微服務的實例列表,并且負載均衡選擇一個訪問。

Spring中提供了12種基本的RoutePredicateFactory實現:

路由斷言

名稱

說明

示例

After

是某個時間點后的請求

- After=2037-01-20T17:42:47.789-07:00[America/Denver]

Before

是某個時間點之前的請求

- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]

Between

是某兩個時間點之前的請求

- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]

Cookie

請求必須包含某些cookie

- Cookie=chocolate, ch.p

Header

請求必須包含某些header

- Header=X-Request-Id, \d+

Host

請求必須是訪問某個host(域名)

- Host=**.somehost.org,**.anotherhost.org

Method

請求方式必須是指定方式

- Method=GET,POST

Path

請求路徑必須符合指定規則

- Path=/red/{segment},/blue/**

Query

請求參數必須包含指定參數

- Query=name, Jack或者- Query=name

RemoteAddr

請求者的ip必須是指定范圍

- RemoteAddr=192.168.1.1/24

weight

權重處理

2、路由過濾

網關中提供了33種路由過濾器,每種過濾器都有獨特的作用。?

      routes:- id: item # 路由規則id,自定義,唯一uri: lb://item-service # 路由的目標服務,lb代表負載均衡,會從注冊中心拉取服務列表predicates: # 路由斷言,判斷當前請求是否符合當前規則,符合則路由到目標服務- Path=/items/**,/search/** # 這里是以請求路徑作為判斷規則(有多個路徑逗號分割,或者下一行重新寫 - Path=/search/**)filters:- AddResponseHeader=truth, anyone

如果與routes同一級設置?default-filters,就是對所有路由都生效:

      default-filters:- AddResponseHeader=truth, anyone  //所有路由都生效

創建啟動類:

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

二、網關登錄校驗

1、實現思路

單體架構時我們只需要完成一次用戶登錄、身份校驗,就可以在所有業務中獲取到用戶信息。而微服務拆分后,每個微服務都獨立部署,不再共享數據。也就意味著每個微服務都需要做登錄校驗,這顯然不可取。

既然網關是所有微服務的入口,一切請求都需要先經過網關。我們完全可以把登錄校驗的工作放到網關去做,這樣之前說的問題就解決了。

?

?在網關內自定義過濾器,編寫登錄校驗邏輯,并且將過濾器執行順序定義到NettyRoutingFilter之前,

?2、自定義過濾器

網管過濾器有兩種,分別是:

  • GatewayFilter:路由過濾器,作用于任意指定的路由;默認不生效,要配置到路由后生效。
  • GlobalFilter:全局過濾器,作用范圍是所有路由;聲明后自動生效。

兩種過濾器的過濾方法簽名完全一樣:

/*** 處理請求并將其傳遞給下一個過濾器* @param exchange 當前請求的上下文,其中包含request、response等各種數據* @param chain 過濾器鏈,基于它向下傳遞請求* @return 根據返回值標記當前請求是否被完成或攔截,chain.filter(exchange)就放行了。*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

?GlobalFilter定義步驟:

  1. 新建包filters,新建類MyGlobalFilter。
  2. 添加@Component注解。
  3. 實現GlobaFilter接口以及其中的filter方法。
  4. 進行邏輯代碼編寫
  5. 實現Ordered接口以及其中的方法。(用來定義優先級)
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//TODO 模擬登錄校驗邏輯ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();System.out.println("header =" + headers);return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}
}

3、實現登錄校驗

需求:在網關中基于過濾器實現登錄校驗功能

定義步驟與 上面GlobalFilter定義步驟一致,具體代碼如下:

@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {private final JwtTool jwtTool;private final AuthProperties authProperties;private AntPathMatcher antPathMatcher = new AntPathMatcher();  //是Spring 框架提供的路徑匹配工具類。@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1、獲取requestServerHttpRequest request = exchange.getRequest();//2、判斷是否需要做登錄攔截if (isExclude(request.getPath().toString())) {//放行return chain.filter(exchange);}//3、獲取tokenString token = null;List<String> headers = request.getHeaders().get("authorization");if (headers != null && !headers.isEmpty()) {token = headers.get(0);}Long userId = null;//4、校驗并解析tokentry {userId = jwtTool.parseToken(token);} catch (Exception e) {//攔截,設置響應狀態碼,401// 獲取響應對象ServerHttpResponse response = exchange.getResponse();// 設置響應狀態碼為401(未授權)response.setStatusCode(HttpStatus.UNAUTHORIZED);// 結束響應,不再繼續處理請求return response.setComplete();}//5、TODO 傳遞用戶信息System.out.println("userId=" + userId);//6、放行return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}private boolean isExclude(String path) {// 獲取所有需要排除的路徑,來自AuthProperties配置類中的excludePaths屬性// AuthProperties通過@ConfigurationProperties注解自動綁定配置文件中hm.auth.exclude-paths的值for (String pathPattern : authProperties.getExcludePaths()) {// 使用AntPathMatcher匹配當前路徑是否符合排除路徑模式// 如果匹配成功,則說明該路徑不需要進行身份驗證攔截if (antPathMatcher.match(pathPattern, path)) {return true;}}return false;}
}

4、網關傳遞用戶

①在網關的登錄校驗過濾器中,把獲取得到的用戶寫入請求頭。

修改轉發到微服務的請求,需要用到ServerWebExchange類提供的API,示例如下:

?修改內容:

     //5、傳遞用戶信息String userInfo = userId.toString();ServerWebExchange swe = exchange.mutate().request(builder -> builder.header("user-info", userInfo)) //要寫入的請求頭,名字可以自己起,要寫入的內容.build();//6、放行return chain.filter(swe);

②在hm-common中編寫SpringMVC攔截器,獲取登錄用戶。

public class UserInfoInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1、獲取用戶登錄信息String userInfo = request.getHeader("user-info");//2、判斷是否獲取了用戶,如果有,存入ThreadLocalif (StrUtil.isNotBlank(userInfo)) {UserContext.setUser(Long.valueOf(userInfo));}//放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//清理用戶UserContext.removeUser();}
}

5、OpenFeign傳遞用戶

OpenFeign中提供了一個攔截器接口,所有由OpenFeign發起的請求都會先調用攔截器處理請求:

public interface RequestInterceptor {/*** Called for every request. * Add data using methods on the supplied {@link RequestTemplate}.*/void apply(RequestTemplate template);
}
    @Beanpublic RequestInterceptor userInfoRequestInterceptor() {return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate template) {Long userId = UserContext.getUser();if(userId != null){template.header("user-info",userId.toString());}}};}

微服務登錄解決方案

三、配置管理

微服務配置的問題:

  • 微服務重復配置過多,維護成本高。
  • 業務配置經常變動,每次修改都要重啟服務。
  • 網關路由配置寫死,如果變更要重啟網關。

1、配置共享

①將一些公共的配置進行抽取,放到Nacos->配置列表->新建配置中,

?${}是可以通過其他配置文件來指明,這些都是不固定的,不能寫死,后面的:是添加一個默認值。共享的配置有swagger,log,jdbc

?

②然后將其中的變量值聲明出來:

hm:db:database: hm-cart

③拉取共享配置

?基于NacosConfig拉取共享配置代替微服務的本地配置。

SpringCloud在初始化上下文的時候會先讀取一個名為bootstrap.yaml(或者bootstrap.properties)的文件,如果我們將nacos地址配置到bootstrap.yaml中,那么在項目引導階段就可以讀取nacos中的配置了。

配置步驟:

? ? ? ? 1)引入依賴(幫助完成拉取配置的動作, 讀取bootstrap文件,創建bootStrap的上下文)

  <!--nacos配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--讀取bootstrap文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>

? ? ? ? 2)新建bootstrap.yaml(包含服務名字,nacos地址,共享文件的名稱)

spring:application:name: cart-serviceprofiles:active: dev  #開發環境(dev)、測試環境(test)、生產環境(prod)cloud:nacos:server-addr: 192.168.100.128:8848config:file-extension: yamlshared-configs:- data-id: shared-jdbc.yaml- data-id: shared-log.yaml- data-id: shared-swagger.yaml

application.yaml變為:

server:port: 8082
feign:okhttp:enabled: true # 開啟OKHttp功能hm:db:database: hm-cartswagger:title: "黑馬商城購物車服務接口文檔"package: com.hmall.cart.controller# keytool -genkeypair -alias hmall -keyalg RSA -keypass hmall123 -keystore hmall.jks -storepass hmall123

2、配置熱更新

配置熱更新:當修改配置文件中的配置時,微服務無需重啟即可使配置生效。

前提條件:

①nacos中要有一個與微服務名有關的配置文件規則:[服務名]-[spring.active.profile].[后綴名]

②微服務中要以特定的方式讀取需要熱更新的配置屬性 新建config包,創建類并定義屬性

@Data
@Component
@ConfigurationProperties(prefix = "hm.cart")
public class CartProperties {private Integer maxAmount;
}

在源代碼處進行更改:

 private void checkCartsFull(Long userId) {int count = lambdaQuery().eq(Cart::getUserId, userId).count();if (count >= cartProperties.getMaxItems()) {throw new BizIllegalException(StrUtil.format("用戶購物車課程不能超過{}", cartProperties.getMaxItems()));}}

3、動態路由

要實現動態路由首先要將路由配置保存到Nacos,當Nacos中的路由配置變更時,推送最新配置到網關,實時更新網關中的路由信息。?

要完成的事情:

①監聽Nacos配置變更的消息

②當配置變更時,將最新的路由信息更新到網關路由表

//TODO

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917044.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917044.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917044.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

04動手學深度學習筆記(上)

04數據操作 import torch(1)張量表示一個數據組成的數組&#xff0c;這個數組可能有多個維度。 xtorch.arange(12) xtensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])(2)通過shape來訪問張量的形狀和張量中元素的總數 x.shapetorch.Size([12])(3)number of elements表…

MCU中的RTC(Real-Time Clock,實時時鐘)是什么?

MCU中的RTC(Real-Time Clock,實時時鐘)是什么? 在MCU(微控制器單元)中,RTC(Real-Time Clock,實時時鐘) 是一個獨立計時模塊,用于在系統斷電或低功耗狀態下持續記錄時間和日期。以下是關于RTC的詳細說明: 1. RTC的核心功能 精準計時:提供年、月、日、時、分、秒、…

Linux 進程調度管理

進程調度器可粗略分為兩類&#xff1a;實時調度器(kernel)&#xff0c;系統中重要的進程由實時調度器調度&#xff0c;獲得CPU能力強。非實時調度器(user)&#xff0c;系統中大部分進程由非實時調度器調度&#xff0c;獲得CPU能力弱。實時調度器實時調度器支持的調度策略&#…

基于 C 語言視角:流程圖中分支與循環結構的深度解析

前言&#xff08;約 1500 字&#xff09;在 C 語言程序設計中&#xff0c;控制結構是構建邏輯的核心骨架&#xff0c;而流程圖作為可視化工具&#xff0c;是將抽象代碼邏輯轉化為直觀圖形的橋梁。對于入門 C 語言的工程師而言&#xff0c;掌握流程圖與分支、循環結構的對應關系…

threejs創建自定義多段柱

最近在研究自定義建模&#xff0c;有一個多斷柱模型比較有意思&#xff0c;分享下&#xff0c;就是利用幾組點串&#xff0c;比如上中下&#xff0c;然后每組點又不一樣多&#xff0c;點續還不一樣&#xff0c;(比如第一個環的第一個點在左邊&#xff0c;第二個環在右邊)&#…

Language Models are Few-Shot Learners: 開箱即用的GPT-3(四)

Result續 Winograd-Style Tasks Winograd-Style Tasks 是自然語言處理中的一類經典任務。它源于 Winograd Schema Challenge(WSC),主要涉及確定代詞指的是哪個單詞,旨在評估模型的常識推理和自然語言理解能力。 這個任務中的具體通常包含高度歧義的代詞,但從語義角度看…

BGP高級特性之認證

一、概述BGP使用TCP作為傳輸協議&#xff0c;只要TCP數據包的源地址、目的地址、源端口、目的端 口和TCP序號是正確的&#xff0c;BGP就會認為這個數據包有效&#xff0c;但數據包的大部分參數對于攻擊 者來說是不難獲得的。為了保證BGP免受攻擊&#xff0c;可以在BGP鄰居之間使…

商旅平臺怎么選?如何規避商旅流程中的違規風險?

在中大型企業的商旅管理中&#xff0c;一個典型的管理“黑洞”——流程漏洞與超標正持續吞噬企業成本與管理效能&#xff1a;差標混亂、審批脫節讓超規訂單頻頻闖關&#xff0c;不僅讓企業商旅成本超支&#xff0c;還可能引發稅務稽查風險。隱性的合規風險&#xff0c;比如虛假…

Anaconda的常用命令

Anaconda 是一個用于科學計算、數據分析和機器學習的 Python 發行版&#xff0c;包含了大量的預安裝包。它配有 conda 命令行工具&#xff0c;方便用戶管理包和環境。以下是一些常用的 conda 命令和 Anaconda 的常見操作命令&#xff0c;幫助你高效管理環境和包。1. 環境管理創…

JVM之【Java虛擬機概述】

目錄 對JVM的理解 JVM的架構組成 類加載系統 執行引擎 運行時數據區 垃圾收集系統 本地方法庫 對JVM的理解 JVM保證了Java程序的執行&#xff0c;同時也是Java語言具有跨平臺性的根本原因&#xff1b;Java源代碼通過javac等前端編譯器生成的字節碼計算機并不能識別&…

RabbitMQ+內網穿透遠程訪問教程:實現異地AMQP通信+Web管理

RabbitMQ是一個開源的消息隊列中間件&#xff0c;基于Erlang開發&#xff0c;遵循AMQP&#xff08;Advanced Message Queuing Protocol&#xff0c;高級消息隊列協議&#xff09;標準&#xff0c;主要用于實現異步通信、消息解耦和系統間數據傳輸。它的核心作用是在分布式系統中…

go 語言 timer 與 ticker理論和實例大全

目錄 1. 時間之門的鑰匙:Timer與Ticker的本質 2. Timer:精準的單次計時 2.1 Timer的基礎用法 2.2 停止與重置Timer 2.3 Timer的高級技巧:優雅處理并發 3. Ticker:時間的節拍器 3.1 Ticker的基本用法 3.2 Ticker的高級應用:動態調整周期 4. Timer與Ticker的結合:打…

MySQL 45講 16-17

全字段排序 explain 中的 using fiesort ,掃描 數據,取出符合判斷條件的 數據,到sort buffer中,然后對排序字段采用快速排序進行 排序后直接將 所需字段進行返回 如果 字段長度所占內存大于所分配 的sort buffer ,需要借助 臨時文件 進行 數據的存放排序,此時會采用 歸并排序,將…

QT項目 -仿QQ音樂的音樂播放器(第四節)

一、RecBox中btUp和btDown按鈕clicked處理 選中左右鍵&#xff08;btUp和btDown按鈕&#xff09;然后右擊轉到槽->click() void RecBox::on_btUp_clicked() {}void RecBox::on_btDown_clicked() {} 二、imageList中圖片分組 // recbox.h 中新增 int currentIndex; // 標記…

DeepSeek SEO關鍵詞優化提升流量增長

內容概要DeepSeek SEO關鍵詞優化致力于通過科學的方法&#xff0c;顯著提升網站在搜索引擎中的可見度與自然流量。其核心在于深入理解并精準匹配用戶的真實搜索意圖&#xff0c;而非僅僅堆砌詞匯。具體來說&#xff0c;該策略運用深度意圖導向策略&#xff0c;確保內容與用戶需…

# Ubuntu 系統設置 USB PnP 音頻設備為默認設備的完整教程

Ubuntu 系統設置 USB PnP 音頻設備為默認設備的完整教程 在使用 Ubuntu 系統時&#xff0c;尤其是在嵌入式設備如 NVIDIA Jetson 系列上&#xff0c;我們經常需要將 USB PnP 音頻設備設置為默認設備。本文將詳細介紹如何通過命令行配置&#xff0c;使 USB PnP 音頻設備在系統重…

Hadoop JMX 配置的完整文檔

一、JMX 基礎概念與 Hadoop 支持 1、JMX 作用。 Java Management Extensions&#xff08;JMX&#xff09;提供標準 API 監控 JVM 應用運行時狀態&#xff08;內存、線程、GC&#xff09;及 Hadoop 組件指標&#xff08;HDFS 容量、RPC 性能、節點狀態&#xff09; 2、Hadoop 組…

arm架構系統打包qt程序--麒麟操作系統為例

檢查系統架構 uname -a如果顯示是aarch644或arm64&#xff0c;說明你使用的是ARM架構&#xff0c;&#xff0c;需要下載ARM版本。 下載對應架構的linuxdeployqt 編寫腳本 vim deploy.sh#!/bin/bash APP_NAME"sunny450_silc"# 確保deploy目錄存在 mkdir -p deploy# 復…

Kong API Gateway深度解析:插件系統與微服務架構的技術基石

在微服務&#xff08;microservices&#xff09;架構主導的今天&#xff0c;API網關&#xff08;API Gateway&#xff09;作為服務入口的“交通樞紐”&#xff0c;承擔著流量調度、安全防護、可觀測性&#xff08;observability&#xff09;等核心職責。Kong作為開源API網關領域…

Linux應用開發基礎知識——Makefile初級教程(九)

目錄 一、Makefile是啥&#xff1f; 1.1、了解幾種文件&#xff08;.o 文件和.c文件 &#xff09; 1.2、關于Makefile的寫法 1.3、簡單使用Makefile基本指令 1.4、引入偽目標 1.5、Makefile的優點 1.6、Makefile的使用 二、Makefile創建和使用變量 2.1、創建變量的目的…