文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

服务网关:项目整合 SpringCloud Gateway 网关

2024-12-02 01:47

关注

项目整合网关

我们需要在项目中增加一个服务网关模块shop-gateway,在服务网关模块中实现网关的能力。此时,我们的项目中就会有用户微服务、商品微服务、订单微服务和服务网关。

新建网关模块

在项目中新建shop-gateway模块,新增网关模块后项目的结构如下图所示。

初步整合SpringCloud Gateway

(1)在服务网关shop-gateway模块的pom.xml文件中添加如下依赖。

<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
dependencies>

(2)在服务网关shop-gateway模块的resources目录下新建application.yml文件,并在文件中添加如下配置信息。

server:
port: 10001
spring:
application:
name: server-gateway
cloud:
gateway:
globalcors:
cors-configurations:
'[
@SpringBootApplication
public class GatewayStarter {
public static void main(String[] args){
SpringApplication.run(GatewayStarter.class, args);
}
}

(4)由于之前项目中整合了Nacos和Sentinel,所以,在启动项目前,要分别启动Nacos和Sentinel。

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,
"proName": "华为",
"proPrice": 2399,
"proStock": 100
}

可以看到,通过服务网关能够正确访问到商品微服务。

(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.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>

(2)在服务网关shop-gateway模块的启动类io.binghe.shop.GatewayStarter上添加@EnableDiscoveryClient注解,如下所示。


@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:
'[
@Configuration
public class GatewayConfig {

private final List<ViewResolver> viewResolvers;

private final ServerCodecConfigurer serverCodecConfigurer;

@Value("${spring.cloud.gateway.discovery.locator.route-id-prefix}")
private String routeIdPrefix;

public GatewayConfig(ObjectProvider<List<ViewResolver>> 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();
}


private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();


// //用户微服务网关
// rules.add(this.getGatewayFlowRule("user-gateway"));
// //商品微服务网关
// rules.add(this.getGatewayFlowRule("product-gateway"));
// //订单微服务网关
// rules.add(this.getGatewayFlowRule("order-gateway"));
//用户微服务网关
rules.add(this.getGatewayFlowRule(getResource("server-user")));
//商品微服务网关
rules.add(this.getGatewayFlowRule(getResource("server-product")));
//订单微服务网关
rules.add(this.getGatewayFlowRule(getResource("server-order")));
//加载规则
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);
//统计的时间窗口,单位为
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 Mono<ServerResponse> handleRequest(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网关生成的API名称规则如下:

生成的规则为:${spring.cloud.gateway.discovery.locator.route-id-prefix}后面直接加上目标微服务的名称,如下所示。

{spring.cloud.gateway.discovery.locator.route-id-prefix}目标微服务的名称。其中,${spring.cloud.gateway.discovery.locator.route-id-prefix}是在yml文件中配置的访问前缀。

为了让通过服务网关访问目标微服务链接后,请求链路中生成的API名称与流控规则中生成的API名称一致,以达到启动项目即可实现访问链接的限流效果,而无需登录Setinel管理界面手动配置限流规则,可以将生成GatewayFlowRule对象的resource参数设置为${spring.cloud.gateway.discovery.locator.route-id-prefix}目标微服务的名称

当然,如果不按照上述配置,也可以在项目启动后,通过服务网关访问目标微服务链接后,在Sentinel管理界面的请求链路中找到对应的API名称所代表的请求链路,然后手动配置限流规则。

(3)将服务网关shop-gateway模块的application.yml文件备份一份名称为application-nacos-simple.yml的文件,并将application.yml文件的内容修改成如下所示。

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:
'[
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayStarter {
public static void main(String[] args){
System.setProperty("csp.sentinel.app.type", "1");
SpringApplication.run(GatewayStarter.class, args);
}
}

(5)分别启动用户微服务、商品微服务、订单微服务和服务网关,启动后会在Sentinel管理界面左侧菜单栏中看到server-gateway菜单,如下所示。

在server-gateway菜单下的流控规则子菜单中可以看到网关的流控规则已经注册到Sentinel,如下所示。

(6)通过服务网关访问用户微服务,在浏览器中输入http://localhost:10001/server-user/user/get/1001,不断刷新页面,如下所示。

用户微服务返回的原始数据如下所示。

{
"code": 1001,
"codeMsg": "接口被限流了"
}

可以看到,通过服务网关不断刷新用户微服务时,触发了服务限流,并返回了自定义的限流结果数据。

(7)通过服务网关访问商品微服务,在浏览器中输入http://localhost:10001/server-product/product/get/1001,不断刷新页面,如下所示。

商品微服务返回的原始数据如下所示。

{
"code": 1001,
"codeMsg": "接口被限流了"
}

可以看到,通过服务网关不断刷新商品微服务时,触发了服务限流,并返回了自定义的限流结果数据。

(8)通过服务网关访问订单微服务,在浏览器中输入http://localhost:10001/server-order/order/test_sentinel,不断刷新页面,如下所示。

可以看到,通过服务网关不断刷新订单微服务时,触发了服务限流,并返回了自定义的限流结果数据。

实现自定义API分组维度限流

前面,我们实现了route维度的限流,接下来,我们再基于Sentinel与SpringCloud gateway实现自定义API分组维度的限流。

(1)在服务网关shop-gateway模块的io.binghe.shop.config.GatewayConfig配置类中新增initCustomizedApis()方法,初始化API管理的信息,源码如下所示。

private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();
ApiDefinition api1 = new ApiDefinition("user_api1")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
///server-user/user/api1 开头的请求
add(new ApiPathPredicateItem().setPattern("/server-user/user/api1/**").
setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
ApiDefinition api2 = new ApiDefinition("user_api2")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
///server-user/user/api2/demo1 完成的url路径匹配
add(new ApiPathPredicateItem().setPattern("/server-user/user/api2/demo1"));
}});
definitions.add(api1);
definitions.add(api2);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}

上述代码中,配置了两个API分组,每个API分组的规则如下。

(2)在服务网关shop-gateway模块的io.binghe.shop.config.GatewayConfig配置类中init()方法中调用initCustomizedApis()方法,为了避免route维度的限流对自定义API分组维度的限流产生影响,这里,同时在init()方法中注释掉调用initGatewayRules()方法,修改后的init()方法的代码如下所示。

@PostConstruct
public void init() {
//this.initGatewayRules();
this.initBlockHandlers();
this.initCustomizedApis();
}

(3)在用户微服务shop-user的io.binghe.shop.user.controller.UserController类中新增四个测试接口,源码如下所示。

@GetMapping(value = "/api1/demo1")
public String api1Demo1(){
log.info("访问了api1Demo1接口");
return "api1Demo1";
}
@GetMapping(value = "/api1/demo2")
public String api1Demo2(){
log.info("访问了api1Demo2接口");
return "api1Demo2";
}

@GetMapping(value = "/api2/demo1")
public String api2Demo1(){
log.info("访问了api2Demo1接口");
return "api2Demo1";
}
@GetMapping(value = "/api2/demo2")
public String api2Demo2(){
log.info("访问了api2Demo2接口");
return "api2Demo2";
}

(4)分别启动用户微服务、商品微服务、订单微服务和服务网关,启动后会在Sentinel管理界面左侧菜单栏中看到server-gateway菜单,如下所示。

此时,由于我们注释了调用以route维度限流的方法,所以,在流控规则里的限流规则为空,如下所示。

在API管理里面会发现我们定义的API分组已经自动注册到Sentinel中了,如下所示。

(5)在Sentinel管理界面的流控规则中,新增网关流控规则,如下所示。

点击新增网关流控规则后,会弹出新增网关流控规则配置框,按照如下方式为user_api1分组配置限流规则。

点击新增按钮后,按照同样的方式为user_api2分组配置限流规则。

配置完毕后,在流控规则中的限流规则如下所示。

(6)预期的测试结果如下。

注意:只有最后一个不会被限流。

(7)在浏览器上频繁访问http://localhost:10001/server-user/user/api1/demo1,如下所示。

返回的原始数据如下所示。

{
"code": 1001,
"codeMsg": "接口被限流了"
}

说明触发了服务限流,并返回了自定义的限流结果数据。

(8)在浏览器上频繁访问http://localhost:10001/server-user/user/api1/demo2,如下所示。

返回的原始数据如下所示。

{
"code": 1001,
"codeMsg": "接口被限流了"
}

说明触发了服务限流,并返回了自定义的限流结果数据。

(9)在浏览器上频繁访问http://localhost:10001/server-user/user/api2/demo1,如下所示。

返回的原始数据如下所示。

{
"code": 1001,
"codeMsg": "接口被限流了"
}

说明触发了服务限流,并返回了自定义的限流结果数据。

(10)在浏览器上频繁访问http://localhost:10001/server-user/user/api2/demo2,如下所示。

可以看到,访问http://localhost:10001/server-user/user/api2/demo2时,无论访问的频率多频繁,都不会触发Sentinel限流。

至此,我们就成功在项目中整合了SpringCloud Gateway网关,并通过Sentinel整合SpringCloud Gateway实现了网关的限流操作。

来源:冰河技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯