新聞中心
章節(jié)概述
項目整合網(wǎng)關(guān)
我們需要在項目中增加一個服務(wù)網(wǎng)關(guān)模塊shop-gateway,在服務(wù)網(wǎng)關(guān)模塊中實現(xiàn)網(wǎng)關(guān)的能力。此時,我們的項目中就會有用戶微服務(wù)、商品微服務(wù)、訂單微服務(wù)和服務(wù)網(wǎng)關(guān)。

新建網(wǎng)關(guān)模塊
在項目中新建shop-gateway模塊,新增網(wǎng)關(guān)模塊后項目的結(jié)構(gòu)如下圖所示。
初步整合SpringCloud Gateway
(1)在服務(wù)網(wǎng)關(guān)shop-gateway模塊的pom.xml文件中添加如下依賴。
org.springframework.cloud
spring-cloud-starter-gateway
(2)在服務(wù)網(wǎng)關(guān)shop-gateway模塊的resources目錄下新建application.yml文件,并在文件中添加如下配置信息。
server:
port: 10001
spring:
application:
name: server-gateway
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowCredentials: true
allowedHeaders: "*"
routes:
- id: user-gateway
uri: http://localhost:8060
order: 1
predicates:
- Path=/server-user/**
filters:
- StripPrefix=1
- id: product-gateway
uri: http://localhost:8070
order: 1
predicates:
- Path=/server-product/**
filters:
- StripPrefix=1
- id: order-gateway
uri: http://localhost:8080
order: 1
predicates:
- Path=/server-order/**
filters:
- StripPrefix=1
我們重點來看下 spring.cloud.gateway 節(jié)點下的配置。
- globalcors:此節(jié)點下的配置是為了解決SpringCloud Gateway跨域的問題。
- routes:表示一個路由數(shù)組,可以在此節(jié)點下配置多個路由信息。
- id:當(dāng)前路由的唯一標(biāo)識。
- order:路由的優(yōu)先級,數(shù)字越小表示優(yōu)先級越高。
- predicates:網(wǎng)關(guān)斷言,也就是路由轉(zhuǎn)發(fā)的條件,也是一個數(shù)組,可以配置多個路由轉(zhuǎn)發(fā)條件。
- Path:當(dāng)客戶端請求的路徑滿足Path的規(guī)則時,進(jìn)行路由轉(zhuǎn)發(fā)操作。
- filters:網(wǎng)關(guān)過濾器,在過濾器中可以修改請求的參數(shù)和header信息,以及響應(yīng)的結(jié)果和header信息,網(wǎng)關(guān)過濾器也是一個數(shù)組,可以配置多個過濾規(guī)則。
- StripPrefix:網(wǎng)關(guān)在進(jìn)行路由轉(zhuǎn)發(fā)之前,會去掉1層訪問路徑。
(3)在服務(wù)網(wǎng)關(guān)shop-gateway模塊的io.binghe.shop包下新建GatewayStarter類,表示服務(wù)網(wǎng)關(guān)的啟動類,源碼如下所示。
/**
* @author binghe (公眾號:冰河技術(shù))
* @version 1.0.0
* @description 服務(wù)網(wǎng)關(guān)啟動類
*/
@SpringBootApplication
public class GatewayStarter {
public static void main(String[] args){
SpringApplication.run(GatewayStarter.class, args);
}
}
(4)由于之前項目中整合了Nacos和Sentinel,所以,在啟動項目前,要分別啟動Nacos和Sentinel。
- 進(jìn)入到Nacos的bin目錄下,輸入如下命令啟動Nacos。
startup.cmd -m standalone
進(jìn)入Sentinel Jar包所在的目錄,輸入如下命令啟動Sentinel。
java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.4.jar
(5)分別啟動用戶微服務(wù)、商品微服務(wù)、訂單微服務(wù)和服務(wù)網(wǎng)關(guān)。
(6)通過服務(wù)網(wǎng)關(guān)訪問用戶微服務(wù),在瀏覽器中輸入http://localhost:10001/server-user/user/get/1001,如下所示。
用戶微服務(wù)返回的原始數(shù)據(jù)如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到用戶微服務(wù)。
(7)通過服務(wù)網(wǎng)關(guān)訪問商品微服務(wù),在瀏覽器中輸入http://localhost:10001/server-product/product/get/1001,如下所示。
商品微服務(wù)返回的原始數(shù)據(jù)如下所示。
{
"id": 1001,
"proName": "華為",
"proPrice": 2399,
"proStock": 100
}可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到商品微服務(wù)。
(8)通過服務(wù)網(wǎng)關(guān)訪問訂單微服務(wù),在瀏覽器中輸入http://localhost:10001/server-order/order/test_sentinel,如下所示。
可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到訂單微服務(wù)。
網(wǎng)關(guān)整合Nacos
在初步整合SpringCloud Gateway中,我們在服務(wù)網(wǎng)關(guān)模塊的application.yml文件中硬編碼配置了服務(wù)轉(zhuǎn)發(fā)的地址,如下所示。
- 硬編碼用戶微服務(wù)地址
uri: http://localhost:8060
- 硬編碼商品微服務(wù)地址
uri: http://localhost:8070
- 硬編碼訂單微服務(wù)地址
uri: http://localhost:8080
這里,我們將網(wǎng)關(guān)整合Nacos實現(xiàn)從Nacos注冊中心獲取轉(zhuǎn)發(fā)的服務(wù)地址。
(1)在服務(wù)網(wǎng)關(guān)shop-gateway模塊的pom.xml文件中繼續(xù)添加如下依賴。
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
(2)在服務(wù)網(wǎng)關(guān)shop-gateway模塊的啟動類io.binghe.shop.GatewayStarter上添加@EnableDiscoveryClient注解,如下所示。
/**
* @author binghe (公眾號:冰河技術(shù))
* @version 1.0.0
* @description 服務(wù)網(wǎng)關(guān)啟動類
*/
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayStarter {
public static void main(String[] args){
SpringApplication.run(GatewayStarter.class, args);
}
}
(3)將application.yml備份一份,命名為application-simple.yml,并修改application.yml配置文件,修改后的文件如下所示。
server:
port: 10001
spring:
application:
name: server-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowCredentials: true
allowedHeaders: "*"
discovery:
locator:
enabled: true
routes:
- id: user-gateway
uri: lb://server-user
order: 1
predicates:
- Path=/server-user/**
filters:
- StripPrefix=1
- id: product-gateway
uri: lb://server-product
order: 1
predicates:
- Path=/server-product/**
filters:
- StripPrefix=1
- id: order-gateway
uri: lb://server-order
order: 1
predicates:
- Path=/server-order/**
filters:
- StripPrefix=1
上述配置中增加了Nacos相關(guān)的配置,如下所示。
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
新增了讓SpringCloud Gateway可以發(fā)現(xiàn)Nacos中的服務(wù)配置,如下所示。
Spring:
cloud:
gateway:
discovery:
locator:
enabled: true
另外,將硬編碼的服務(wù)轉(zhuǎn)發(fā)地址修改成從Nacos中按照名稱獲取微服務(wù)地址,并按照負(fù)載均衡策略分發(fā)。
- 從Nacos中獲取用戶微服務(wù)
uri: lb://server-user
- 從Nacos中獲取商品微服務(wù)
uri: lb://server-product
- 從Nacos中獲取訂單微服務(wù)
uri: lb://server-order
其中,lb指的是從Nacos中按照微服務(wù)的名稱獲取微服務(wù)地址,并按照負(fù)載均衡的策略分發(fā)。使用lb從Nacos中獲取微服務(wù)時,遵循如下的格式。
lb://微服務(wù)名稱
微服務(wù)的名稱就是各個微服務(wù)在application.yml文件中配置的服務(wù)名稱。
spring:
application:
name: 服務(wù)名稱
(4)分別啟動用戶微服務(wù)、商品微服務(wù)、訂單微服務(wù)和服務(wù)網(wǎng)關(guān)。
(5)通過服務(wù)網(wǎng)關(guān)訪問用戶微服務(wù),在瀏覽器中輸入http://localhost:10001/server-user/user/get/1001,如下所示。
用戶微服務(wù)返回的原始數(shù)據(jù)如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到用戶微服務(wù)。
(6)通過服務(wù)網(wǎng)關(guān)訪問商品微服務(wù),在瀏覽器中輸入http://localhost:10001/server-product/product/get/1001,如下所示。
商品微服務(wù)返回的原始數(shù)據(jù)如下所示。
{
"id": 1001,
"proName": "華為",
"proPrice": 2399,
"proStock": 100
}可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到商品微服務(wù)。
(7)通過服務(wù)網(wǎng)關(guān)訪問訂單微服務(wù),在瀏覽器中輸入http://localhost:10001/server-order/order/test_sentinel,如下所示。
可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到訂單微服務(wù)。
網(wǎng)關(guān)整合Nacos最簡配置
SpringCloud Gateway整合Nacos后,可以不用手動指定其他微服務(wù)的名稱來從Nacos中獲取微服務(wù)的地址。接下來,我們就來實現(xiàn)SpringCloud Gateway網(wǎng)關(guān)整合Nacos的最簡配置。
(1)將application.yml備份一份,命名為application-nacos.yml,并修改application.yml配置文件,修改后的文件如下所示。
server:
port: 10001
spring:
application:
name: server-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowCredentials: true
allowedHeaders: "*"
discovery:
locator:
enabled: true
可以看到,在application.yml文件中,去掉了spring.cloud.gateway.routes 節(jié)點及其下面的所有配置。
(2)分別啟動用戶微服務(wù)、商品微服務(wù)、訂單微服務(wù)和服務(wù)網(wǎng)關(guān)。
(3)通過服務(wù)網(wǎng)關(guān)訪問用戶微服務(wù),在瀏覽器中輸入http://localhost:10001/server-user/user/get/1001,如下所示。
用戶微服務(wù)返回的原始數(shù)據(jù)如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到用戶微服務(wù)。
(4)通過服務(wù)網(wǎng)關(guān)訪問商品微服務(wù),在瀏覽器中輸入http://localhost:10001/server-product/product/get/1001,如下所示。
商品微服務(wù)返回的原始數(shù)據(jù)如下所示。
{
"id": 1001,
"proName": "華為",
"proPrice": 2399,
"proStock": 100
}可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到商品微服務(wù)。
(5)通過服務(wù)網(wǎng)關(guān)訪問訂單微服務(wù),在瀏覽器中輸入http://localhost:10001/server-order/order/test_sentinel,如下所示。
可以看到,通過服務(wù)網(wǎng)關(guān)能夠正確訪問到訂單微服務(wù)。
注意:SpringCloud Gateway整合Nacos最簡配置時,通過網(wǎng)關(guān)訪問微服務(wù)的格式如下所示。
http(s)://網(wǎng)關(guān)IP:網(wǎng)關(guān)端口/訪問的目標(biāo)微服務(wù)名稱/接口地址
網(wǎng)關(guān)整合Sentinel限流
Sentinel從1.6.0版本開始,提供了SpringCloud Gateway的適配模塊,并且可以提供兩種資源維度的限流,一種是route維度;另一種是自定義API分組維度。
- route維度:對application.yml文件中配置的spring.cloud.gateway.routes.id限流,并且資源名為spring.cloud.gateway.routes.id對應(yīng)的值。
- 自定義API分組維度:利用Sentinel提供的API接口來自定義API分組,并且對這些API分組進(jìn)行限流。
實現(xiàn)route維度限流
(1)在服務(wù)網(wǎng)關(guān)shop-gateway模塊的pom.xml文件中添加如下依賴。
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
com.alibaba.cloud
spring-cloud-alibaba-sentinel-gateway
org.springframework.cloud
spring-cloud-starter-gateway
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.csp
sentinel-spring-cloud-gateway-adapter
(2)在服務(wù)網(wǎng)關(guān)shop-gateway模塊中新建io.binghe.shop.config包,并在包下新建GatewayConfig類?;赟entinel 的Gateway限流是通過其提供的Filter來完成的,使用時只需注入對應(yīng)的SentinelGatewayFilter實例以及 SentinelGatewayBlockExceptionHandler 實例即可。
GatewayConfig類的源代碼如下所示。
/**
* @author binghe (公眾號:冰河技術(shù))
* @version 1.0.0
* @description 網(wǎng)關(guān)配置類
*/
@Configuration
public class GatewayConfig {
private final ListviewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
@Value("${spring.cloud.gateway.discovery.locator.route-id-prefix}")
private String routeIdPrefix;
public GatewayConfig(ObjectProvider> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* 初始化一個限流的過濾器
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct
public void init() {
this.initGatewayRules();
this.initBlockHandlers();
}
/**
* 配置初始化的限流參數(shù)
*/
private void initGatewayRules() {
Setrules = new HashSet<>();
/**
* Sentinel整合SpringCloud Gateway使用的API類型為Route ID類型,也就是基于route維度時,
* 由于Sentinel為SpringCloud Gateway網(wǎng)關(guān)生成的API名稱規(guī)則如下:
* 生成的規(guī)則為:${spring.cloud.gateway.discovery.locator.route-id-prefix}后面直接加上目標(biāo)微服務(wù)的名稱,如下所示。
* ${spring.cloud.gateway.discovery.locator.route-id-prefix}目標(biāo)微服務(wù)的名稱
* 其中,${spring.cloud.gateway.discovery.locator.route-id-prefix}是在yml文件中配置的訪問前綴
*
* 為了讓通過服務(wù)網(wǎng)關(guān)訪問目標(biāo)微服務(wù)鏈接后,請求鏈路中生成的API名稱與流控規(guī)則中生成的API名稱一致,以達(dá)到啟動項目即可實現(xiàn)訪問鏈接的限流效果,
* 而無需登錄Setinel管理界面手動配置限流規(guī)則,可以將
* resource參數(shù)設(shè)置為${spring.cloud.gateway.discovery.locator.route-id-prefix}目標(biāo)微服務(wù)的名稱
*
* 當(dāng)然,如果不按照上述配置,也可以在項目啟動后,通過服務(wù)網(wǎng)關(guān)訪問目標(biāo)微服務(wù)鏈接后,在Sentinel管理界面的請求鏈路中找到對應(yīng)的API名稱所代表的請求鏈路,
* 然后手動配置限流規(guī)則。
**/
// //用戶微服務(wù)網(wǎng)關(guān)
// rules.add(this.getGatewayFlowRule("user-gateway"));
// //商品微服務(wù)網(wǎng)關(guān)
// rules.add(this.getGatewayFlowRule("product-gateway"));
// //訂單微服務(wù)網(wǎng)關(guān)
// rules.add(this.getGatewayFlowRule("order-gateway"));
//用戶微服務(wù)網(wǎng)關(guān)
rules.add(this.getGatewayFlowRule(getResource("server-user")));
//商品微服務(wù)網(wǎng)關(guān)
rules.add(this.getGatewayFlowRule(getResource("server-product")));
//訂單微服務(wù)網(wǎng)關(guān)
rules.add(this.getGatewayFlowRule(getResource("server-order")));
//加載規(guī)則
GatewayRuleManager.loadRules(rules);
}
private String getResource(String targetServiceName){
if (routeIdPrefix == null){
routeIdPrefix = "";
}
return routeIdPrefix.concat(targetServiceName);
}
private GatewayFlowRule getGatewayFlowRule(String resource){
//傳入資源名稱生成GatewayFlowRule
GatewayFlowRule gatewayFlowRule = new GatewayFlowRule(resource);
//限流閾值
gatewayFlowRule.setCount(1);
//統(tǒng)計的時間窗口,單位為
gatewayFlowRule.setIntervalSec(1);
return gatewayFlowRule;
}
/**
* 配置限流的異常處理器
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
/**
* 自定義限流異常頁面
*/
private void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public MonohandleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map = new HashMap<>();
map.put("code", 1001);
map.put("codeMsg", "接口被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON_UTF8).
body(BodyInserters.fromObject(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
GatewayConfig類的源代碼看上去比較多,但是都是一些非常簡單的方法,冰河在這里就不再贅述了。
這里有個需要特別注意的地方:
Sentinel1.8.4整合SpringCloud Gateway使用的API類型為Route ID類型時,也就是基于route維度時,由于Sentinel為SpringCloud Gateway網(wǎng)關(guān)生成的API名稱規(guī)則如下:
生成的規(guī)則為:${spring.cloud.gateway.discovery.locator.route-id-prefix}后面直接加上目標(biāo)微服務(wù)的名稱,如下所示。
{spring.cloud.gateway.discovery.locator.route-id-prefix}目標(biāo)微服務(wù)的名稱。其中,${spring.cloud.gateway.discovery.locator.route-id-prefix}是在yml文件中配置的訪問前綴。
為了讓通過服務(wù)網(wǎng)關(guān)訪問目標(biāo)微服務(wù)鏈接后,請求鏈路中生成的API名稱與流控規(guī)則中生成的API名稱一致,以達(dá)到啟動項目即可實現(xiàn)訪問鏈接的限流效果,而無需登錄Setinel管理界面手動配置限流規(guī)則,可以將生成GatewayFlowRule對象的resource參數(shù)設(shè)置為${spring.cloud.gateway.discovery.locator.route-id-prefix}目標(biāo)微服務(wù)的名稱
當(dāng)然,如果不按照上述配置,也可以在項目啟動后,通過服務(wù)網(wǎng)關(guān)訪問目標(biāo)微服務(wù)鏈接后,在Sentinel管理界面的請求鏈路中找到對應(yīng)的API名稱所代表的請求鏈路,然后手動配置限流規(guī)則。
(3)將服務(wù)網(wǎng)關(guān)shop-gateway模塊的application.yml文件備份一份名稱為application-nacos-simple.yml的文件,并將application.yml文件的內(nèi)容修改成如下所示。
server:
port: 10001
spring:
application:
name: server-gateway
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
port: 7777
dashboard: 127.0.0.1:8888
web-context-unify: false
eager: true
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowCredentials: true
allowedHeaders: "*"
discovery:
locator:
enabled: true
route-id-prefix: gateway-
其中:
- spring.cloud.sentinel.eager表示程序啟動時,流控規(guī)則是否立即注冊到Sentinel,配置為true表示立即注冊到Sentinel。
- spring.cloud.gateway.discovery.locator.route-id-prefix:生成流控規(guī)則API名稱的前綴。
(4)在IDEA中配置啟動服務(wù)網(wǎng)關(guān)shop-gateway模塊的參數(shù)-Dcsp.sentinel.app.type=1,如下所示。
如果是在命令行啟動網(wǎng)關(guān)服務(wù)的Ja
文章名稱:服務(wù)網(wǎng)關(guān):項目整合SpringCloudGateway網(wǎng)關(guān)
本文地址:http://m.5511xx.com/article/cdjchei.html


咨詢
建站咨詢
