Spring Cloud Gateway 的簡(jiǎn)單搭建
早期文章

? ? ? ? 在 《服務(wù)注冊(cè)、發(fā)現(xiàn)和遠(yuǎn)程調(diào)用》 這篇文章中介紹關(guān)于服務(wù)注冊(cè)、發(fā)現(xiàn)和遠(yuǎn)程調(diào)用的一個(gè) Demo,本文在這篇文章的基礎(chǔ)上介紹如何使用 Spring Cloud Gateway 搭建一個(gè)網(wǎng)關(guān)。
一、問(wèn)題
? ? ? ??在上篇文章中,分別創(chuàng)建了 service_user 和 service_dict 兩個(gè)服務(wù),兩個(gè)服務(wù)分別使用了 8001 和 8002 兩個(gè)端口。這樣直接通過(guò) PostMan 或?yàn)g覽器調(diào)用其中的接口沒(méi)什么問(wèn)題,如下圖所示。


? ? ? ??從上圖可以看到,訪問(wèn) user 使用了 8001 端口,訪問(wèn) dict 使用了 8002 端口,如果要為這些服務(wù)提供一個(gè)頁(yè)面,由于不同的服務(wù)使用了不同的端口號(hào),那么在寫(xiě)前端頁(yè)面時(shí)就會(huì)因?yàn)橛卸鄠€(gè)端口而導(dǎo)致難以管理,使得開(kāi)發(fā)變得復(fù)雜。為了解決該問(wèn)題,那么此時(shí),我們可以通過(guò)反向代理來(lái)進(jìn)行完成,比如 Nginx。
二、使用 Nginx?的反向代理功能來(lái)完成請(qǐng)求的分發(fā)
? ? ? ? 在上面拋出的問(wèn)題中,我們可用使用 Nginx 的反向代理功能來(lái)進(jìn)行解決,解決的方法也很容易。這里 Nginx 直接下載一個(gè) Windows 版本的進(jìn)行測(cè)試。對(duì) Nginx 進(jìn)行簡(jiǎn)單的配置,配置如下:
server {listen 9001;server_name localhost;?????????????????location ~ /user/ {proxy_pass http://localhost:8001;}location ~ /dict/ {proxy_pass http://localhost:8002;}}
? ? ? ? 這里通過(guò)配置了兩個(gè) location 完成了服務(wù)的分發(fā),并且可用使用統(tǒng)一的端口 9001,測(cè)試如下圖所示。


? ? ? ? 可用看到,通過(guò)訪問(wèn) localhost 的 9001 端口可用正常的訪問(wèn) service_user 和 service_dict 兩個(gè)服務(wù)。接著,我們寫(xiě)一個(gè)頁(yè)面,通過(guò)頁(yè)面來(lái)調(diào)用 localhost 的 9001 來(lái)訪問(wèn)這兩個(gè)服務(wù)。
三、編寫(xiě)簡(jiǎn)單的頁(yè)面進(jìn)行測(cè)試
? ? ? ??這里使用 vue-admin-template 來(lái)進(jìn)行測(cè)試,我們直接在登錄頁(yè)進(jìn)行測(cè)試,然后通過(guò) F12 的調(diào)試窗口來(lái)進(jìn)行觀察。先添加接口調(diào)用的代碼,代碼如下:
export function getUser() {return request({url: 'http://localhost:9001/admin/user/getUser/1',method: 'get'})}
? ? ? ? 然后再登錄頁(yè)面中進(jìn)行調(diào)用,調(diào)用的代碼如下:
getUsers() {getUser().then(response => {console.log(response)}).catch(error => {console.log(error)})},
? ? ? ? 最后我們讓頁(yè)面打開(kāi)時(shí)就進(jìn)行調(diào)用,代碼如下:
created() {this.getUsers()},
? ? ? ? 然后我們來(lái)觀察調(diào)用的請(qǐng)求,如下圖所示。


? ? ? ??從兩幅圖中可用看出,接口并沒(méi)有調(diào)用成功,因?yàn)榘l(fā)生了跨域的問(wèn)題。我們可以在每個(gè)控制器上增加 @CrossOrigin 注解,也可以給每個(gè)服務(wù)添加一個(gè)配置類。同樣,我們可以在兩個(gè)服務(wù)前面增加一個(gè)網(wǎng)關(guān),讓網(wǎng)關(guān)來(lái)做路由分發(fā)和處理跨域的問(wèn)題。
四、使用 Spring Cloud Gateway?網(wǎng)關(guān)
? ? ? ??網(wǎng)關(guān)的作用比較多,網(wǎng)關(guān)可以做鑒權(quán)、限流、日志等功能,這里只是使用它做一個(gè)路由分發(fā)和處理跨域的問(wèn)題。
? ? ? ? 在項(xiàng)目中創(chuàng)建一個(gè)子模塊,命名為 gateway,接著來(lái)引入它的依賴,依賴如下:
<dependencies><dependency><groupId>com.alibaba.cloudgroupId><artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId><version>2.2.6.RELEASEversion>dependency><dependency><groupId>org.springframework.cloudgroupId><artifactId>spring-cloud-starter-gatewayartifactId><version>2.2.0.RELEASEversion>dependency>dependencies>
? ? ? ??第一個(gè)依賴是做 Nacos 服務(wù)發(fā)現(xiàn)的,第二個(gè)就是網(wǎng)關(guān)的依賴。
? ? ? ? 引入依賴之后,創(chuàng)建 config 包,然后寫(xiě)一個(gè)用于允許跨域的 Bean,代碼如下:
public class CorsConfig {public CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowedHeader("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}}
? ? ? ? 有了上面的代碼就可以讓前端完成跨域請(qǐng)求,這里需要注意,在網(wǎng)關(guān)有了上面的跨域配置,那么在實(shí)際服務(wù)的 Controller 類上面就不可用再使用 @CrossOrigin 注解了,否則會(huì)報(bào)錯(cuò)。
? ? ? ??創(chuàng)建一個(gè) application.properties 文件,然后來(lái)配置路由分發(fā),配置如下:
# 服務(wù)端口server.port=7000# 服務(wù)名spring.application.name=service-gateway# nacos服務(wù)地址spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848#使用服務(wù)發(fā)現(xiàn)路由spring.cloud.gateway.discovery.locator.enabled=true#設(shè)置路由idspring.cloud.gateway.routes[0].id=service-user#設(shè)置路由的urispring.cloud.gateway.routes[0].uri=lb://service-user#設(shè)置路由斷言,代理servicerId為auth-service的/auth/路徑spring.cloud.gateway.routes[0].predicates= Path=/*/user/**#設(shè)置路由idspring.cloud.gateway.routes[1].id=service-dict#設(shè)置路由的urispring.cloud.gateway.routes[1].uri=lb://service-dict#設(shè)置路由斷言,代理servicerId為auth-service的/auth/路徑spring.cloud.gateway.routes[1].predicates= Path=/*/dict/**
? ? ? ? 上面的配置文件中,主要看 spring.cloud.gateway.routes 的配置,這里是數(shù)組,分別配置了兩個(gè)路由規(guī)則,一個(gè)用來(lái)轉(zhuǎn)發(fā)給 service_user 服務(wù),第二個(gè)用來(lái)轉(zhuǎn)發(fā)給 service_dict 服務(wù)。
? ? ? ??同樣要給 gateway 創(chuàng)建一個(gè)啟動(dòng)類,啟動(dòng)類的代碼如下:
public class ServerGatewayApplication{public static void main(String[] args) {SpringApplication.run(ServerGatewayApplication.class, args);}}
? ? ? ? 這樣就可以啟動(dòng)我們的 gateway 了,gateway 的端口號(hào)為 7000。
五、測(cè)試前端調(diào)用
? ? ? ??service-user、service-dict 和 service-gateway 已經(jīng)啟動(dòng)并注冊(cè)到了 Nacos 中,但是現(xiàn)在我們并不能測(cè)試我們的前端頁(yè)面,原因是前端頁(yè)面的地址使用的是 Nginx 的端口,而 Nginx 的規(guī)則仍然是直接轉(zhuǎn)發(fā)給兩個(gè)服務(wù),我們需要修改 Nginx 的配置,修改如下:
server {listen 9001;server_name localhost;?????????location ~ /user/ {proxy_pass http://localhost:7000;}location ~ /dict/ {proxy_pass http://localhost:7000;}}
? ? ? ??可以看到,Nginx 將兩個(gè)請(qǐng)求轉(zhuǎn)發(fā)給了 localhost:7000,也就是轉(zhuǎn)發(fā)給了我們的網(wǎng)關(guān)。那么,我們來(lái)測(cè)試我們的前端頁(yè)面。通過(guò) F12 的調(diào)試窗口來(lái)進(jìn)行查看。如下圖所示。


? ? ? ? 可以看到,我們的請(qǐng)求同樣成功了。前端頁(yè)面請(qǐng)求 localhost:9001 也就是 Nginx 的端口號(hào),然后 Nginx 轉(zhuǎn)發(fā)給?網(wǎng)關(guān),最后網(wǎng)關(guān)路由到具體的服務(wù),這樣就完成了一次前端請(qǐng)求服務(wù)的調(diào)用。如下圖所示。

? ? ? ??同樣的,我們可以讓 Ajax 直接調(diào)用網(wǎng)關(guān)來(lái)訪問(wèn)服務(wù),這里就不再進(jìn)行演示了,大家可以自行測(cè)試。
六、總結(jié)
? ? ? ??本篇文章通過(guò)一個(gè)簡(jiǎn)單的 Demo 完成了一個(gè)簡(jiǎn)單的 網(wǎng)關(guān)功能,該網(wǎng)關(guān)具有 處理跨域請(qǐng)求 和 路由轉(zhuǎn)發(fā) 的功能。當(dāng)然了我們這個(gè)功能過(guò)于的簡(jiǎn)單,但是大家可以自己進(jìn)行擴(kuò)展。比如可以類似如下圖所示。

? ? ? ? gateway、service_user 和 service_dict 同時(shí)部署多臺(tái),Nginx 通過(guò)負(fù)載均衡策略將請(qǐng)求轉(zhuǎn)發(fā)到任意一臺(tái)網(wǎng)關(guān),網(wǎng)關(guān)再將請(qǐng)求分發(fā)到任意一臺(tái)具體的服務(wù)上。如果是這樣做,那么我們的 Demo 看起來(lái)就更有些意思了。

公眾號(hào)內(nèi)回復(fù)?【mongo】 下載 SpringBoot 整合操作 MongoDB 的文檔。
更多文章
