如何实现zuul动态路由
发表于:2024-11-26 作者:千家信息网编辑
千家信息网最后更新 2024年11月26日,本篇内容介绍了"如何实现zuul动态路由"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!zuul动态路
千家信息网最后更新 2024年11月26日如何实现zuul动态路由
本篇内容介绍了"如何实现zuul动态路由"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
zuul动态路由
网关服务是流量的唯一入口。不能随便停服务。所以动态路由就显得尤为必要。
数据库动态路由基于事件刷新机制热修改zuul的路由属性。
DiscoveryClientRouteLocator
可以看到DiscoveryClientRouteLocator 是默认的刷新的核心处理类。
//重新加载路由信息方法 protected方法。需要子方法重新方法。protected LinkedHashMaplocateRoutes() //触发刷新的方法 RefreshableRouteLocator 接口 public void refresh() { this.doRefresh(); }
而这俩个方法都是继承与SimpleRouteLocator 类,并进行了重新操作。其实官方的方法注释说明了。如果需要动态读取加载映射关系。则需要子类重写这俩个方法。 进行具体的实现
首先pom jar包导入 需要连接mysql 数据库
mysql mysql-connector-java org.springframework.boot spring-boot-starter-jdbc
路由实体 ZuulRouteEntity
package com.xian.cloud.entity;import lombok.Data;import java.io.Serializable;import java.util.Date;/** *路由实体类 * * @author xianliru@100tal.com * @version 1.0 * @createDate 2019/10/30 15:00 */@Datapublic class ZuulRouteEntity implements Serializable { private static final long serialVersionUID = 1L; /** * router Id */ private Integer id; /** * 路由路径 */ private String path; /** * 服务名称 */ private String serviceId; /** * url代理 */ private String url; /** * 转发去掉前缀 */ private String stripPrefix; /** * 是否重试 */ private String retryable; /** * 是否启用 */ private String enabled; /** * 敏感请求头 */ private String sensitiveheadersList; /** * 创建时间 */ private Date createTime; /** * 更新时间 */ private Date updateTime; /** * 删除标识(0-正常,1-删除) */ private String delFlag;}
新建DiscoveryRouteLocator 类 父类 接口 都不变化
package com.xian.cloud.router;import com.google.common.base.Strings;import com.google.common.collect.Sets;import com.xian.cloud.entity.ZuulRoute;import lombok.extern.slf4j.Slf4j;import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.util.StringUtils;import java.util.*;/** ** * @author xianliru@100tal.com * @version 1.0 * @createDate 2019/10/30 18:57 */@Slf4jpublic class DiscoveryRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator { private ZuulProperties properties; private JdbcTemplate jdbcTemplate; public DiscoveryRouteLocator(String servletPath, ZuulProperties properties, JdbcTemplate jdbcTemplate) { super(servletPath, properties); this.properties = properties; this.jdbcTemplate = jdbcTemplate; log.info("servletPath:{}",servletPath); } @Override public void refresh() { doRefresh(); } @Override protected Map locateRoutes() { LinkedHashMap routesMap = new LinkedHashMap (); //从配置文件中加载路由信息 routesMap.putAll(super.locateRoutes()); //自定义加载路由信息 routesMap.putAll(getRouteList()); //优化一下配置 LinkedHashMap values = new LinkedHashMap<>(); for (Map.Entry entry : routesMap.entrySet()) { String path = entry.getKey(); // Prepend with slash if not already present. if (!path.startsWith("/")) { path = "/" + path; } if (StringUtils.hasText(this.properties.getPrefix())) { path = this.properties.getPrefix() + path; if (!path.startsWith("/")) { path = "/" + path; } } values.put(path, entry.getValue()); } return values; } /** * 从数据库读取zuul路由规则 * @return */ private LinkedHashMap getRouteList() { LinkedHashMap zuulRoutes = new LinkedHashMap<>(); List sysZuulRoutes = jdbcTemplate.query("select * from sys_zuul_route where del_flag = 0", new BeanPropertyRowMapper<>(ZuulRoute.class)); for (ZuulRoute route: sysZuulRoutes) { // 为空跳过 if (Strings.isNullOrEmpty(route.getPath()) && Strings.isNullOrEmpty(route.getUrl())) { continue; } ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute(); try { zuulRoute.setId(route.getServiceId()); zuulRoute.setPath(route.getPath()); zuulRoute.setServiceId(route.getServiceId()); zuulRoute.setRetryable(Objects.equals("0", route.getRetryable()) ? Boolean.FALSE : Boolean.TRUE); zuulRoute.setStripPrefix(Objects.equals("0", route.getStripPrefix()) ? Boolean.FALSE : Boolean.TRUE); zuulRoute.setUrl(route.getUrl()); List sensitiveHeadersList = Arrays.asList(route.getSensitiveheadersList().split(",")); if (sensitiveHeadersList != null) { Set sensitiveHeaderSet = Sets.newHashSet(); sensitiveHeadersList.forEach(sensitiveHeader -> sensitiveHeaderSet.add(sensitiveHeader)); zuulRoute.setSensitiveHeaders(sensitiveHeaderSet); zuulRoute.setCustomSensitiveHeaders(true); } } catch (Exception e) { log.error("数据库加载配置异常", e); } log.info("自定义的路由配置,path:{},serviceId:{}", zuulRoute.getPath(), zuulRoute.getServiceId()); zuulRoutes.put(zuulRoute.getPath(), zuulRoute); } return zuulRoutes; }}
我们还需要一个事件的生产者 和 消费者 直接图方便 集成到一个类中
package com.xian.cloud.event;import com.xian.cloud.router.DiscoveryRouteLocator;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.discovery.event.HeartbeatEvent;import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent;import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;import org.springframework.context.ApplicationEvent;import org.springframework.context.ApplicationEventPublisher;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.stereotype.Service;/** *路由刷新事件发布,与事件监听者 * * @author xianliru@100tal.com * @version 1.0 * @createDate 2019/10/30 15:27 */@Servicepublic class RefreshRouteService implements ApplicationListener { @Autowired private ZuulHandlerMapping zuulHandlerMapping; private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor(); @Autowired ApplicationEventPublisher publisher; @Autowired private DiscoveryRouteLocator dynamicRouteLocator; /** * 动态路由实现 调用refreshRoute() 发布刷新路由事件 */ public void refreshRoute() { RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(dynamicRouteLocator); publisher.publishEvent(routesRefreshedEvent); } /** * 事件监听者。监控检测事件刷新 * @param event */ @Override public void onApplicationEvent(ApplicationEvent event) { if(event instanceof ContextRefreshedEvent || event instanceof RefreshScopeRefreshedEvent || event instanceof RoutesRefreshedEvent){ //主动手动刷新。上下文刷新,配置属性刷新 zuulHandlerMapping.setDirty(true); }else if(event instanceof HeartbeatEvent){ //心跳触发,将本地映射关系。关联到远程服务上 HeartbeatEvent heartbeatEvent = (HeartbeatEvent)event; if(heartbeatMonitor.update(heartbeatEvent.getValue())){ zuulHandlerMapping.setDirty(true); } } }}
对外提供触发接口
package com.xian.cloud.controller;import com.xian.cloud.event.RefreshRouteService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;/** *手动刷新对外接口 * * @author xianliru@100tal.com * @version 1.0 * @createDate 2019/10/30 20:23 */@RestControllerpublic class RefreshController { @Autowired private RefreshRouteService refreshRouteService; @GetMapping("/refresh") public String refresh() { refreshRouteService.refreshRoute(); return "refresh"; }}
数据库表结构
CREATE TABLE `sys_zuul_route` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'router Id', `path` varchar(255) NOT NULL COMMENT '路由路径', `service_id` varchar(255) NOT NULL COMMENT '服务名称', `url` varchar(255) DEFAULT NULL COMMENT 'url代理', `strip_prefix` char(1) DEFAULT '1' COMMENT '转发去掉前缀', `retryable` char(1) DEFAULT '1' COMMENT '是否重试', `enabled` char(1) DEFAULT '1' COMMENT '是否启用', `sensitiveHeaders_list` varchar(255) DEFAULT NULL COMMENT '敏感请求头', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `del_flag` char(1) DEFAULT '0' COMMENT '删除标识(0-正常,1-删除)', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='动态路由配置表'
将配置文件client 消费者服务 路由配置注释掉。设置数据源。从数据库中读取
启动服务打印日志
2019-10-30 20:49:39.946 INFO 63449 --- [TaskScheduler-1] c.xian.cloud.router.DynamicRouteLocator : 添加数据库自定义的路由配置,path:/client/**,serviceId:cloud-discovery-client2019-10-30 20:49:40.397 INFO 63449 --- [TaskScheduler-1] c.xian.cloud.router.DynamicRouteLocator : 添加数据库自定义的路由配置,path:/client/**,serviceId:cloud-discovery-client
postman 请求client 接口 看看是否能转发成功
基于zuul 动态网关路由完成。
"如何实现zuul动态路由"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
路由
配置
动态
数据
数据库
方法
事件
服务
接口
时间
信息
内容
前缀
名称
实体
属性
手动
文件
更多
标识
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
护苗网络安全系列课堂二
软件开发人员语言
数据库回滚命令
nom数据库
mc怎么使服务器卡崩
软件开发的工程量如何计算
中日免上互联网科技有限公司
石家庄智友软件开发公司
软件开发哪个最赚钱
小行星数据库浏览器官网
典型的RUP软件开发过程
杨浦区一站式软件开发供应商
解压显示服务器繁忙
嵌入式软件开发成本定价
西峡网络安全
超市系统数据库连接失败
使命召唤手游的服务器在哪个城市
宽德资本软件开发笔试
辽宁省视频会议服务器虚拟主机
网络技术基础代谢1300
quartz 操作数据库
数据库中的核心
livedb数据库
aap软件开发构架建设
宝塔面板 数据库 表损坏
机关网络安全队伍建设
网络安全和数据安全的区别
央行互联网金融科技
天下票仓网络技术企查查
咪咪扑克软件开发商