springCloudGateway-踩坑記錄


一、需求描述

  舊項目做好之后,已經維護了一兩個月,基本上已經趨於穩定,按照項目的整體進度基本上不會在做什么改動。新項目已經確定

下來,只是有一個大概的需求,unity3d的客戶端已經開始做,在這個月23號之前會要求先出一個游戲的版本。目前相對來說不是太忙,

自己就考慮着開始搭建新項目的框架,首先考慮的就是先搭建網關服務。之前的項目由於工期非常短,並且非常急就沒有把網關服務

給加進去,現在有時間了自己就想着第一個任務就是先添加網關服務,之后在根據需要在添加其他的服務。

二、需求分析

  自己的一個了解,網關服務可以做很多事情,比如實現所有訪問請求的日志采集;身份認證,是否已經登錄,是否有權限登錄某個

系統;如果系統的訪問量比較大的話,還可以做負載均衡;還可以做路由轉發,根據不同的路由轉發到對應的服務。好處這么多當然需要

使用一個網關服務來作為項目的統一入口,做各種事情。

三、技術選型

由於現在技術更新得特別快,比如springboot的版本一直在不斷地進行更新,支持時間也在不斷地壓縮。

 

 

 參考了很多資料,最終自己采納選擇2.3.x的springboot版本,springcloud和springcloudalibaba的版本如下,

<!-- 依賴的jar包所對應的版本 -->
<properties>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
<!--<spring-cloud-starter-alibaba-nacos-config.version>1.4.2</spring-cloud-starter-alibaba-nacos-config.version>-->

<!-- 編譯插件 mvn compile -->
<maven-compiler-plugin.source>1.8</maven-compiler-plugin.source>
<maven-compiler-plugin.target>1.8</maven-compiler-plugin.target>
<maven-compiler-plugin.encoding>UTF-8</maven-compiler-plugin.encoding>

<!-- 是否跳過單元測試 解決中文亂碼 -->
<maven-surefire-plugin.skipTests>true</maven-surefire-plugin.skipTests>
<maven-surefire-plugin.argLine>-Dfile.encoding=UTF-8</maven-surefire-plugin.argLine>
<mybatis-generator-maven-plugin.version>1.3.2</mybatis-generator-maven-plugin.version>
</properties>

<!-- 單個子項目特有的jar包 -->
<dependencyManagement>
<dependencies>
<!-- springcloud版本 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- springcloud alibaba 版本 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>

</dependencyManagement>

版本選定好之后就開始搭建項目。由於自己之前一直在使用springcloudalibaba的nacos組件,因此新搭建的項目中繼續使用這個組件。

 主要用來做配置管理和服務發現。本篇博文需要有nacos使用基礎的人才能理解。

 

首先搭建gateway網關項目,java代碼很簡單,就一個啟動類,導入的maven配置如下:<dependencies>

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

<!-- lombok 僅限編譯的時候使用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>

<!-- nacos 配置管理 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<!-- nacos 服務發現 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>

nacos中的配置如下:
server.port=51309
#路由ID 唯一即可,就類似於數據表中的主鍵ID
spring.cloud.gateway.routes[0].id=motionBackend
#路由轉發的地址 lb表示 以load balance 負載均衡的 方式 將講求轉發到 motionSpacebackend(項目名稱) 這個項目中,解析之后是一個具體的地址
spring.cloud.gateway.routes[0].uri=lb://motionSpacebackend
#訪問地址中包含的路徑
spring.cloud.gateway.routes[0].predicates[0]=Path=/gateway/backend/**
#StripPrefix 表示去掉前綴 1 表示第一個前綴 即使是去除 訪問地址中的 /gateway/ 前綴
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
 
bootstrap.properties的配置如下:

 

spring.application.name=motionSpaceGateway
spring.profiles.active=dev
#配置管理
spring.cloud.nacos.config.server-addr=127.0.0.1:24700
#spring.cloud.nacos.config.server-addr=192.168.1.2.5
#命名空間
spring.cloud.nacos.config.namespace=8760e76628114fceb7fc723b2da51c5c
#分組配置
spring.cloud.nacos.config.group=motionSpace
# 開啟動態刷新
spring.cloud.nacos.config.refresh.enabled=true
#讀取的配置文件后綴名
spring.cloud.nacos.config.file-extension=properties
#服務發現地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:24700
#spring.cloud.nacos.discovery.server-addr=192.168.1.2.5
 

由於剛開始搭建項目,只要請求能夠轉發即可,之后的一些功能會一步一步的進行添加。

做完這些工作后,啟動項目,如下圖

 

 

 

 注意事項:springcloudgateway這個項目,不需要配置項目的根路徑,如上圖所示。它和其他springboot項目的啟動方式還不太一樣,其他

項目可以配置項目的根路徑,在項目啟動時也會添加進去。可是springcloudgateway 即使在配置中添加了項目根路徑,啟動時也不會加載。

上圖顯示的是Netty started on port,只需要配置一個端口即可。

 

之后是搭建一個后端主項目,導入的maven配置如下:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- lombok 僅限編譯的時候使用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>

<!-- nacos 配置管理 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<!-- nacos 服務發現 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>

配置更加簡單,一個端口和一個訪問路徑即可:

server.servlet.context-path=/backend
server.port=17303

 

bootstrap.properties的配置如下:

 

 

 

spring.application.name=motionSpacebackend
spring.profiles.active=dev
#配置管理
spring.cloud.nacos.config.server-addr=127.0.0.1:24700
#spring.cloud.nacos.config.server-addr=192.168.1.2.5
#命名空間
spring.cloud.nacos.config.namespace=8760e76628114fceb7fc723b2da51c5c
#分組配置
spring.cloud.nacos.config.group=motionSpace
# 開啟動態刷新
spring.cloud.nacos.config.refresh.enabled=true
#讀取的配置文件后綴名
spring.cloud.nacos.config.file-extension=properties
#服務發現地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:24700
#spring.cloud.nacos.discovery.server-addr=192.168.1.2.5

然后添加一個測試類

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

/**
* @description:
* @author: dengyilang
* @date: 2022/1/7 17:40
* @return: void
*/
@RequestMapping(value = "/rout", method = RequestMethod.GET)
public String scanBind(){
log.info("backend路由測試---");
return "路由測試";
}
}

項目啟動成功。

 

 

 

首先測試后端項目能否正常訪問,訪問的地址為 http://localhost:17303/backend/test/rout

 

 

 測試結果正常。

 

然后測試使用網關服務進行轉發是否正常,請求地址為 http://localhost:51309/gateway/backend/test/rout

 

 測試結果正確。

 

請求的大致過程為 首先請求地址 http://localhost:51309/gateway/backend/test/rout 會到達 gateway項目的后台,

根據路由匹配規則,匹配到如下圖中的路由,並且會截取掉第一個前綴/gateway/變為 http://localhost:51309/backend/test/rout

 

 

 然后gateway項目將請求進行轉發到下圖的地址中,gateway項目在底層進行處理時,會將motionSpacebackend這個項目名稱解析為

對應的地址和端口,在本地就解析為127.0.0.1:17303

 

 

轉發后的請求就變為http://127.0.0.1:17303/backend/test/rout  最終正確地返回想要的結果。

到此一個簡單的網關服務就搭建完成,之后在使用過程中遇到任何問題都會更新在本篇博客中。

參考博客

https://www.cnblogs.com/hellohero55/p/12723451.html

 

2022-01-10-出現問題一:自己按照之前的教程將gateway項目搭建起來后,順利的通過gateway項目轉發請求訪問到另外一個項目的首頁,

 

 

 可是當自己重新引入一個自定義的公共模塊后,發現就訪問不了了,這就讓我很納悶,是怎么回事呢?明明之前還好好的,

 

 

 

 

 而且還報了一個錯如下,

Action:

Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.

查看網友的類似問題,經過排查發現,自己確實在新引入的公共模塊中引入了spring-boot-starter-web 這個依賴導致的,參考博文如下

https://www.cnblogs.com/youcong/p/13939473.html

 

 

解決辦法,暫時不導入公共模塊即可。

 

springcloudgateway的配置如下:

#SSL證書配置 網站是使用 https訪問

server.ssl.key-store=classpath:certificate/ssl_certificate_prd.pfx
server.ssl.key-store-password=xxxx
server.ssl.key-store-type=PKCS12
server.ssl.enabled=true
server.port=43563

#路由的ID 唯一即可
spring.cloud.gateway.routes[0].id=webBackend
#請求轉發的地址 lb 表示以負載均衡的方式 轉發請求 webBackend 表示項目名稱 底層處理的時候會將其解析為具體的IP地址和端口號
spring.cloud.gateway.routes[0].uri=lb://webBackend
#路由匹配規則 當請求地址中包含 /gateway/web/ 這個路由時 會將請求轉發到上面的地址和端口中
spring.cloud.gateway.routes[0].predicates[0]=Path=/gateway/web/**
#表示截取請求地址中的第一個前綴,以上面的為例,將會截取截取掉 /gateway/ 之后訪問的真實地址為 /web/**
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
#配置自定義權限驗證過濾器
spring.cloud.gateway.routes[0].filters[1]=WebAuthorize

 

由於項目中使用了WebSocket這門技術,如果使用gateway網關進行轉發wss協議的請求,會一直報一個錯如下

java.lang.ClassCastException: org.apache.catalina.connector.ResponseFacade cannot be cast to reactor.netty.http.server.HttpServerResponse
at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.getNativeResponse(ReactorNettyRequestUpgradeStrategy.java:124)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/gateway/applets/websocket" [ExceptionHandlingWebHandler]

這個錯暫時還未解決,可是不影響系統的使用。在使用google搜索這個異常后,發現都只有3頁的答案,一個一個的嘗試后暫時還未解決這個問題。

讓系統能夠正常運行的辦法是有使用websocket這門技術的項目直接使用nginx進行轉發,不走gateway網關項目,其他項目的請求都走網關項目,

而且是使用https訪問,以確保項目的安全性。

 

現在這種配置方式已經在生產環境上正式使用起來,已經穩定運行一兩個月,暫時沒發現其他問題。

 

 

 

 之后在使用過程中遇到任何問題,都會貼出來進行分享。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM