gateway 动态路由
gataway动态路基于数据库读取路由信息进行路由网关拦截等功能
1:需要使用注册中心 nacos eureka 等都可以
2:需要重写gateway的方法
package com.lary.gatewaydemo.ceshi.service;import com.alibaba.fastjson.JSON;
import com.lary.gatewaydemo.ceshi.entity.GatewayRoute;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import static com.lary.gatewaydemo.ceshi.service.RedisRouteDefinitionRepository.GATEWAY_ROUTES;/*** @program: gateway* @description: sss* @author: lary* @create: 2021-08-05 15:28*/
@Slf4j
@Service
public class GatewayServiceHandler implements ApplicationEventPublisherAware, CommandLineRunner {@Autowiredprivate RedisRouteDefinitionRepository routeDefinitionWriter;private ApplicationEventPublisher publisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.publisher = applicationEventPublisher;}@Autowiredprivate RedisTemplate redisTemplate;@Resourceprivate GatewayRouteService gatewayRouteService;@Overridepublic void run(String... args){this.loadRouteConfig();}public String loadRouteConfig() {log.info("====开始加载=====网关配置信息=========");//删除redis里面的路由配置信息redisTemplate.delete(GATEWAY_ROUTES);//从数据库拿到基本路由配置List<GatewayRoute> gatewayRouteList = gatewayRouteService.gatewayRoutes();gatewayRouteList.forEach(gatewayRoute -> {RouteDefinition definition=handleData(gatewayRoute);routeDefinitionWriter.save(Mono.just(definition)).subscribe();});this.publisher.publishEvent(new RefreshRoutesEvent(this));log.info("=======网关配置信息===加载完成======");return "success";}public void saveRoute(GatewayRoute gatewayRoute){RouteDefinition definition=handleData(gatewayRoute);routeDefinitionWriter.save(Mono.just(definition)).subscribe();this.publisher.publishEvent(new RefreshRoutesEvent(this));}public void update(GatewayRoute gatewayRoute) {RouteDefinition definition=handleData(gatewayRoute);try {this.routeDefinitionWriter.delete(Mono.just(definition.getId()));routeDefinitionWriter.save(Mono.just(definition)).subscribe();this.publisher.publishEvent(new RefreshRoutesEvent(this));} catch (Exception e) {e.printStackTrace();}}public void deleteRoute(String routeId){routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();this.publisher.publishEvent(new RefreshRoutesEvent(this));}/*** 路由数据转换公共方法* @param gatewayRoute* @return*/private RouteDefinition handleData(GatewayRoute gatewayRoute){RouteDefinition definition = new RouteDefinition();Map<String, String> predicateParams = new HashMap<>(8);PredicateDefinition predicate = new PredicateDefinition();FilterDefinition filterDefinition = new FilterDefinition();Map<String, String> filterParams = new HashMap<>(8);URI uri = null;if(gatewayRoute.getUri().startsWith("http")){//http地址uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();}else{//注册中心uri = UriComponentsBuilder.fromUriString("lb://"+gatewayRoute.getUri()).build().toUri();}definition.setId(gatewayRoute.getServiceId());// 名称是固定的,spring gateway会根据名称找对应的PredicateFactorypredicate.setName("Path");String predicate1 = gatewayRoute.getPredicates();predicateParams.put("pattern",gatewayRoute.getPredicates());predicate.setArgs(predicateParams);// 名称是固定的, 路径去前缀filterDefinition.setName("StripPrefix");// 作用为去前缀 意思就是列入我的实际接口为localhost:8080/ceshi/ceshio2// 那么他就会去掉ceshi 接口变为localhost:8080/ceshio2接口肯定不通,所以// 例如我的地址为/ga/demo/**那么请求的地址也为这个。然后接口会去掉ga,ga即可调通filterParams.put("_genkey_0", gatewayRoute.getFilters().toString());filterDefinition.setArgs(filterParams);definition.setPredicates(Arrays.asList(predicate));definition.setFilters(Arrays.asList(filterDefinition));definition.setUri(uri);definition.setOrder(Integer.parseInt(gatewayRoute.getSort()));System.out.println("definition:" + JSON.toJSONString(definition));return definition;}
package com.lary.gatewaydemo.ceshi.service;import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.util.ArrayList;
import java.util.List;/*** @program: gateway* @description: peizhi* @author: lary* @create: 2021-08-05 15:25*//***将定义好的路由表信息通过此类读写到redis中*/
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {public static final String GATEWAY_ROUTES = "gateway_routes";@Autowiredprivate RedisTemplate redisTemplate;//请注意,此方法很重要,从redis取路由信息的方法,官方核心包要用,核心路由功能都是从redis取的@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {System.out.println("===============RedisRouteDefinitionRepository==============");List<RouteDefinition> routeDefinitions = new ArrayList<>();redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream().forEach(routeDefinition -> {routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class));});return Flux.fromIterable(routeDefinitions);}@Overridepublic Mono<Void> save(Mono<RouteDefinition> route) {System.out.println("===============RedisRouteDefinitionRepository---save ==============");return route.flatMap(routeDefinition -> {redisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(),JSON.toJSONString(routeDefinition));return Mono.empty();});}@Overridepublic Mono<Void> delete(Mono<String> routeId) {System.out.println("===============RedisRouteDefinitionRepository---delete ==============");return routeId.flatMap(id -> {if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES, id)) {redisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);return Mono.empty();}return Mono.defer(() -> Mono.error(new NotFoundException("路由文件没有找到: " + routeId)));});}}
配置文件:
eureka:client:service-url:defaultZone: http://127.0.0.1:8040/eurekaserver:port: 8082
spring:application:name: service-gatewaydatasource:driverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.7.34:3306/mx_institute?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghaiusername: meixpassword: Fvjm3JibEgoPuYzfSZePredis:host: 127.0.0.1port: 6379password: 123456database: 1
数据库数据:
CREATE TABLE `gateway_route` (`id` bigint(20) NOT NULL,`route_id` varchar(255) DEFAULT NULL,`uri` varchar(255) NOT NULL,`predicates` varchar(255) NOT NULL,`filters` varchar(255) DEFAULT NULL,`sort` int(11) DEFAULT '0',`remarks` varchar(255) DEFAULT NULL,`create_time` date DEFAULT NULL,`update_time` date DEFAULT NULL,`is_deleted` int(11) DEFAULT '0',`version` int(11) DEFAULT '1',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
总结:如果把服务都写在数据库中,则无法做负载均衡,需要测试,所以目前引用注册中心进行,两个子服务的application-name都是一样即可做到负载均衡
gateway 动态路由相关推荐
- Spring Cloud Gateway 动态路由管理,一点都不吹,应该没有比这更好的管理系统了吧
本文介绍的 Spring Cloud Gateway 动态路由.不比其他博客通篇 copy 的 Gateway 动态路由,直接上干货!!!为你们提供了一套完整的动态路由管理系统.文末附本文全套代码 ...
- gateway动态路由_无语!SpringCloud Gateway动态路由之Nacos,我已经讲得很清楚了
前言 当我们的网关Gateway程序开发完成之后,需要部署到生产环境,这个时候你的程序不能是单点运行的,肯定是多节点启动(独立部署或者docker等容器部署),防止单节点故障导致整个服务不能访问,网关 ...
- gateway动态路由_微服务与网关技术(SIA-GateWay)
一.背景 软件架构,总是在不断的演进中... 把时间退回到二十年之前,当时企业级领域研发主要推崇的还是C/S模式,PB.Delphi这样的开发软件是企业应用开发的主流.随着时间的推移,基于浏览器的B/ ...
- gateway动态路由_微服务中的网关技术:Gateway
技术/杨33 一.Gateway是什么 为微服务提供一种简单有效的统一的API路由管理方式. Gateway是基于WebFlux框架实现的,而WebFlux框架底层使用了高性能的Reactor模式通讯 ...
- Nacos + Spring Cloud Gateway动态路由配置
前言 Nacos最近项目一直在使用,其简单灵活,支持更细粒度的命令空间,分组等为麻烦复杂的环境切换提供了方便:同时也很好支持动态路由的配置,只需要简单的几步即可.在国产的注册中心.配置中心中比较突出, ...
- Spring Cloud Gateway动态路由实现
Gateway上线部署分析 当你的网关程序开发完成之后,需要部署到生产环境,这个时候你的程序不能是单点运行的,肯定是多节点启动(独立部署或者docker等容器部署),防止单节点故障导致整个服务不能访问 ...
- gateway动态路由_spring-cloud-gateway简介
概述 API网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求.如果让客户端直接与各个微服务通信,会有以下的问题: 客户端 ...
- gateway动态路由_Java如何用Spring Cloud奇淫小技巧 来使用gateway作为服务网管
什么是网关 在微服务架构里,服务的粒度被进一步细分,各个业务服务可以被独立的设计.开发.测试.部署和管理.这时,各个独立部署单元可以用不同的开发测试团队维护,可以使用不同的编程语言和技术平台进行设计, ...
- SpringCloud 微服务网关Gateway 动态路由配置
概述:在上一章节<SpringCloud 微服务网关Gateway介绍及简单路由配置>中我们讲述了Gateway的最简单的路由配置方式.但是其中比较明显的问题就是我们在配置路由服务的地址时 ...
- 一. spring cloud gateway集成 spring cloud stream binder kafka,实现“动态路由“刷新与加载之采坑记录
一.前言 Spring Cloud Stream是用于构建消息驱动的微服务应用程序的框架. 本文主要介绍如何集成 Spring Cloud Stream,以 Kafka发布订阅模式(topic),实现 ...
最新文章
- 虚拟机(VMware Workstation Pro)安装多台Linux
- 工业级PoE交换机是如何进行工作的?使用中要注意什么?
- python中字符串输出乱码怎么解决_Python字符串的encode与decode研究心得乱码问题解决方法(转)...
- 从MFC与ATL的男女关系说起
- [codeup 1126]看电视
- Amber分子动力学模拟
- Mysql 日历数据表
- Google原生输入法LatinIME词库构建流程分析(一)
- java pgm_java - 如何用Java读取PGM图像? - 堆栈内存溢出
- 业务流程与组织结构优化
- 计算机技能鉴定高级,职业技能鉴定计算机(高级)试题.pdf
- npm启动报错Eorror:ENOENT no such file or directory ‘/node-sass/vender‘
- 平面直角坐标系中的旋转公式_中考难点,旋转+动点的最值问题的构建
- python-mao
- “大学教育的目的”-- 芝加哥大学Andrew Abbott教授的演讲
- 生物学中的云计算和大数据
- 定时多次自动打开关闭网页的bat脚本
- SQLite虚表介绍
- 美国食品药物管理局证实:心脏医疗设备可被黑客入侵
- 站长导航系统源码-修复版
热门文章
- matlab 一维 平滑,MATLAB中数据平滑处理
- 2021年全球及中国区块链投融资及技术专利情况:中国区块链相关注册企业达到9.36万余家,新增专利15985项 [图]
- PR(Premiere)安装插件Aescripts BeatEdit(Beat Edit)后无法打开的解决方案
- 前端之图形学-1 数据可视化
- java单点登录解决方案_N多系统单点登录,实现、解决方案。四种解决方案
- TiDB的设计哲学——Make It Work! Make It Right! Make It Fast!
- 计算机输入什么指令关机,电脑自动关机命令是什么
- 如何在电脑上实现企业微信多开?
- OpenModelica模型导入Simulink运行的方法
- After Effect CC 2019插件