1、gateway相關介紹 在微服務架構中,系統往往由多個微服務組成,而這些服務可能部署在不同機房、不同地區、不同功能變數名稱下。這種情況下,客戶端(例如瀏覽器、手機、軟體工具等)想要直接請求這些服務,就需要知道它們具體的地址信息,例如 IP 地址、埠號等。這種客戶端直接請求服務的方式存在很多的複雜問題。 ...
1、gateway相關介紹
在微服務架構中,系統往往由多個微服務組成,而這些服務可能部署在不同機房、不同地區、不同功能變數名稱下。這種情況下,客戶端(例如瀏覽器、手機、軟體工具等)想要直接請求這些服務,就需要知道它們具體的地址信息,例如 IP 地址、埠號等。這種客戶端直接請求服務的方式存在很多的複雜問題。如:需要維護大量的服務地址、存在跨域請求的問題、每個微服務需要獨立認證等。所以我們可以通過 API 網關(gateway)來解決這些問題。所有客戶端請求都發生到網關,由網關統一轉發到不同的地址。網關還可以 處理一些非業務功能的邏輯,例如許可權驗證、監控、緩存等。本篇主要講解通過網關統一請求轉發到不同微服務。
2、創建網關服務
首先創建maven項目新建網關模塊:
pom導入網關相關依賴:
<dependencies> <!--Eureka Client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--特別註意:在 gateway 網關服務中不能引入 spring-boot-starter-web 的依賴,否則會報錯--> <!-- Spring cloud gateway 網關依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
<!-- LoadBalancer -->
<!-- 引入spring-cloud-loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--ribbon Spring Cloud Ribbon 在高版本移除了 -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
<!-- <version>2.2.5.RELEASE</version>-->
<!-- </dependency>-->
</dependencies>
創建springboot啟動類:
@SpringBootApplication @EnableEurekaClient public class GateWayApplication { public static void main(String[] args) { SpringApplication.run(GateWayApplication.class,args); } }
啟動類創建成功後,在resources資源目錄下創建application.yml文件,用來配置gateway。首先設置服務埠和服務名稱:
server: port: 8081 spring: application: name: gateway-server-one
在把網關註冊到註冊中心:
#客戶端註冊 eureka: instance: instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} #localhost hostname: localhost client: register-with-eureka: true #是否向註冊中心註冊自己 預設為true fetch-registry: true #是否需要檢索服務 預設為true service-url: defaultZone: http://eternity:1234qwer@localhost:4405/eureka/
配置好之後,可以啟動網關。查看網關服務是否可以正常啟動以及是否在註冊中心註冊成功,如果註冊成功然後在開始配置網關參數。
可以看到服務啟動成功,我們看看註冊中心是否成功:
eureka中心已經有了,說明啟動成功。
3、配置gateway路由
spring: application: name: gateway-server-one cloud: loadbalancer: ribbon: enabled: false #使用LoadBalancer, Ribbon 在高版本移除了 切換到ReactiveLoadBalancerClientFilter gateway: discovery: locator: #路由訪問方式:http://Gateway_HOST:Gateway_PORT/大寫的serviceId/**,其中微服務應用名預設大寫訪問。 enabled: true #開啟通過名稱找到伺服器功能 lower-case-service-id: true #使用小寫service-id routes: - id: hibernate-server-one-route #路由的ID,沒有固定規則,但要求唯一,建議與服務名對應 uri: http://localhost:8800 #匹配後提供服務的路由地址 predicates: #以下是斷言條件,必選全部符合條件 - Path=/admin/user/** #斷言,路徑相匹配的進行路由 - Method=GET #只能時 GET 請求時,才能訪問 - id: xxl-job-server-one-route # uri: http://localhost:8801 #可以設置為服務名 uri: lb://XXL-JOB-SERVER-MODEL #可以設置為服務名 predicates: - Path=/admin/user/** #斷言,路徑相匹配的進行路由, 註意:Path 中 P 為大寫 - After=2022-06-06T03:29:37.318-07:00 # [Asia/Shanghai] # after來進行設置,後面添加一個時間,就是指在什麼時間之後這個服務才可以被訪問,否則將無法被訪問到 # - After=2030-01-20T17:42:47.789-07:00 # [America/Denver]
配置成功後再次啟動網關,查看伺服器是否轉發成功。
通過網關gateway請求路徑訪問查找用戶信息:
http://localhost:8081/admin/user/
通過postman測試介面,查詢成功。
4、gateway負載均衡
通過在配置文件中配置路徑的uri為註冊中心伺服器名稱,可以實現gateway負載均衡。訪問時通過服務名稱去查找服務名下麵的多個實例,根據配置的策略實現轉發到不同實例服務。
uri: lb://XXL-JOB-SERVER-MODEL #可以設置為服務名
在通過服務名稱轉發的過程中,有可能轉發失敗。報找不到服務,介面報錯:
查看網關控制台發現也報錯:
java.net.UnknownHostException: failed to resolve 'xxl-job-server-model' after 4 queries at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final] 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 POST "/admin/user/" [ExceptionHandlingWebHandler] Stack trace: at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final] at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:966) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final] at io.netty.resolver.dns.DnsResolveContext.query(DnsResolveContext.java:414) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
沒有找到服務名,剛開始以為是設置路由的服務名和註冊中心的服務名不一致。經過查找發現是一致。最後查找發現是客戶端微服務註冊到註冊中心的hostname配置錯誤,需要配置和註冊中心一致的hostname。不然網關通過服務名找不到相關地址:
查看eureka服務註冊地址:
所以需要配置客戶端hostname:
hostname: localhost
再次重新運行系統,發現報錯問題已經解決。