飞道的博客

【项目实战】Nacos下发路由配置实现Spring Cloud Gateway的动态路由

297人阅读  评论(0)

Spring Cloud Gateway网关的使用和Nacos下发路由配置实现Spring Cloud Gateway的动态路由

一、微服务网关概述

1.1 微服务网关诞生背景

不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性

  • 存在跨域请求,在一定场景下处理相对复杂

  • 认证复杂,每个服务都需要独立认证

  • 难以重构,随着项目的迭代,可能需要重新划分微服务。
    例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难

以上这些问题可以借助网关解决

1.2 微服务网关是什么?

又名:API网关

网关是介于客户端和服务器端之间的中间层,所有的外部请求都统一发到网关服务(base-gateway),网关再根据路由规则转发到相应服务,所以尽管我们的微服务可能会有成百上千个子服务,我们只需配置好路由规则将网关对外就可以了,服务器防火墙也只要开放网关服务的端口(9999)。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由网关来做,这样既提高业务灵活性又不缺安全性

1.3 微服务网关的特点

【服务器、中间层】API网关是一个服务器,介于客户端和服务器端之间的中间层,
【系统入口,请求先到它】API网关是系统的唯一入口。所有的外部请求都会先经过它这一层
【网关就是门卫】网关就好比一个公司的门卫。屏蔽内部细节,统一对外服务接口。
【设计模式-外观模式】从面向对象设计的角度看,它与外观模式类似。
【核心功能】API网关封装了系统内部架构,为每个客户端提供一个定制的API。
【多职能】API网关可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
【核心要点】所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。
通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
API网关 所有的客户端请求通过这个网关访问后台的服务。
可以使用一定的路由配置来判断某一个URL由哪个服务来处理。并从Eureka获取注册的服务来转发请求。

1.4 微服务网关架构图

如图所示:


1.5 微服务网关的优点

  • 安全
    只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。

  • 易于监控。
    可以在网关收集监控数据并将其推送到外部系统进行分析。

  • 易于认证
    可以在网关上进行认证,再将请求转发到后端的微服务,而无须在每个微服务中进行认证。减少了客户端与各个微服务之间的交互次数,易于统一鉴权。

二 、SpringCloud Gateway介绍

2.1 SpringCloud Gateway 是什么?

SpringCloud的网关路由更新迭代如下

技术名称 说明
zuul1.x Zuul 是 Netflix 开源的微服务网关
zuul2.x Netflix 公司不再维护了
Spring Cloud Gateway 根据zuul2.x,Spring团队自己实现了一套,叫Spring Cloud Gateway,SpringCloud本身的网关服务

2.2 微服务网关的核心

网关中有两个重要的概念,那就是路由配置路由规则

  • 路由配置 (路由转发)

是指配置某请求路径路由到指定的目的地址。
接收一切外界请求,转发到后端的微服务上去。

  • 路由规则(过滤器)

指匹配到路由配置之后,再根据路由规则进行转发处理。
在服务网关中,可以完成一系列的横切功能(见:服务网关基本功能),都可通过过滤器完成
(其实路由转发也是通过过滤器实现的)

三、动态路由实现

Spring Cloud Gateway作为所有请求流量的入口,在实际生产环境中为了保证高可靠和高可用,尽量避免重启,需要实现Spring Cloud Gateway动态路由配置。

2.1 路由模块(base-gateway)启动时加载路由配置并开启监听实现动态(DynamicRouteInit.java)

//初始化网关路由
@Slf4j
@Configuration
@AllArgsConstructor
public class DynamicRouteInit {
   
	private RouteDefinitionWriter routeDefinitionWriter;
	private NacosConfigUtils nacosConfigUtils;
	@PostConstruct
	public void initRoute() {
   
		try {
   
			ConfigService configService = nacosConfigUtils.getConfigService();
			String content = configService.getConfig(CommonConstants.CONFIG_DATA_ID_DYNAMIC_ROUTES, CommonConstants.CONFIG_GROUP, CommonConstants.CONFIG_TIMEOUT_MS);
			log.info("初始化网关路由开始");
			updateRoute(content);
			log.info("初始化网关路由完成");
			//开户监听,实现动态
			configService.addListener(CommonConstants.CONFIG_DATA_ID_DYNAMIC_ROUTES, CommonConstants.CONFIG_GROUP, new Listener() {
   
				@Override
				public void receiveConfigInfo(String configInfo) {
   
					log.info("更新网关路由开始");
					updateRoute(configInfo);
					log.info("更新网关路由完成");
				}
				@Override
				public Executor getExecutor() {
   
					return null;
				}
			});
		} catch (NacosException e) {
   
			log.error("加载路由出错:{}", e.getErrMsg());
		}
	}

	public void updateRoute(String content){
   
		Yaml yaml = new Yaml();
		GatewayRouteList gatewayRouteList = yaml.loadAs(content,GatewayRouteList.class);
		gatewayRouteList.getRoutes().forEach(route -> {
   
			log.info("加载路由:{},{}", route.getId(), route);
			routeDefinitionWriter.save(Mono.just(route)).subscribe();
		});
	}
}

 

2.2 Nacos中配置路由信息(dynamic_routes)


动态路由就是这么简单,更新路由配置不再需要重启服务


转载:https://blog.csdn.net/wstever/article/details/128638771
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场