SA实战 ·《SpringCloud Alibaba实战》第13章(一)
大家好,我是冰河~~
在《SpringCloud Alibaba实战》专栏前面的文章中,我们实现了用户微服务、商品微服务和订单微服务之间的远程调用,并且实现了服务调用的负载均衡。也基于阿里开源的Sentinel实现了服务的限流与容错,并详细介绍了Sentinel的核心技术与配置规则,同时,简单介绍了服务网关,并对SpringCloud Gateway的核心架构进行了简要说明 。今天,我们就正式在项目中整合SpringCloud Gateway网关
本章总览
章节概述
今天,我们就在项目中整合SpringCloud Gateway来为项目增加API网关,同时,会将SpringCloud Gateway与Sentinel进行整合实现网关的限流能力。说干就干,小伙伴们跟上发车速度。
项目整合网关
我们需要在项目中增加一个服务网关模块shop-gateway,在服务网关模块中实现网关的能力。此时,我们的项目中就会有用户微服务、商品微服务、订单微服务和服务网关。
新建网关模块
在项目中新建shop-gateway模块,新增网关模块后项目的结构如下图所示。
初步整合SpringCloud Gateway
(1)在服务网关shop-gateway模块的pom.xml文件中添加如下依赖。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
(2)在服务网关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 节点下的配置。
- globalcors:此节点下的配置是为了解决SpringCloud Gateway跨域的问题。
- routes:表示一个路由数组,可以在此节点下配置多个路由信息。
- id:当前路由的唯一标识。
- order:路由的优先级,数字越小表示优先级越高。
- predicates:网关断言,也就是路由转发的条件,也是一个数组,可以配置多个路由转发条件。
- Path:当客户端请求的路径满足Path的规则时,进行路由转发操作。
- filters:网关过滤器,在过滤器中可以修改请求的参数和header信息,以及响应的结果和header信息,网关过滤器也是一个数组,可以配置多个过滤规则。
- StripPrefix:网关在进行路由转发之前,会去掉1层访问路径。
(3)在服务网关shop-gateway模块的io.binghe.shop包下新建GatewayStarter类,表示服务网关的启动类,源码如下所示。
/**
* @author binghe (公众号:冰河技术)
* @version 1.0.0
* @description 服务网关启动类
*/
@SpringBootApplication
public class GatewayStarter {
public static void main(String[] args){
SpringApplication.run(GatewayStarter.class, args);
}
}
(4)由于之前项目中整合了Nacos和Sentinel,所以,在启动项目前,要分别启动Nacos和Sentinel。
- 进入到Nacos的bin目录下,输入如下命令启动Nacos。
startup.cmd -m standalone
- 进入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)分别启动用户微服务、商品微服务、订单微服务和服务网关。
(6)通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001,如下所示。
用户微服务返回的原始数据如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}
可以看到,通过服务网关能够正确访问到用户微服务。
(7)通过服务网关访问商品微服务,在浏览器中输入http://localhost:10001/server-product/product/get/1001,如下所示。
商品微服务返回的原始数据如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}
可以看到,通过服务网关能够正确访问到商品微服务。
(8)通过服务网关访问订单微服务,在浏览器中输入http://localhost:10001/server-order/order/test_sentinel,如下所示。
可以看到,通过服务网关能够正确访问到订单微服务。
网关整合Nacos
在初步整合SpringCloud Gateway中,我们在服务网关模块的application.yml文件中硬编码配置了服务转发的地址,如下所示。
- 硬编码用户微服务地址
uri: http://localhost:8060
- 硬编码商品微服务地址
uri: http://localhost:8070
- 硬编码订单微服务地址
uri: http://localhost:8080
这里,我们将网关整合Nacos实现从Nacos注册中心获取转发的服务地址。
(1)在服务网关shop-gateway模块的pom.xml文件中继续添加如下依赖。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2)在服务网关shop-gateway模块的启动类io.binghe.shop.GatewayStarter上添加@EnableDiscoveryClient注解,如下所示。
/**
* @author binghe (公众号:冰河技术)
* @version 1.0.0
* @description 服务网关启动类
*/
@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相关的配置,如下所示。
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
新增了让SpringCloud Gateway可以发现Nacos中的服务配置,如下所示。
Spring:
cloud:
gateway:
discovery:
locator:
enabled: true
另外,将硬编码的服务转发地址修改成从Nacos中按照名称获取微服务地址,并按照负载均衡策略分发。
- 从Nacos中获取用户微服务
uri: lb://server-user
- 从Nacos中获取商品微服务
uri: lb://server-product
- 从Nacos中获取订单微服务
uri: lb://server-order
其中,lb指的是从Nacos中按照微服务的名称获取微服务地址,并按照负载均衡的策略分发。使用lb从Nacos中获取微服务时,遵循如下的格式。
lb://微服务名称
微服务的名称就是各个微服务在application.yml文件中配置的服务名称。
spring:
application:
name: 服务名称
(4)分别启动用户微服务、商品微服务、订单微服务和服务网关。
(5)通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001,如下所示。
用户微服务返回的原始数据如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}
可以看到,通过服务网关能够正确访问到用户微服务。
(6)通过服务网关访问商品微服务,在浏览器中输入http://localhost:10001/server-product/product/get/1001,如下所示。
商品微服务返回的原始数据如下所示。
{
"id": 1001,
"proName": "华为",
"proPrice": 2399,
"proStock": 100
}
可以看到,通过服务网关能够正确访问到商品微服务。
(7)通过服务网关访问订单微服务,在浏览器中输入http://localhost:10001/server-order/order/test_sentinel,如下所示。
可以看到,通过服务网关能够正确访问到订单微服务。
网关整合Nacos最简配置
SpringCloud Gateway整合Nacos后,可以不用手动指定其他微服务的名称来从Nacos中获取微服务的地址。接下来,我们就来实现SpringCloud Gateway网关整合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 节点及其下面的所有配置。
(2)分别启动用户微服务、商品微服务、订单微服务和服务网关。
(3)通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001,如下所示。
用户微服务返回的原始数据如下所示。
{
"id": 1001,
"username": "binghe",
"password": "c26be8aaf53b15054896983b43eb6a65",
"phone": "13212345678",
"address": "北京"
}
可以看到,通过服务网关能够正确访问到用户微服务。
(4)通过服务网关访问商品微服务,在浏览器中输入http://localhost:10001/server-product/product/get/1001,如下所示。
商品微服务返回的原始数据如下所示。
{
"id": 1001,
"proName": "华为",
"proPrice": 2399,
"proStock": 100
}
可以看到,通过服务网关能够正确访问到商品微服务。
(5)通过服务网关访问订单微服务,在浏览器中输入http://localhost:10001/server-order/order/test_sentinel,如下所示。
可以看到,通过服务网关能够正确访问到订单微服务。
注意:SpringCloud Gateway整合Nacos最简配置时,通过网关访问微服务的格式如下所示。
http(s)://网关IP:网关端口/访问的目标微服务名称/接口地址
网关整合Sentinel限流
Sentinel从1.6.0版本开始,提供了SpringCloud Gateway的适配模块,并且可以提供两种资源维度的限流,一种是route维度;另一种是自定义API分组维度。
- route维度:对application.yml文件中配置的spring.cloud.gateway.routes.id限流,并且资源名为spring.cloud.gateway.routes.id对应的值。
- 自定义API分组维度:利用Sentinel提供的API接口来自定义API分组,并且对这些API分组进行限流。
实现route维度限流
(1)在服务网关shop-gateway模块的pom.xml文件中添加如下依赖。
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
</dependencies>
文章转自公众号:冰河技术